{"id":41271,"date":"2026-10-19T00:32:56","date_gmt":"2026-10-18T16:32:56","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-98799"},"modified":"2026-10-19T00:32:56","modified_gmt":"2026-10-18T16:32:56","slug":"cve-2026-98799","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-98799","title":{"rendered":"CVE-2026-98799 &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nbpf: Skip detached pr"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>bpf: Skip detached progs in trampoline images that are still in use<\/p>\n<p>bpf_tramp_image_put() makes sure a trampoline image is not freed while<br \/>\na task may still be running in it, but nothing similar is done for the<br \/>\nprogs called by that image. Detach drops the last prog reference right<br \/>\naway and the prog is freed after grace periods, on the basis that a<br \/>\ntask still in the traced function skips the fexit progs once the nop at<br \/>\nip_after_call is patched to a jump.<\/p>\n<p>That leaves out a task sleeping in a sleepable prog that runs before<br \/>\nthe detached one, which no grace period waits for:<\/p>\n<p>  CPU 0                               CPU 1<br \/>\n  in image I, sleeping in prog S<br \/>\n                                      detach P from I&#8217;s trampoline<br \/>\n                                       -&gt; new image, bpf_tramp_image_put(I)<br \/>\n                                      bpf_prog_put(P), last ref<br \/>\n                                      grace periods, P freed<br \/>\n  back from S<br \/>\n  __bpf_prog_enter(P)<br \/>\n  call P-&gt;bpf_func<\/p>\n<p>If S and P are fexit progs the task is already past the patched jump,<br \/>\nand fentry only images don&#8217;t have one. On x86 this is an int3 in<br \/>\npoisoned bpf_prog_pack memory:<\/p>\n<p>  Oops: int3: 0000 [#1] SMP NOPTI<br \/>\n  CPU: 18 UID: 0 PID: 94573 Comm: x169 Not tainted 6.18.44 #1 PREEMPT(lazy)<br \/>\n  RIP: 0010:0xffffffffc0601d8d<br \/>\n  Call Trace:<\/p>\n<p>   ? bpf_trampoline_6442515411+0x1a4\/0x21b<br \/>\n   bpf_lsm_bprm_committed_creds+0x5\/0x10<br \/>\n   security_bprm_committed_creds+0x5f\/0x70<br \/>\n   begin_new_exec+0x2d6\/0x410<br \/>\n   &#8230;<\/p>\n<p>We hit this in production when progs attached through trampolines got<br \/>\ndetached while their hooks were busy, and it was independently found<br \/>\nwith a fuzzer and KASAN.<\/p>\n<p>Have the JITs emit a patchable nop in front of each prog call sequence<br \/>\nand record it in the image. When a prog is detached, patch its nop to a<br \/>\njump over the call sequence. Progs that stay attached keep running for<br \/>\nthe tasks that are in the image, and ip_after_call isn&#8217;t needed anymore.<\/p>\n<p>The task can be in any image that isn&#8217;t freed yet, not only in the<br \/>\ncurrent one. It sleeps in image I1 that calls S, P and Q, then P is<br \/>\ndetached and the trampoline moves to image I2, then Q is detached and<br \/>\nits call is still in I1. So the trampoline keeps a list of its images<br \/>\nuntil they are freed, and detaching a prog patches its nop in all of<br \/>\nthem. Images hold a reference on the trampoline for that long.<\/p>\n<p>On riscv and loongarch a jump of any range takes several instructions,<br \/>\nand a task preempted in the middle of them could resume into half of the<br \/>\nnew sequence. The nop is a single instruction there, patched to a near<br \/>\nbranch through arch_bpf_trampoline_skip().<\/p>\n<p>With the extra nops, BPF_MAX_TRAMP_LINKS progs no longer fit in a page<br \/>\non x86 and arm64 (and already didn&#8217;t on powerpc), so lower the limit<br \/>\nthere like s390 does.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>bpf: Skip detached progs in trampoline images that are still in use<\/p>\n<p>bpf_tramp_image_put() makes sure a trampoline image is not fre<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-41271","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/41271","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=41271"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=41271"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=41271"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}