{"id":33325,"date":"2026-10-06T20:31:46","date_gmt":"2026-10-06T12:31:46","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-98256"},"modified":"2026-10-06T20:31:46","modified_gmt":"2026-10-06T12:31:46","slug":"cve-2026-98256","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-98256","title":{"rendered":"CVE-2026-98256 &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nsignal: Prevent exec("},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>signal: Prevent exec() race<\/p>\n<p>Hyunwoo debugged the following KASAN UAF splat:<\/p>\n<p>  BUG: KASAN: slab-use-after-free in __send_signal_locked+0xb27\/0xba0<br \/>\n  Write of size 8 at addr ffff888007ed80c8 by task poc\/79<br \/>\n  &#8230;<br \/>\n  Call Trace:<br \/>\n   __send_signal_locked+0xb27\/0xba0<br \/>\n   do_send_sig_info+0xa7\/0x160<br \/>\n   do_send_specific+0x76\/0xa0<br \/>\n   __x64_sys_tgkill+0x193\/0x270<br \/>\n  &#8230;<br \/>\n  Allocated by task 80:<br \/>\n   do_timer_create+0x1a4\/0x1030<br \/>\n   __x64_sys_timer_create+0x145\/0x190<br \/>\n  &#8230;<br \/>\n  Freed by task 12:<br \/>\n   kmem_cache_free_bulk+0x1f8\/0x4a0<br \/>\n   kvfree_rcu_bulk+0x14f\/0x1c0<br \/>\n   kfree_rcu_work+0x128\/0x1a0<br \/>\n  &#8230;<br \/>\n  Last potentially related work creation:<br \/>\n   kvfree_call_rcu+0x39\/0x390<br \/>\n   __flush_itimer_signals+0x211\/0x320<br \/>\n   flush_itimer_signals+0x47\/0x90<br \/>\n   begin_new_exec+0xa6b\/0x28c0<\/p>\n<p>It turned out that this happens with a non-leader exec() as Hyunwoo<br \/>\nexplained:<\/p>\n<p>de_thread() calls exchange_tids() before release_task(leader), so the<br \/>\nstruct pid held by a SIGEV_THREAD_ID timer created against the leader&#8217;s tid<br \/>\nnow points to the thread which called execve(). pid_task() returns that<br \/>\nthread and lock_task_sighand() on it succeeds.<\/p>\n<p>If the timer signal is blocked, its sigqueue stays queued on the leader&#8217;s<br \/>\ntask::pending. The next expiry of that timer can then run while<br \/>\nrelease_task() flushes the queue.<\/p>\n<p>posixtimer_send_sigqueue() checks whether the sigqueue is already queued<br \/>\nwith a plain list_empty(), which only reads list_head::next.<br \/>\nlist_del_init() is not atomic and INIT_LIST_HEAD() stores list_head::next<br \/>\nbefore list_head::prev, so the check can pass in between. list_add_tail()<br \/>\nqueues the entry on the task::pending of the live thread, and the<br \/>\nlist_head::prev store from the flush then overwrites the list_head::prev<br \/>\nlink that list_add_tail() has just set.<\/p>\n<p>__flush_itimer_signals() does not undo that either. With list_head::prev<br \/>\npointing at the entry itself, its list_del_init() only stores the same<br \/>\nvalues again, so the entry is not removed from the list. It is still there<br \/>\nafter the last reference is dropped and the timer is freed by RCU, and the<br \/>\nlist_add_tail() of a later tgkill() follows that list_head::prev into the<br \/>\nfreed timer.<\/p>\n<p>This problem surfaced with the recent commit which moved the sigqueue flush<br \/>\nout of the sighand lock held region.<\/p>\n<p>Hyonwoo proposed to fix this by using list_del_init_careful(), but that<br \/>\njust papers over the problem. After some disucssions and various attempts<br \/>\nto solve it, Eric pointed out that there is no reason to flush<br \/>\ntask::pending late in release_task() and it should be done in<br \/>\nexit_signals() already.<\/p>\n<p>As nothing can collect and deliver signals which are queued in a dying<br \/>\ntask&#8217;s pending queue, there is no reason to delay it further.<\/p>\n<p>But it has to be ensured that no signals can be queued into it after that<br \/>\npoint. exit_signals() sets PF_EXITING in task::flags, which can be used as<br \/>\nan indicator for this.<\/p>\n<p>Cure it by:<\/p>\n<p>  &#8211; Preventing signal queueing for task private signals (PIDTYPE_PID) when<br \/>\n    the task has PF_EXITING set in __send_signal_locked() and in<br \/>\n    posixtimer_send_sigqueue().<\/p>\n<p>  &#8211; Protecting the unlocked setting of PF_EXITING in exit_signals() for the<br \/>\n    task group empty and the group exit case with sighand lock<\/p>\n<p>  &#8211; Flushing task::pending signals right there.<\/p>\n<p>    Optimize that by moving the whole pending list to an on-stack list head<br \/>\n    under sighand lock and free the signals without the lock held.<\/p>\n<p>There has been quite some discussion about the lockless flush and the<br \/>\nnon-leader exec case on weakly ordered systems. The problem is that a third<br \/>\nparty which tries to send a posix timer signal relies on the PID lookup to<br \/>\nfind the target task and that lookup might result in the new leader when<br \/>\nthe signal was originaly directed to the old leader. In case that the<br \/>\nsignal was queued on the old leader then the lockless flush raised a<br \/>\nconcern over the following situation:<\/p>\n<p>   old_leader\t\tnew_leader              third party<\/p>\n<p>A: flush_list()\t\/\/ list_del_in<br \/>\n&#8212;truncated&#8212;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>signal: Prevent exec() race<\/p>\n<p>Hyunwoo debugged the following KASAN UAF splat:<\/p>\n<p>  BUG: KASAN: slab-use-after-free in __send_signal_lo<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-33325","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/33325","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln"}],"about":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/types\/vuln"}],"wp:attachment":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=33325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=33325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=33325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}