{"id":44129,"date":"2026-10-22T04:40:07","date_gmt":"2026-10-21T20:40:07","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-98869"},"modified":"2026-10-22T04:40:07","modified_gmt":"2026-10-21T20:40:07","slug":"cve-2026-98869","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-98869","title":{"rendered":"CVE-2026-98869 &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nbpf: Infer zext_dst b"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>bpf: Infer zext_dst based on static register liveness analysis<\/p>\n<p>As reported in the thread [1], the verifier&#8217;s 32-bit operations zero<br \/>\nextension logic is broken. This logic is responsible for correct<br \/>\nsemantics of 32-bit operations on s390 architecture.<\/p>\n<p>According to BPF semantics, operation `w1 += 1` is supposed to zero<br \/>\nextend the upper half of the register `r1`. On s390 the JIT relies on<br \/>\nthe verifier emitting explicit zero extension before such operations.<\/p>\n<p>The verifier attempts to minimize the amount of zero extensions<br \/>\ninserted by tracking whether upper halves of the 64-bit registers are<br \/>\never used. Previously such tracking worked as follows:<\/p>\n<p>&#8211; bpf_reg_state-&gt;subreg_def field was set by do_check_insn()<br \/>\n  for each operation defining lower but not the upper halves<br \/>\n  of the register.<br \/>\n&#8211; Whenever an operation reading the whole register was verified,<br \/>\n  the verifier checked register&#8217;s subreg_def and set<br \/>\n  bpf_insn_aux_data-&gt;zext_dst flag as true via a call to<br \/>\n  mark_insn_zext() function.<br \/>\n&#8211; After the verification was complete, a special pass<br \/>\n  bpf_opt_subreg_zext_lo32_rnd_hi32() extended 32-bit operations<br \/>\n  with bpf_insn_aux_data-&gt;zext_dst set as true by adding<br \/>\n  explicit zero extension.<\/p>\n<p>Note that the logic above relies on bpf_reg_state-&gt;subreg_def,<br \/>\nwhich is a property of a current verifier state.<br \/>\nBefore the commit [2] two additional steps happened:<\/p>\n<p>&#8211; The verifier tracked upper and lower register halves&#8217; liveness as<br \/>\n  flags REG_LIVE_READ{32,64} in bpf_reg_state-&gt;live.<br \/>\n&#8211; The function propagate_liveness() called mark_insn_zext()<br \/>\n  in order to transfer the knowledge about which registers have<br \/>\n  their upper halves alive (and thus might require zero extension).<\/p>\n<p>The commit [2] removed the two steps described above,<br \/>\nhence making possible a situation like below:<\/p>\n<p>&#8211; The register&#8217;s upper half is set and is used on some verification<br \/>\n  path P1 and the register happens not to be marked as precise.<br \/>\n&#8211; The checkpoint C is created while processing some instruction<br \/>\n  between register initialization and usage.<br \/>\n&#8211; On some other verification path P2 the register&#8217;s upper half is not<br \/>\n  initialized and that path ends hitting the checkpoint C.<br \/>\n&#8211; In such a case the register&#8217;s initialization on path P2 would lack<br \/>\n  zext_dst mark, making it possible for the program to inject<br \/>\n  an arbitrary value in the register&#8217;s upper half.<\/p>\n<p>This commit replaces subreg_def based logic with computing zext_dst<br \/>\nstatically, as a part of the bpf_compute_live_registers() analysis:<\/p>\n<p>&#8211; The analysis now tracks usage of upper and lower halves of the<br \/>\n  registers separately.<br \/>\n&#8211; If some instruction defines a 32-bit subregister, but not the whole<br \/>\n  register, *and* the upper half of the register is alive after that<br \/>\n  instruction, the instruction is marked as zext_dst.<\/p>\n<p>There is one notable drop in precision: whenever a BPF subprogram is<br \/>\ncalled, all 64 bits of parameter registers are presumed to be used.<br \/>\nThe assumption is that such a drop in precision would not inflict<br \/>\na noticeable performance penalty.<\/p>\n<p>[1] https:\/\/lore.kernel.org\/bpf\/CAGKGUv=sOuqQtA1Ub-5JXfA4FPosJFYKAQE4B79cK+P1erxqtg@mail.gmail.com\/<br \/>\n[2] commit 107e16979905 (&#8220;bpf: disable and remove registers chain based liveness&#8221;)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>bpf: Infer zext_dst based on static register liveness analysis<\/p>\n<p>As reported in the thread [1], the verifier&#8217;s 32-bit operations zer<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-44129","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/44129","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=44129"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=44129"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=44129"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}