Char: virtio_console, fix memory leak
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>
This commit is contained in:
parent
7ae4b866f8
commit
22e132ff26
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue