Linux: thunderbolt: Fix KASAN reported use-after-free when request is canceled
What fixes it
- 71b3c517e02af2c46ad58d4b3706b7c3cb24936dLinuxCVE List
- 08287212b622039212c972806f896f078dfd28e2LinuxCVE List
A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.
Description
In the Linux kernel, the following vulnerability has been resolved:
thunderbolt: Fix KASAN reported use-after-free when request is canceled
Alan reported that when doing stress testing sometimes KASAN notices use-after-free during control channel operation (stripped down keeping the relevant parts):
BUG: KASAN: slab-use-after-free in tb_cfg_request_sync+0x240/0x250 [thunderbolt] Read of size 24 at addr ffff88811067f290 by task kworker/u40:2/1760 <TASK> tb_cfg_request_sync+0x240/0x250 [thunderbolt] tb_cfg_read_raw+0x367/0x510 [thunderbolt] tb_cfg_read+0xec/0x240 [thunderbolt] tb_port_get_link_generation+0x258/0x420 [thunderbolt] tb_usb3_consumed_bandwidth+0x1c1/0x2c0 [thunderbolt] tb_tunnel_consumed_bandwidth+0xfd/0x910 [thunderbolt] tb_available_bandwidth+0x5f2/0xeb0 [thunderbolt] tb_recalc_estimated_bandwidth+0x2a0/0x1bc0 [thunderbolt] tb_handle_dp_bandwidth_request+0x1897/0x5e20 [thunderbolt] process_one_work+0x675/0x1230 worker_thread+0x5e6/0xf70 kthread+0x365/0x470 ret_from_fork+0x54d/0x710 ret_from_fork_asm+0x1a/0x30 </TASK>
Allocated by task 1760: __kmalloc_cache_noprof+0x1ee/0x550 tb_cfg_read_raw+0x1d3/0x510 [thunderbolt] tb_cfg_read+0xec/0x240 [thunderbolt] tb_port_get_link_generation+0x258/0x420 [thunderbolt] tb_usb3_consumed_bandwidth+0x1c1/0x2c0 [thunderbolt] tb_tunnel_consumed_bandwidth+0xfd/0x910 [thunderbolt] tb_available_bandwidth+0x5f2/0xeb0 [thunderbolt] tb_recalc_estimated_bandwidth+0x2a0/0x1bc0 [thunderbolt] tb_handle_dp_bandwidth_request+0x1897/0x5e20 [thunderbolt] process_one_work+0x675/0x1230 worker_thread+0x5e6/0xf70 kthread+0x365/0x470 ret_from_fork+0x54d/0x710 ret_from_fork_asm+0x1a/0x30
Freed by task 926: kfree+0x18f/0x4a0 tb_cfg_request_put+0xb7/0xe0 [thunderbolt] tb_cfg_request_work+0x82/0x120 [thunderbolt] process_one_work+0x675/0x1230 worker_thread+0x5e6/0xf70 kthread+0x365/0x470 ret_from_fork+0x54d/0x710 ret_from_fork_asm+0x1a/0x30
Second to last potentially related work creation: __queue_work+0x575/0xd00 queue_work_on+0x77/0x80 tb_cfg_request_cancel+0xc7/0x260 [thunderbolt] tb_cfg_request_sync+0x1f6/0x250 [thunderbolt] tb_cfg_read_raw+0x367/0x510 [thunderbolt] tb_cfg_read+0xec/0x240 [thunderbolt] tb_port_get_link_generation+0x258/0x420 [thunderbolt] tb_usb3_consumed_bandwidth+0x1c1/0x2c0 [thunderbolt] tb_tunnel_consumed_bandwidth+0xfd/0x910 [thunderbolt] tb_available_bandwidth+0x5f2/0xeb0 [thunderbolt] tb_recalc_estimated_bandwidth+0x2a0/0x1bc0 [thunderbolt] tb_handle_dp_bandwidth_request+0x1897/0x5e20 [thunderbolt] process_one_work+0x675/0x1230 worker_thread+0x5e6/0xf70 kthread+0x365/0x470 ret_from_fork+0x54d/0x710 ret_from_fork_asm+0x1a/0x30
The last stack trace is helpful because it shows that we are cancelling a request and looking at tb_cfg_request_cancel() what might happen is that tb_cfg_request_work() completes right before tb_cfg_request_cancel() starts and because of this it will call schedule_work() queueing the same work to run again. However, it is already removed from the request_queue and reference count is dropped so when tb_cfg_request_work() triggers again it will access memory that is already released.
Fix this so that we first make sure a cancelled request is not handed away from tb_cfg_request_find() or scheduled to run. Then instead of relying on the worker to clean up the request we will do it in tb_cfg_request_cancel() after the work is canceled from running. Make tb_cfg_request_dequeue() release the request only if it was actually removed from the queue.
Text from CVE List
Affected versions 12
- Linuxaffected: d7f781bfdbf4eb7c5706c9974b8bf6d3c82e69c1 before b70b9c41f240c42bf6e728034537c0fe60c16ef4CVE List
- Linuxaffected: d7f781bfdbf4eb7c5706c9974b8bf6d3c82e69c1 before 71b3c517e02af2c46ad58d4b3706b7c3cb24936dCVE List
- Linuxaffected: d7f781bfdbf4eb7c5706c9974b8bf6d3c82e69c1 before f18faa3d3b810d60a3005ae1b1d1866faa67d343CVE List
- Linuxaffected: d7f781bfdbf4eb7c5706c9974b8bf6d3c82e69c1 before 08287212b622039212c972806f896f078dfd28e2CVE List
- Linuxaffected: d7f781bfdbf4eb7c5706c9974b8bf6d3c82e69c1 before a02188ddc24b7872f0c5e0c5873f827318717803CVE List
- Linuxaffected: 4.13CVE List
- Linuxunaffected: all versions before 4.13CVE List
- Linuxunaffected: 6.6.160 through 6.6.*CVE List
- Linuxunaffected: 6.12.113 through 6.12.*CVE List
- Linuxunaffected: 6.18.56 through 6.18.*CVE List
- Linuxunaffected: 7.2.10 through 7.2.*CVE List
- Linuxunaffected: 7.3CVE List
References 5
- git.kernel.org/stable/c/b70b9c41f240c42bf6e728034537c0fe60c16ef4Referencevia CVE List
- git.kernel.org/stable/c/71b3c517e02af2c46ad58d4b3706b7c3cb24936dReferencevia CVE List
- git.kernel.org/stable/c/f18faa3d3b810d60a3005ae1b1d1866faa67d343Referencevia CVE List
- git.kernel.org/stable/c/08287212b622039212c972806f896f078dfd28e2Referencevia CVE List
- git.kernel.org/stable/c/a02188ddc24b7872f0c5e0c5873f827318717803Referencevia CVE List