{"id":"CVE-2026-98869","kind":"vulnerability","aliases":["CVE-2026-98869"],"related":[],"title":"Linux kernel BPF verifier: 32-bit zero-extension bug may leak upper register bits","description":"In the Linux kernel, the following vulnerability has been resolved:\n\nbpf: Infer zext_dst based on static register liveness analysis\n\nAs reported in the thread [1], the verifier's 32-bit operations zero\nextension logic is broken. This logic is responsible for correct\nsemantics of 32-bit operations on s390 architecture.\n\nAccording to BPF semantics, operation `w1 += 1` is supposed to zero\nextend the upper half of the register `r1`. On s390 the JIT relies on\nthe verifier emitting explicit zero extension before such operations.\n\nThe verifier attempts to minimize the amount of zero extensions\ninserted by tracking whether upper halves of the 64-bit registers are\never used. Previously such tracking worked as follows:\n\n- bpf_reg_state->subreg_def field was set by do_check_insn()\n  for each operation defining lower but not the upper halves\n  of the register.\n- Whenever an operation reading the whole register was verified,\n  the verifier checked register's subreg_def and set\n  bpf_insn_aux_data->zext_dst flag as true via a call to\n  mark_insn_zext() function.\n- After the verification was complete, a special pass\n  bpf_opt_subreg_zext_lo32_rnd_hi32() extended 32-bit operations\n  with bpf_insn_aux_data->zext_dst set as true by adding\n  explicit zero extension.\n\nNote that the logic above relies on bpf_reg_state->subreg_def,\nwhich is a property of a current verifier state.\nBefore the commit [2] two additional steps happened:\n\n- The verifier tracked upper and lower register halves' liveness as\n  flags REG_LIVE_READ{32,64} in bpf_reg_state->live.\n- The function propagate_liveness() called mark_insn_zext()\n  in order to transfer the knowledge about which registers have\n  their upper halves alive (and thus might require zero extension).\n\nThe commit [2] removed the two steps described above,\nhence making possible a situation like below:\n\n- The register's upper half is set and is used on some verification\n  path P1 and the register happens not to be marked as precise.\n- The checkpoint C is created while processing some instruction\n  between register initialization and usage.\n- On some other verification path P2 the register's upper half is not\n  initialized and that path ends hitting the checkpoint C.\n- In such a case the register's initialization on path P2 would lack\n  zext_dst mark, making it possible for the program to inject\n  an arbitrary value in the register's upper half.\n\nThis commit replaces subreg_def based logic with computing zext_dst\nstatically, as a part of the bpf_compute_live_registers() analysis:\n\n- The analysis now tracks usage of upper and lower halves of the\n  registers separately.\n- If some instruction defines a 32-bit subregister, but not the whole\n  register, *and* the upper half of the register is alive after that\n  instruction, the instruction is marked as zext_dst.\n\nThere is one notable drop in precision: whenever a BPF subprogram is\ncalled, all 64 bits of parameter registers are presumed to be used.\nThe assumption is that such a drop in precision would not inflict\na noticeable performance penalty.\n\n[1] https://lore.kernel.org/bpf/CAGKGUv=sOuqQtA1Ub-5JXfA4FPosJFYKAQE4B79cK+P1erxqtg@mail.gmail.com/\n[2] commit 107e16979905 (\"bpf: disable and remove registers chain based liveness\")","summary":"The Linux kernel BPF verifier can skip the zero extension of a register's upper 32 bits on some verification paths, which breaks the semantics of 32-bit operations on s390. The sources do not say what an attacker gets beyond a program being able to inject an arbitrary value into a register's upper half.","severity":"unknown","cvss":null,"epss":0.00155,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["bpf","linux-kernel","runtime","s390"],"not_affected_if":["bpf-disabled"],"how_to_check":"- unknown","fix":"- Update the Linux kernel to a release that includes the upstream commit resolving the bpf zext_dst inference change (the sources do not list fixed versions).","status":"open","published_at":"2026-10-21T15:17:19+00:00","first_seen_at":"2026-10-23T21:57:28+00:00","triaged_at":"2026-10-25T05:02:08+00:00","updated_at":"2026-10-25T05:02:08+00:00","category":"runtime","confidence":0.4,"triage":{"at":"2026-10-25T05:02:08Z","model":"claude-haiku-5-5","output":{"fix":"- Update the Linux kernel to a release that includes the upstream commit resolving the bpf zext_dst inference change (the sources do not list fixed versions).","reach":"local","title":"Linux kernel BPF verifier: 32-bit zero-extension bug may leak upper register bits","impact":"medium","summary":"The Linux kernel BPF verifier can skip the zero extension of a register's upper 32 bits on some verification paths, which breaks the semantics of 32-bit operations on s390. The sources do not say what an attacker gets beyond a program being able to inject an arbitrary value into a register's upper half.","category":"runtime","nicknames":[],"who_cares":["linux-kernel","bpf","s390"],"confidence":0.4,"needs_auth":"unknown","worst_case":"unknown; sources suggest arbitrary upper register bits could be injected","analyst_note":"Check the NVD entry and the linked upstream kernel commits for affected and fixed kernel versions and whether unprivileged BPF is needed.","how_to_check":"- unknown","needs_analyst":true,"not_affected_if":["bpf-disabled"],"who_is_affected":"Systems running a Linux kernel with BPF program loading enabled, particularly on s390 where the JIT depends on verifier-inserted zero extension. The sources do not say whether unprivileged BPF loading is required. Systems without BPF use can likely skip it, but the sources do not confirm this.","user_interaction":"no","needs_special_setup":"unknown","severity_if_unknown":"unknown"},"cost_usd":0.000707,"input_tokens":4398,"output_tokens":534,"severity_before":"unknown"},"analyst_status":null,"analyst_note":null,"search":"'-2026':17A,20A '-98869':18A,21A '/bpf/cagkguv=souqqta1ub-5jxfa4fposjfykaqe4b79ck+p1erxqtg@mail.gmail.com/':592C '1':109C,141C,589C '107e16979905':595C '2':317C,373C,593C '32':5A,43B,54B,113C,129C,275C,336C,522C '64':187C,337C,563C 'abl':72B 'accord':135C 'add':289C 'addit':319C 'aliv':364C,538C 'amount':175C 'analysi':103C,502C,504C 'arbitrari':76B,473C 'architectur':134C 'assumpt':574C 'attack':66B 'attempt':171C 'aux':244C,281C 'base':98C,486C,602C 'beyond':68B 'bit':6A,15A,44B,55B,114C,130C,188C,276C,523C,564C 'bpf':3A,22B,31B,94C,137C,199C,242C,267C,279C,300C,339C,498C,558C,596C 'break':50B 'broken':120C 'bug':10A 'c':414C,447C 'call':253C,347C,561C 'case':451C 'chain':601C 'check':209C,235C 'checkpoint':413C,446C 'commit':316C,372C,482C,594C 'complet':263C 'comput':489C,499C 'correct':126C 'creat':416C 'current':311C 'cve':16A,19A 'data':245C,282C 'def':203C,239C,304C,485C 'defin':214C,520C 'describ':378C 'disabl':597C 'drop':553C,579C 'dst':97C,247C,284C,462C,491C,548C 'emit':162C 'end':443C 'ever':191C 'explicit':163C,290C 'extend':146C,274C 'extens':9A,37B,117C,165C,178C,292C,370C 'field':204C 'flag':248C,332C 'follow':89C,198C 'function':258C,344C 'get':67B 'half':83B,149C,391C,436C,480C,533C 'halv':184C,220C,329C,363C,512C 'happen':321C,405C 'henc':380C 'hi32':273C 'hit':444C 'infer':95C 'inflict':584C 'initi':423C,439C,455C 'inject':74B,471C 'insert':179C 'insn':210C,243C,256C,280C,349C 'instruct':420C,519C,541C,543C 'jit':157C 'kernel':2A,25B,30B,87C 'knowledg':356C 'lack':460C 'leak':12A 'like':385C 'linux':1A,24B,29B,86C 'linux-kernel':23B 'live':102C,330C,334C,342C,346C,500C,603C 'lo32':271C 'logic':118C,122C,296C,487C 'lore.kernel.org':591C 'lore.kernel.org/bpf/cagkguv=souqqta1ub-5jxfa4fposjfykaqe4b79ck+p1erxqtg@mail.gmail.com/':590C 'lower':215C,327C,511C 'make':381C,464C 'mark':255C,348C,409C,463C,545C 'may':11A 'might':367C 'minim':173C 'notabl':552C 'note':293C 'notic':586C 'one':551C 'oper':56B,115C,131C,139C,168C,213C,226C,277C 'opt':268C 'order':352C 'p1':401C 'p2':431C,458C 'paramet':566C 'part':495C 'pass':266C 'path':48B,400C,430C,442C,457C 'penalti':588C 'perform':587C 'possibl':382C,466C 'precis':411C,555C,581C 'presum':569C 'previous':193C 'process':418C 'program':70B,469C 'propag':345C 'properti':308C 'r1':153C 'read':227C,335C 'reg':200C,301C,333C,340C 'regist':14A,40B,80B,101C,152C,189C,223C,230C,236C,328C,359C,388C,404C,422C,433C,453C,477C,501C,515C,529C,536C,567C,600C 'reli':158C,298C 'remov':374C,599C 'replac':483C 'report':105C 'requir':368C 'resolv':93C 'respons':124C 'rnd':272C 'runtim':26B 's390':27B,58B,133C,155C 'say':63B 'semant':52B,127C,138C 'separ':516C 'set':206C,241C,285C,393C 'situat':384C 'skip':34B 'sourc':60B 'special':265C 'state':201C,302C,313C,341C 'static':100C,492C 'step':320C,377C 'subprogram':559C 'subreg':202C,238C,269C,303C,484C 'subregist':524C 'suppos':143C 'thread':108C 'thus':366C 'track':181C,195C,324C,506C 'transfer':354C 'true':250C,287C 'two':318C,376C 'upper':13A,42B,82B,148C,183C,219C,325C,362C,390C,435C,479C,509C,532C 'usag':425C,507C 'use':192C,396C,572C 'valu':77B,474C 'verif':47B,261C,399C,429C 'verifi':4A,32B,111C,161C,170C,232C,234C,312C,323C 'via':251C 'vulner':90C 'w1':140C 'whenev':224C,556C 'whether':182C 'whole':229C,528C 'work':196C 'would':459C,582C 'zero':8A,36B,116C,145C,164C,177C,291C,369C 'zero-extens':7A 'zext':96C,246C,257C,270C,283C,350C,461C,490C,547C","nicknames":[],"mitigations":[],"who_affected":"Systems running a Linux kernel with BPF program loading enabled, particularly on s390 where the JIT depends on verifier-inserted zero extension. The sources do not say whether unprivileged BPF loading is required. Systems without BPF use can likely skip it, but the sources do not confirm this.","tier":"C","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-21T15:17:19+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-98869","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-98869","severity":null,"published_at":"2026-10-21T15:17:19+00:00","modified_at":"2026-10-21T15:17:19+00:00","first_seen_at":"2026-10-23T21:57:28+00:00","fetched_at":"2026-10-23T22:29:01+00:00","note":null},{"source":"epss","external_id":"CVE-2026-98869","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-98869","severity":null,"published_at":null,"modified_at":null,"first_seen_at":"2026-10-24T13:15:54+00:00","fetched_at":"2026-10-24T13:15:54+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}