{"id":"CVE-2026-98547","kind":"vulnerability","aliases":["CVE-2026-98547"],"related":[],"title":"Linux kernel: af_packet integer overflow lets local user spin CPU","description":"In the Linux kernel, the following vulnerability has been resolved:\n\naf_packet: fix integer overflow in prb_calc_retire_blk_tmo()\n\nprb_calc_retire_blk_tmo() computes in 32-bit int arithmetic:\n\n        mbits = (blk_size_in_bytes * 8) / (1024 * 1024);\n\nIf I'm reading the validation right, tp_block_size is user\ncontrolled and packet_set_ring() only rejects values that are <= 0\nas int or not page aligned, so a 256MiB block goes right through\n(and alloc_one_pg_vec_page() even has a vzalloc fallback for it).\n0x10000000 * 8 wraps to INT_MIN, and on a NIC reporting 1 Gbps\n(div == 1) the function ends up returning -2047.\n\nThe condition is actually (8 * size) mod 2^32 >= 2^31 && div == 1,\nso the trigger set is [256,512), [768,1024), [1280,1536) and\n[1792,2048) MiB. Other sizes wrap to non-negative values and faster\nlinks divide the unsigned value back below 2^31, which is why this\ndoesn't blow up for everyone.\n\nWhat makes it fatal is what happens next in init_prb_bdqc():\n\n        p1->interval_ktime = ms_to_ktime(prb_calc_retire_blk_tmo(...));\n        hrtimer_start(&p1->retire_blk_timer, p1->interval_ktime,\n                      HRTIMER_MODE_REL_SOFT);\n\nA negative relative timeout expires immediately. The callback\nunconditionally returns HRTIMER_RESTART, and hrtimer_forward() turns\nthe negative interval into hrtimer_resolution:\n\n        if (interval < hrtimer_resolution)\n                interval = hrtimer_resolution;\n\nSo the SOFT timer re-fires at the maximum rate forever, holding\nsk_receive_queue.lock each pass. One CPU spins in softirq until the\nsocket is closed. Repeat with more rings and the machine is gone.\n\nThe overflow itself is ancient - it was introduced together with\nTPACKET_V3 in f6fb8f100b80 (\"af-packet: TPACKET_V3 flexible buffer\nimplementation.\"). Its effect prior to f7460d2989fa (\"net:\naf_packet: Use hrtimer to do the retire operation\", v6.18) was not\nas clear-cut, though: the return value was stored into an unsigned\nshort retire_blk_tov, so a negative result was truncated, and a\n0-jiffy delay loop could be programmed as well. Neither is nearly\nas detrimental as the immediate maximum-rate spin the hrtimer\nconversion turned it into.\n\n(Unrelated to CVE-2019-20812 - that one was the ethtool failure path\nreturning 0, which now returns DEFAULT_PRB_RETIRE_TOV.)\n\nReproducer, needs CAP_NET_RAW (a --network host container has it by\ndefault) and a 1 Gbps NIC (QEMU e1000 works):\n\n        int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));\n        bind(fd, ...);\n        int v = TPACKET_V3;\n        setsockopt(fd, SOL_PACKET, PACKET_VERSION, &v, sizeof(v));\n        struct tpacket_req3 req = {\n                .tp_block_size = 0x10000000,\n                .tp_block_nr = 1,\n                .tp_frame_size = 2048,\n                .tp_frame_nr = 0x10000000 / 2048,\n                .tp_retire_blk_tov = 0,\n        };\n        setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req));\n\nCompute in 64 bits instead. The operands are already bounded by the\nexisting validation, so nothing else changes. If you'd prefer a\ndifferent fix, just say so and I'll respin.","summary":"An integer overflow in the AF_PACKET TPACKET_V3 ring setup can produce a negative retire timeout on a 1 Gbps NIC, causing a high-rate hrtimer loop in softirq context. An unprivileged user with CAP_NET_RAW can exhaust a CPU and, with several rings, take the machine down.","severity":"high","cvss":null,"epss":null,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["containers","linux-kernel","network-host","runtime","self-hosted"],"not_affected_if":["kernel-patched","no-cap-net-raw","non-1gbps-nic"],"how_to_check":"- Run `uname -r` and compare against the kernel version that carries the fix; the sources do not list affected versions.\n- Check whether unprivileged users or containers hold CAP_NET_RAW, for example with `capsh --print` inside a `--network host` container.","fix":"- Update the Linux kernel to a release that includes the fix that computes prb_calc_retire_blk_tmo() in 64-bit arithmetic; the sources do not name the fixed version.\n- Until patched, restrict CAP_NET_RAW for untrusted workloads.","status":"open","published_at":"2026-10-18T16:17:06+00:00","first_seen_at":"2026-10-23T21:57:15+00:00","triaged_at":"2026-10-25T05:23:36+00:00","updated_at":"2026-10-25T05:23:36+00:00","category":"runtime","confidence":0.8,"triage":{"at":"2026-10-25T05:23:36Z","model":"claude-haiku-5-5","output":{"fix":"- Update the Linux kernel to a release that includes the fix that computes prb_calc_retire_blk_tmo() in 64-bit arithmetic; the sources do not name the fixed version.\n- Until patched, restrict CAP_NET_RAW for untrusted workloads.","reach":"local","title":"Linux kernel: af_packet integer overflow lets local user spin CPU","impact":"medium","summary":"An integer overflow in the AF_PACKET TPACKET_V3 ring setup can produce a negative retire timeout on a 1 Gbps NIC, causing a high-rate hrtimer loop in softirq context. An unprivileged user with CAP_NET_RAW can exhaust a CPU and, with several rings, take the machine down.","category":"runtime","nicknames":[],"who_cares":["linux-kernel","self-hosted","containers","network-host"],"confidence":0.8,"needs_auth":"yes","worst_case":"local user spins a CPU in softirq and can crash the machine","analyst_note":"Find the upstream commit and the first fixed kernel version from the NVD or kernel.org stable list, since the sources give no affected or fixed versions.","how_to_check":"- Run `uname -r` and compare against the kernel version that carries the fix; the sources do not list affected versions.\n- Check whether unprivileged users or containers hold CAP_NET_RAW, for example with `capsh --print` inside a `--network host` container.","needs_analyst":true,"not_affected_if":["no-cap-net-raw","kernel-patched","non-1gbps-nic"],"who_is_affected":"Systems running a Linux kernel with the af_packet TPACKET_V3 code path, reachable by any user or container holding CAP_NET_RAW. The trigger needs a 1 Gbps link (div == 1) and a block size in specific ranges of 256 MiB multiples, so most hosts are not hit by the exact trigger. Hosts that never grant CAP_NET_RAW to untrusted code can deprioritise it.","user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"high"},"cost_usd":0.000817,"input_tokens":4539,"output_tokens":727,"severity_before":"unknown"},"analyst_status":null,"analyst_note":null,"search":"'-2019':441C '-2026':13A,16A '-2047':188C '-20812':442C '-98547':14A,17A '0':141C,411C,451C,531C '0x10000000':168C,513C,525C '1':48B,179C,182C,201C,474C,517C '1024':117C,118C,210C '1280':211C '1536':212C '1792':214C '2':196C,198C,234C '2048':215C,521C,526C '256':207C '256mib':150C '31':199C,235C '32':107C,197C '512':208C '64':544C '768':209C '8':116C,169C,193C 'actual':192C 'af':3A,34B,89C,361C,374C,483C 'af-packet':360C 'align':147C 'alloc':156C 'alreadi':550C 'ancient':350C 'arithmet':110C 'back':232C 'bdqc':257C 'bind':491C 'bit':108C,545C 'blk':98C,103C,112C,267C,273C,401C,529C 'block':127C,151C,511C,515C 'blow':242C 'bound':551C 'buffer':366C 'byte':115C 'calc':96C,101C,265C 'callback':289C 'cap':65B,461C 'caus':51B 'chang':559C 'clear':388C 'clear-cut':387C 'close':336C 'comput':105C,542C 'condit':190C 'contain':18B,467C 'context':60B 'control':131C 'convers':434C 'could':415C 'cpu':11A,71B,328C 'cut':389C 'cve':12A,15A,440C 'd':562C 'default':455C,471C 'delay':413C 'detriment':424C 'differ':565C 'div':181C,200C 'divid':228C 'doesn':240C 'e1000':478C 'effect':369C 'els':558C 'end':185C 'eth':488C 'ethtool':447C 'even':161C 'everyon':245C 'exhaust':69B 'exist':554C 'expir':286C 'f6fb8f100b80':359C 'f7460d2989fa':372C 'failur':448C 'fallback':165C 'faster':226C 'fatal':249C 'fd':481C,492C,498C,533C 'fire':317C 'fix':91C,566C 'flexibl':365C 'follow':84C 'forev':322C 'forward':296C 'frame':519C,523C 'function':184C 'gbps':49B,180C,475C 'goe':152C 'gone':345C 'happen':252C 'high':54B 'high-rat':53B 'hold':323C 'host':24B,28B,466C 'hrtimer':56B,269C,278C,292C,295C,302C,306C,309C,377C,433C 'hton':487C 'immedi':287C,427C 'implement':367C 'init':255C 'instead':546C 'int':109C,143C,172C,480C,493C 'integ':5A,30B,92C 'interv':259C,276C,300C,305C,308C 'introduc':353C 'jiffi':412C 'kernel':2A,21B,82C 'ktime':260C,263C,277C 'let':7A 'link':227C 'linux':1A,20B,81C 'linux-kernel':19B 'll':572C 'local':8A 'loop':57B,414C 'm':121C 'machin':78B,343C 'make':247C 'maximum':320C,429C 'maximum-r':428C 'mbit':111C 'mib':216C 'min':173C 'mod':195C 'mode':279C 'ms':261C 'near':422C 'need':460C 'negat':43B,223C,283C,299C,405C 'neither':420C 'net':66B,373C,462C 'network':23B,465C 'network-host':22B 'next':253C 'nic':50B,177C,476C 'non':222C 'non-neg':221C 'noth':557C 'nr':516C,524C 'one':157C,327C,444C 'oper':382C 'operand':548C 'overflow':6A,31B,93C,347C 'p':489C 'p1':258C,271C,275C 'packet':4A,35B,90C,133C,362C,375C,484C,500C,501C,535C,536C 'page':146C,160C 'pass':326C 'path':449C 'pg':158C 'prb':95C,100C,256C,264C,456C 'prefer':563C 'prior':370C 'produc':41B 'program':417C 'qemu':477C 'rate':55B,321C,430C 'raw':67B,463C,486C 're':316C 're-fir':315C 'read':122C 'reject':137C 'rel':280C 'relat':284C 'repeat':337C 'report':178C 'reproduc':459C 'req':509C,539C,541C 'req3':508C 'resolut':303C,307C,310C 'resolv':88C 'respin':573C 'restart':293C 'result':406C 'retir':44B,97C,102C,266C,272C,381C,400C,457C,528C 'return':187C,291C,392C,450C,454C 'right':125C,153C 'ring':38B,75B,135C,340C,538C 'runtim':25B 'rx':537C 'say':568C 'self':27B 'self-host':26B 'set':134C,205C 'setsockopt':497C,532C 'setup':39B 'sever':74B 'short':399C 'size':113C,128C,194C,218C,512C,520C 'sizeof':504C,540C 'sk_receive_queue.lock':324C 'sock':485C 'socket':334C,482C 'soft':281C,313C 'softirq':59B,331C 'sol':499C,534C 'spin':10A,329C,431C 'start':270C 'store':395C 'struct':506C 'take':76B 'though':390C 'timeout':45B,285C 'timer':274C,314C 'tmo':99C,104C,268C 'togeth':354C 'tov':402C,458C,530C 'tp':126C,510C,514C,518C,522C,527C 'tpacket':36B,356C,363C,495C,507C 'trigger':204C 'truncat':408C 'turn':297C,435C 'uncondit':290C 'unprivileg':62B 'unrel':438C 'unsign':230C,398C 'use':376C 'user':9A,63B,130C 'v':494C,503C,505C 'v3':37B,357C,364C,496C 'v6.18':383C 'valid':124C,555C 'valu':138C,224C,231C,393C 'vec':159C 'version':502C 'vulner':85C 'vzalloc':164C 'well':419C 'work':479C 'wrap':170C,219C","nicknames":[],"mitigations":[],"who_affected":"Systems running a Linux kernel with the af_packet TPACKET_V3 code path, reachable by any user or container holding CAP_NET_RAW. The trigger needs a 1 Gbps link (div == 1) and a block size in specific ranges of 256 MiB multiples, so most hosts are not hit by the exact trigger. Hosts that never grant CAP_NET_RAW to untrusted code can deprioritise it.","tier":"B","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-18T16:17:06+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-98547","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-98547","severity":null,"published_at":"2026-10-18T16:17:06+00:00","modified_at":"2026-10-19T10:19:10+00:00","first_seen_at":"2026-10-23T21:57:15+00:00","fetched_at":"2026-10-23T22:28:56+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"}