Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2d7c0bf authored by Jack Pham's avatar Jack Pham Committed by Gerrit - the friendly Code Review server
Browse files

usb: pd: Fix memory leak in usbpd_create()



In both the usbpd_create() failure path and usbpd_destroy(),
some associated allocations, namely the string allocated from
dev_set_name() as well as the resource-mananaged dual_role_instance
structure were not getting freed. These were detected by kmemleak.

unreferenced object 0xffffffe158c37c80 (size 128):
  comm "kworker/6:1", pid 198, jiffies 4294938493 (age 469.090s)
  hex dump (first 32 bytes):
    75 73 62 70 64 30 00 6b 6b 6b 6b 6b 6b 6b 6b 6b  usbpd0.kkkkkkkkk
    6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
  backtrace:
    [<ffffff894d897f38>] kmemleak_alloc+0x60/0xc0
    [<ffffff894ca3ca98>] __kmalloc_track_caller+0x220/0x3bc
    [<ffffff894cc12d00>] kvasprintf+0x80/0x10c
    [<ffffff894cc12dfc>] kvasprintf_const+0x70/0xe4
    [<ffffff894d8892d8>] kobject_set_name_vargs+0x5c/0xe8
    [<ffffff894cf3afdc>] dev_set_name+0x84/0xb0
    [<ffffff894d16aa6c>] usbpd_create+0x84/0x700
    [<ffffff894d172d14>] pdphy_probe+0x21c/0x2ec
    [<ffffff894cf42d88>] platform_drv_probe+0x5c/0xb0
    [<ffffff894cf40208>] driver_probe_device+0x2e8/0x41c
    [<ffffff894cf40c80>] __device_attach_driver+0xcc/0x144
    [<ffffff894cf3e374>] bus_for_each_drv+0x80/0xc8
    [<ffffff894cf40464>] __device_attach+0xa4/0x154
    [<ffffff894cf40534>] device_initial_probe+0x20/0x2c
    [<ffffff894cf3e518>] bus_probe_device+0x34/0x8c
    [<ffffff894cf40a1c>] deferred_probe_work_func+0xcc/0x16c

unreferenced object 0xffffffe158c00580 (size 128):
  comm "kworker/6:1", pid 198, jiffies 4294938493 (age 469.090s)
  hex dump (first 32 bytes):
    78 5d c9 58 e1 ff ff ff 78 5d c9 58 e1 ff ff ff  x].X....x].X....
    24 ef 0c 4d 89 ff ff ff 80 b0 3a 59 e1 ff ff ff  $..M......:Y....
  backtrace:
    [<ffffff894d897f38>] kmemleak_alloc+0x60/0xc0
    [<ffffff894ca3ca98>] __kmalloc_track_caller+0x220/0x3bc
    [<ffffff894cf44198>] devres_alloc_node+0x34/0x70
    [<ffffff894d0cedec>] devm_dual_role_instance_register+0x40/0x178
    [<ffffff894d16af6c>] usbpd_create+0x584/0x700
    [<ffffff894d172d14>] pdphy_probe+0x21c/0x2ec
    [<ffffff894cf42d88>] platform_drv_probe+0x5c/0xb0
    [<ffffff894cf40208>] driver_probe_device+0x2e8/0x41c
    [<ffffff894cf40c80>] __device_attach_driver+0xcc/0x144
    [<ffffff894cf3e374>] bus_for_each_drv+0x80/0xc8
    [<ffffff894cf40464>] __device_attach+0xa4/0x154
    [<ffffff894cf40534>] device_initial_probe+0x20/0x2c
    [<ffffff894cf3e518>] bus_probe_device+0x34/0x8c
    [<ffffff894cf40a1c>] deferred_probe_work_func+0xcc/0x16c
    [<ffffff894c8d1c64>] process_one_work+0x1c0/0x3d4
    [<ffffff894c8d19a4>] process_scheduled_works+0x28/0x40

Both of these can be fixed by making sure to use put_device()
instead of simply kfree(pd), as that will make sure to call
additional cleanup routines for the associated objects.

Change-Id: Id755ddef66308c7d10217b2b8ef56c47421188a5
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 712e7c39
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -4254,6 +4254,13 @@ struct usbpd *devm_usbpd_get_by_phandle(struct device *dev, const char *phandle)
}
EXPORT_SYMBOL(devm_usbpd_get_by_phandle);

static void usbpd_release(struct device *dev)
{
	struct usbpd *pd = container_of(dev, struct usbpd, dev);

	kfree(pd);
}

static int num_pd_instances;

/**
@@ -4278,6 +4285,7 @@ struct usbpd *usbpd_create(struct device *parent)
	device_initialize(&pd->dev);
	pd->dev.class = &usbpd_class;
	pd->dev.parent = parent;
	pd->dev.release = usbpd_release;
	dev_set_drvdata(&pd->dev, pd);

	ret = dev_set_name(&pd->dev, "usbpd%d", num_pd_instances++);
@@ -4435,7 +4443,7 @@ struct usbpd *usbpd_create(struct device *parent)
	device_del(&pd->dev);
free_pd:
	num_pd_instances--;
	kfree(pd);
	put_device(&pd->dev);
	return ERR_PTR(ret);
}
EXPORT_SYMBOL(usbpd_create);
@@ -4453,8 +4461,7 @@ void usbpd_destroy(struct usbpd *pd)
	power_supply_unreg_notifier(&pd->psy_nb);
	power_supply_put(pd->usb_psy);
	destroy_workqueue(pd->wq);
	device_del(&pd->dev);
	kfree(pd);
	device_unregister(&pd->dev);
}
EXPORT_SYMBOL(usbpd_destroy);