Message ID | be0003e5-d8e0-bff6-2205-7e88270ba2b4@users.sourceforge.net (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Sep 20, 2017 at 02:40:28PM +0200, SF Markus Elfring wrote: > From: Markus Elfring <elfring@users.sourceforge.net> > Date: Wed, 20 Sep 2017 14:30:55 +0200 > > Add a jump target so that a bit of exception handling can be better > reused at the end of this function. > > This refactoring might fix also an error situation where the > function "kfree" was not called after a software failure > was noticed in two cases. > No. It doesn't fix a leak, it introduces a double free. If smscore_register_device() succeeds then mdev is freed when we call smsusb_term_device(intf); The call tree is: smsusb_term_device() -> smscore_unregister_device() -> smscore_notify_clients() -> smsdvb_onremove() -> smsdvb_unregister_client() -> smsdvb_media_device_unregister() -> kfree(coredev->media_dev); regards, dan carpenter
> If smscore_register_device() succeeds then mdev is freed when we call > smsusb_term_device(intf); The call tree is: Thanks for your constructive information. How do you think about another implementation detail in this function then? May the statement “kfree(mdev);” be executed before “smsusb_term_device(intf);” in one if branch? Regards, Markus
diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 8c1f926567ec..b8e7b05cf6d0 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -458,12 +458,10 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) rc = smscore_register_device(¶ms, &dev->coredev, mdev); if (rc < 0) { pr_err("smscore_register_device(...) failed, rc %d\n", rc); - smsusb_term_device(intf); #ifdef CONFIG_MEDIA_CONTROLLER_DVB media_device_unregister(mdev); #endif - kfree(mdev); - return rc; + goto terminate_device; } smscore_set_board_id(dev->coredev, board_id); @@ -480,8 +478,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) rc = smsusb_start_streaming(dev); if (rc < 0) { pr_err("smsusb_start_streaming(...) failed\n"); - smsusb_term_device(intf); - return rc; + goto terminate_device; } dev->state = SMSUSB_ACTIVE; @@ -489,13 +486,17 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) rc = smscore_start_device(dev->coredev); if (rc < 0) { pr_err("smscore_start_device(...) failed\n"); - smsusb_term_device(intf); - return rc; + goto terminate_device; } pr_debug("device 0x%p created\n", dev); return rc; + +terminate_device: + smsusb_term_device(intf); + kfree(mdev); + return rc; } static int smsusb_probe(struct usb_interface *intf,