Linux: tracing: Undo the registration when enabling the histogram trigger fails
What fixes it
- 880712b6f48103ba3a04b154ff076d45fe86dcecLinuxCVE List
- 51b07104d563d4be2be34158d3b9d922ca417642LinuxCVE List
- 92383cef66791a0c63a2f27755cadbdb2fbf270bLinuxCVE 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:
tracing: Undo the registration when enabling the histogram trigger fails
Commit 6f86bdeab633 ("tracing: Fix bad hist from corrupting named_triggers list") described how a trigger that is registered but not on file->triggers ends up freed while still on the global named_triggers list, and moved the registration down so that hist_trigger_enable() follows it immediately. One path still gets there. hist_trigger_enable() adds the trigger and takes it straight back out when the event cannot be enabled:
list_add_tail_rcu(&data->list, &file->triggers);
update_cond_flag(file);
if (trace_event_trigger_enable_disable(file, 1) < 0) { list_del_rcu(&data->list); update_cond_flag(file); ret--; }
so the list walk in hist_unregister_trigger() matches nothing, test stays NULL, and the ->free() that would call del_named_trigger() is skipped. out_unreg falls through to out_free, which frees the trigger anyway:
BUG: KASAN: slab-use-after-free in find_named_trigger+0xac/0xc0 Read of size 8 at addr ffff8880091d3160 by task init/1 find_named_trigger+0xac/0xc0 hist_register_trigger+0xc1/0xa00 event_hist_trigger_parse+0x3146/0x6af0 event_trigger_write+0xce/0x160 Freed by task 69: kfree+0x154/0x420 trigger_kthread_fn+0xfd/0x160
Leave the trigger where hist_unregister_trigger() can find it and let that undo the registration, which is the only code that knows all of what cmd_ops->init() took: the named list entry, the hist_pad reference, the reference on the trigger a named histogram is shared with, and the copied cmd_ops. It also pairs the failed trace_event_trigger_enable_disable(), whose sm_ref and buffered event reference are otherwise left behind.
Since ->free() releases trigger_data and, for a trigger that does not share its histogram, hist_data with it, out_unreg can no longer fall through to out_free. For a trigger that does share, hist_register_trigger() has already destroyed the caller's hist_data, so the fall-through was reading freed memory there as well.
Move the enable_timestamps check in hist_unregister_trigger() above the ->free() call for the same reason: hist_data does not outlive it once the trigger being removed is the one that owns it.
Text from CVE List
Affected versions 12
- Linuxaffected: 067fe038e70f6e64960d26a79c4df5f1413d0f13 before 880712b6f48103ba3a04b154ff076d45fe86dcecCVE List
- Linuxaffected: 067fe038e70f6e64960d26a79c4df5f1413d0f13 before c7ee2d5733574d4694f7c0035e4381f54c1fca27CVE List
- Linuxaffected: 067fe038e70f6e64960d26a79c4df5f1413d0f13 before 51b07104d563d4be2be34158d3b9d922ca417642CVE List
- Linuxaffected: 067fe038e70f6e64960d26a79c4df5f1413d0f13 before bfa6bc11aef93a3d9db0ac9564b734849a9d959bCVE List
- Linuxaffected: 067fe038e70f6e64960d26a79c4df5f1413d0f13 before 92383cef66791a0c63a2f27755cadbdb2fbf270bCVE List
- Linuxaffected: 4.17CVE List
- Linuxunaffected: all versions before 4.17CVE List
- Linuxunaffected: 6.6.160 through 6.6.*CVE List
- Linuxunaffected: 6.12.112 through 6.12.*CVE List
- Linuxunaffected: 6.18.53 through 6.18.*CVE List
- Linuxunaffected: 7.2.7 through 7.2.*CVE List
- Linuxunaffected: 7.3CVE List
References 5
- git.kernel.org/stable/c/880712b6f48103ba3a04b154ff076d45fe86dcecReferencevia CVE List
- git.kernel.org/stable/c/c7ee2d5733574d4694f7c0035e4381f54c1fca27Referencevia CVE List
- git.kernel.org/stable/c/51b07104d563d4be2be34158d3b9d922ca417642Referencevia CVE List
- git.kernel.org/stable/c/bfa6bc11aef93a3d9db0ac9564b734849a9d959bReferencevia CVE List
- git.kernel.org/stable/c/92383cef66791a0c63a2f27755cadbdb2fbf270bReferencevia CVE List