* [PATCH] KVM: fix memory leak in kvm_io_bus_unregister_dev() @ 2020-08-30 4:34 Rustam Kovhaev 2020-09-01 16:25 ` Vitaly Kuznetsov 0 siblings, 1 reply; 3+ messages in thread From: Rustam Kovhaev @ 2020-08-30 4:34 UTC (permalink / raw) To: pbonzini, kvm; +Cc: linux-kernel, gregkh, Rustam Kovhaev when kmalloc() fails in kvm_io_bus_unregister_dev(), before removing the bus, we should iterate over all other devices linked to it and call kvm_iodevice_destructor() for them Reported-and-tested-by: syzbot+f196caa45793d6374707@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?extid=f196caa45793d6374707 Signed-off-by: Rustam Kovhaev <rkovhaev@gmail.com> --- virt/kvm/kvm_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 67cd0b88a6b6..646aa7b82548 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -4332,7 +4332,7 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, struct kvm_io_device *dev) { - int i; + int i, j; struct kvm_io_bus *new_bus, *bus; bus = kvm_get_bus(kvm, bus_idx); @@ -4351,6 +4351,11 @@ void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, GFP_KERNEL_ACCOUNT); if (!new_bus) { pr_err("kvm: failed to shrink bus, removing it completely\n"); + for (j = 0; j < bus->dev_count; j++) { + if (j == i) + continue; + kvm_iodevice_destructor(bus->range[j].dev); + } goto broken; } -- 2.28.0 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] KVM: fix memory leak in kvm_io_bus_unregister_dev() 2020-08-30 4:34 [PATCH] KVM: fix memory leak in kvm_io_bus_unregister_dev() Rustam Kovhaev @ 2020-09-01 16:25 ` Vitaly Kuznetsov 2020-09-01 22:45 ` Rustam Kovhaev 0 siblings, 1 reply; 3+ messages in thread From: Vitaly Kuznetsov @ 2020-09-01 16:25 UTC (permalink / raw) To: Rustam Kovhaev; +Cc: linux-kernel, gregkh, pbonzini, kvm Rustam Kovhaev <rkovhaev@gmail.com> writes: > when kmalloc() fails in kvm_io_bus_unregister_dev(), before removing > the bus, we should iterate over all other devices linked to it and call > kvm_iodevice_destructor() for them > > Reported-and-tested-by: syzbot+f196caa45793d6374707@syzkaller.appspotmail.com > Link: https://syzkaller.appspot.com/bug?extid=f196caa45793d6374707 > Signed-off-by: Rustam Kovhaev <rkovhaev@gmail.com> > --- > virt/kvm/kvm_main.c | 7 ++++++- > 1 file changed, 6 insertions(+), 1 deletion(-) > > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index 67cd0b88a6b6..646aa7b82548 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -4332,7 +4332,7 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, > void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, > struct kvm_io_device *dev) > { > - int i; > + int i, j; > struct kvm_io_bus *new_bus, *bus; > > bus = kvm_get_bus(kvm, bus_idx); > @@ -4351,6 +4351,11 @@ void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, > GFP_KERNEL_ACCOUNT); > if (!new_bus) { ^^^ redundant space > pr_err("kvm: failed to shrink bus, removing it completely\n"); > + for (j = 0; j < bus->dev_count; j++) { > + if (j == i) > + continue; > + kvm_iodevice_destructor(bus->range[j].dev); > + } > goto broken; The name of the label is really misleading (as it is not actually a failure path), I'd even suggest we get rid of this goto completely, something like new_bus = kmalloc(struct_size(bus, range, bus->dev_count - 1), GFP_KERNEL_ACCOUNT); if (new_bus) { memcpy(new_bus, bus, sizeof(*bus) + i * sizeof(struct kvm_io_range)); new_bus->dev_count--; memcpy(new_bus->range + i, bus->range + i + 1, (new_bus->dev_count - i) * sizeof(struct kvm_io_range)); } else { pr_err("kvm: failed to shrink bus, removing it completely\n"); for (j = 0; j < bus->dev_count; j++) { if (j == i) continue; kvm_iodevice_destructor(bus->range[j].dev); } rcu_assign_pointer(kvm->buses[bus_idx], new_bus); synchronize_srcu_expedited(&kvm->srcu); kfree(bus); return; > } None of the above should block the fix IMO, so: Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com> -- Vitaly ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] KVM: fix memory leak in kvm_io_bus_unregister_dev() 2020-09-01 16:25 ` Vitaly Kuznetsov @ 2020-09-01 22:45 ` Rustam Kovhaev 0 siblings, 0 replies; 3+ messages in thread From: Rustam Kovhaev @ 2020-09-01 22:45 UTC (permalink / raw) To: Vitaly Kuznetsov; +Cc: linux-kernel, gregkh, pbonzini, kvm On Tue, Sep 01, 2020 at 06:25:42PM +0200, Vitaly Kuznetsov wrote: > Rustam Kovhaev <rkovhaev@gmail.com> writes: > > > when kmalloc() fails in kvm_io_bus_unregister_dev(), before removing > > the bus, we should iterate over all other devices linked to it and call > > kvm_iodevice_destructor() for them > > > > Reported-and-tested-by: syzbot+f196caa45793d6374707@syzkaller.appspotmail.com > > Link: https://syzkaller.appspot.com/bug?extid=f196caa45793d6374707 > > Signed-off-by: Rustam Kovhaev <rkovhaev@gmail.com> > > --- > > virt/kvm/kvm_main.c | 7 ++++++- > > 1 file changed, 6 insertions(+), 1 deletion(-) > > > > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > > index 67cd0b88a6b6..646aa7b82548 100644 > > --- a/virt/kvm/kvm_main.c > > +++ b/virt/kvm/kvm_main.c > > @@ -4332,7 +4332,7 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, > > void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, > > struct kvm_io_device *dev) > > { > > - int i; > > + int i, j; > > struct kvm_io_bus *new_bus, *bus; > > > > bus = kvm_get_bus(kvm, bus_idx); > > @@ -4351,6 +4351,11 @@ void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, > > GFP_KERNEL_ACCOUNT); > > if (!new_bus) { > ^^^ redundant space > > > pr_err("kvm: failed to shrink bus, removing it completely\n"); > > + for (j = 0; j < bus->dev_count; j++) { > > + if (j == i) > > + continue; > > + kvm_iodevice_destructor(bus->range[j].dev); > > + } > > goto broken; > > The name of the label is really misleading (as it is not actually a > failure path), I'd even suggest we get rid of this goto completely, > something like > > new_bus = kmalloc(struct_size(bus, range, bus->dev_count - 1), > GFP_KERNEL_ACCOUNT); > if (new_bus) { > memcpy(new_bus, bus, sizeof(*bus) + i * sizeof(struct kvm_io_range)); > new_bus->dev_count--; > memcpy(new_bus->range + i, bus->range + i + 1, > (new_bus->dev_count - i) * sizeof(struct kvm_io_range)); > } else { > pr_err("kvm: failed to shrink bus, removing it completely\n"); > for (j = 0; j < bus->dev_count; j++) { > if (j == i) > continue; > kvm_iodevice_destructor(bus->range[j].dev); > } > > rcu_assign_pointer(kvm->buses[bus_idx], new_bus); > synchronize_srcu_expedited(&kvm->srcu); > kfree(bus); > return; > > > > } > > None of the above should block the fix IMO, so: > > Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com> > > -- > Vitaly > hi Vitaly, thank you for the review! i'll send the new patch ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-09-01 22:44 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-08-30 4:34 [PATCH] KVM: fix memory leak in kvm_io_bus_unregister_dev() Rustam Kovhaev 2020-09-01 16:25 ` Vitaly Kuznetsov 2020-09-01 22:45 ` Rustam Kovhaev
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox