diff mbox series

usb: typec: tcpm: fix double-free issue in tcpm_port_unregister_pd()

Message ID 20240311065219.777037-1-xu.yang_2@nxp.com
State New
Headers show
Series usb: typec: tcpm: fix double-free issue in tcpm_port_unregister_pd() | expand

Commit Message

Xu Yang March 11, 2024, 6:52 a.m. UTC
When unregister pd capabilitie in tcpm, KASAN will capture below double
-free issue. The root cause is the same capabilitiy will be kfreed twice,
the first time is kfreed by pd_capabilities_release() and the second time
is explicitly kfreed by tcpm_port_unregister_pd().

[    3.988059] BUG: KASAN: double-free in tcpm_port_unregister_pd+0x1a4/0x3dc
[    3.995001] Free of addr ffff0008164d3000 by task kworker/u16:0/10
[    4.001206]
[    4.002712] CPU: 2 PID: 10 Comm: kworker/u16:0 Not tainted 6.8.0-rc5-next-20240220-05616-g52728c567a55 #53
[    4.012402] Hardware name: Freescale i.MX8QXP MEK (DT)
[    4.017569] Workqueue: events_unbound deferred_probe_work_func
[    4.023456] Call trace:
[    4.025920]  dump_backtrace+0x94/0xec
[    4.029629]  show_stack+0x18/0x24
[    4.032974]  dump_stack_lvl+0x78/0x90
[    4.036675]  print_report+0xfc/0x5c0
[    4.040289]  kasan_report_invalid_free+0xa0/0xc0
[    4.044937]  __kasan_slab_free+0x124/0x154
[    4.049072]  kfree+0xb4/0x1e8
[    4.052069]  tcpm_port_unregister_pd+0x1a4/0x3dc
[    4.056725]  tcpm_register_port+0x1dd0/0x2558
[    4.061121]  tcpci_register_port+0x420/0x71c
[    4.065430]  tcpci_probe+0x118/0x2e0

To fix the issue, this will remove kree() from tcpm_port_unregister_pd().

Fixes: cd099cde4ed2 ("usb: typec: tcpm: Support multiple capabilities")
cc: <stable@vger.kernel.org>
Suggested-by: Aisheng Dong <aisheng.dong@nxp.com>
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
 drivers/usb/typec/tcpm/tcpm.c | 2 --
 1 file changed, 2 deletions(-)

Comments

Heikki Krogerus March 12, 2024, 10:24 a.m. UTC | #1
On Mon, Mar 11, 2024 at 02:52:19PM +0800, Xu Yang wrote:
> When unregister pd capabilitie in tcpm, KASAN will capture below double
> -free issue. The root cause is the same capabilitiy will be kfreed twice,
> the first time is kfreed by pd_capabilities_release() and the second time
> is explicitly kfreed by tcpm_port_unregister_pd().
> 
> [    3.988059] BUG: KASAN: double-free in tcpm_port_unregister_pd+0x1a4/0x3dc
> [    3.995001] Free of addr ffff0008164d3000 by task kworker/u16:0/10
> [    4.001206]
> [    4.002712] CPU: 2 PID: 10 Comm: kworker/u16:0 Not tainted 6.8.0-rc5-next-20240220-05616-g52728c567a55 #53
> [    4.012402] Hardware name: Freescale i.MX8QXP MEK (DT)
> [    4.017569] Workqueue: events_unbound deferred_probe_work_func
> [    4.023456] Call trace:
> [    4.025920]  dump_backtrace+0x94/0xec
> [    4.029629]  show_stack+0x18/0x24
> [    4.032974]  dump_stack_lvl+0x78/0x90
> [    4.036675]  print_report+0xfc/0x5c0
> [    4.040289]  kasan_report_invalid_free+0xa0/0xc0
> [    4.044937]  __kasan_slab_free+0x124/0x154
> [    4.049072]  kfree+0xb4/0x1e8
> [    4.052069]  tcpm_port_unregister_pd+0x1a4/0x3dc
> [    4.056725]  tcpm_register_port+0x1dd0/0x2558
> [    4.061121]  tcpci_register_port+0x420/0x71c
> [    4.065430]  tcpci_probe+0x118/0x2e0
> 
> To fix the issue, this will remove kree() from tcpm_port_unregister_pd().
> 
> Fixes: cd099cde4ed2 ("usb: typec: tcpm: Support multiple capabilities")
> cc: <stable@vger.kernel.org>
> Suggested-by: Aisheng Dong <aisheng.dong@nxp.com>
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>

Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
>  drivers/usb/typec/tcpm/tcpm.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index 3d505614bff1..afbb0d832db2 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -6940,9 +6940,7 @@ static void tcpm_port_unregister_pd(struct tcpm_port *port)
>  	port->port_source_caps = NULL;
>  	for (i = 0; i < port->pd_count; i++) {
>  		usb_power_delivery_unregister_capabilities(port->pd_list[i]->sink_cap);
> -		kfree(port->pd_list[i]->sink_cap);
>  		usb_power_delivery_unregister_capabilities(port->pd_list[i]->source_cap);
> -		kfree(port->pd_list[i]->source_cap);
>  		devm_kfree(port->dev, port->pd_list[i]);
>  		port->pd_list[i] = NULL;
>  		usb_power_delivery_unregister(port->pds[i]);
> -- 
> 2.34.1
diff mbox series

Patch

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 3d505614bff1..afbb0d832db2 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -6940,9 +6940,7 @@  static void tcpm_port_unregister_pd(struct tcpm_port *port)
 	port->port_source_caps = NULL;
 	for (i = 0; i < port->pd_count; i++) {
 		usb_power_delivery_unregister_capabilities(port->pd_list[i]->sink_cap);
-		kfree(port->pd_list[i]->sink_cap);
 		usb_power_delivery_unregister_capabilities(port->pd_list[i]->source_cap);
-		kfree(port->pd_list[i]->source_cap);
 		devm_kfree(port->dev, port->pd_list[i]);
 		port->pd_list[i] = NULL;
 		usb_power_delivery_unregister(port->pds[i]);