Hi PrasannaKumar, On Sun, Oct 18, 2026 at 10:30:08PM +0530, PrasannaKumar Muralidharan wrote: > Hi Thorsten, > > On Fri, 16 Oct 2026 at 16:16, Thorsten Blum <[email protected]> wrote: > > > > remove_common() frees the driver data during freeze, but does not clear > > vdev->priv, which points to freed memory. If probe_common() then fails > > during restore, a later remove or freeze can dereference the dangling > > pointer. > > > > Clear vdev->priv on the probe_common() error cleanup path and before > > freeing the driver data in remove_common(). Also reset the device and > > return early from remove_common() if vdev->priv is already NULL for a > > safe teardown after a failed restore. > > > > Fixes: 08e53fbdb85c ("virtio-rng: support multiple virtio-rng devices") > > Cc: [email protected] > > Signed-off-by: Thorsten Blum <[email protected]> > > --- > > drivers/char/hw_random/virtio-rng.c | 7 +++++++ > > 1 file changed, 7 insertions(+) > > > > diff --git a/drivers/char/hw_random/virtio-rng.c > > b/drivers/char/hw_random/virtio-rng.c > > index 5e83ffa105e4..a9ff520975a7 100644 > > --- a/drivers/char/hw_random/virtio-rng.c > > +++ b/drivers/char/hw_random/virtio-rng.c > > @@ -190,6 +190,7 @@ static int probe_common(struct virtio_device *vdev) > > err_find: > > ida_free(&rng_index_ida, index); > > err_ida: > > + vdev->priv = NULL; > > kfree(vi); > > return err; > > } > > @@ -198,6 +199,11 @@ static void remove_common(struct virtio_device *vdev) > > { > > struct virtrng_info *vi = vdev->priv; > > > > + if (!vi) { > > + virtio_reset_device(vdev); > > + return; > > + } > > + > > The virtio_reset_device() is always called before setting vdev->priv > to NULL. So the virtio device is already quiesced, no need to do early > return. Isn't it?
The check is still needed. For example, during hibernation or suspend, .freeze (virtrng_freeze() -> remove_common()) frees vi and sets vdev->priv to NULL. On resume, .restore (virtrng_restore()) calls probe_common(), which could fail and leave vdev->priv NULL. A later .freeze or .remove calls remove_common() again, which would dereference NULL without the check. Best regards, Thorsten

