Skip to content

Commit

Permalink
Char: virtio_console, fix memory leak
Browse files Browse the repository at this point in the history
Stanse found that in init_vqs, memory is leaked under certain
circumstanses (the fail path order is incorrect). Fix that by checking
allocations in one turn and free all of them at once if some fails
(some may be NULL, but this is OK).

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Amit Shah <amit.shah@redhat.com>
Cc: virtualization@lists.linux-foundation.org
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
Jiri Slaby authored and Rusty Russell committed Nov 24, 2010
1 parent 7ae4b86 commit 22e132f
Showing 1 changed file with 9 additions and 28 deletions.
37 changes: 9 additions & 28 deletions drivers/char/virtio_console.c
Original file line number Diff line number Diff line change
Expand Up @@ -1547,31 +1547,16 @@ static int init_vqs(struct ports_device *portdev)
nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2;

vqs = kmalloc(nr_queues * sizeof(struct virtqueue *), GFP_KERNEL);
if (!vqs) {
err = -ENOMEM;
goto fail;
}
io_callbacks = kmalloc(nr_queues * sizeof(vq_callback_t *), GFP_KERNEL);
if (!io_callbacks) {
err = -ENOMEM;
goto free_vqs;
}
io_names = kmalloc(nr_queues * sizeof(char *), GFP_KERNEL);
if (!io_names) {
err = -ENOMEM;
goto free_callbacks;
}
portdev->in_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
GFP_KERNEL);
if (!portdev->in_vqs) {
err = -ENOMEM;
goto free_names;
}
portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
GFP_KERNEL);
if (!portdev->out_vqs) {
if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs ||
!portdev->out_vqs) {
err = -ENOMEM;
goto free_invqs;
goto free;
}

/*
Expand Down Expand Up @@ -1605,7 +1590,7 @@ static int init_vqs(struct ports_device *portdev)
io_callbacks,
(const char **)io_names);
if (err)
goto free_outvqs;
goto free;

j = 0;
portdev->in_vqs[0] = vqs[0];
Expand All @@ -1621,23 +1606,19 @@ static int init_vqs(struct ports_device *portdev)
portdev->out_vqs[i] = vqs[j + 1];
}
}
kfree(io_callbacks);
kfree(io_names);
kfree(io_callbacks);
kfree(vqs);

return 0;

free_names:
kfree(io_names);
free_callbacks:
kfree(io_callbacks);
free_outvqs:
free:
kfree(portdev->out_vqs);
free_invqs:
kfree(portdev->in_vqs);
free_vqs:
kfree(io_names);
kfree(io_callbacks);
kfree(vqs);
fail:

return err;
}

Expand Down

0 comments on commit 22e132f

Please sign in to comment.