Cloudanix VulnDB

CVE-2026-98547

None

CVSS

—

EPSS

0.2%

Published

Oct 18, 2026

CISA due date

—

Cloudanix analysis

Schedule a fix SSVC: Track

A bug in the Linux kernel's network packet handling can let someone with special network permissions overload the computer's processor and make the system unusable.

Exploitation
Local Privilege
Attacker needs
Low Privilege
Complexity
Moderate
Impact
Denial Of Service
Component
OS kernel
Class
Improper Input Validation
Remediation
Patch
Effort
Medium
Patch risk
Low

What it actually does

Integer overflow in 32-bit arithmetic within prb_calc_retire_blk_tmo() for TPACKET_V3 packet rings allows user-controlled block sizes to produce a negative ktime value, causing init_prb_bdqc() to start an hrtimer that immediately restarts at maximum rate in softirq context while holding sk_receive_queue.lock.

Why it matters to the business

A local user with network raw socket privileges can trigger sustained CPU exhaustion on one or more cores, leading to system unresponsiveness or denial of service on affected Linux kernels; low EPSS and absence from KEV indicate limited observed exploitation five days after publication.

How an attack unfolds

An attacker with CAP_NET_RAW creates an AF_PACKET socket, enables TPACKET_V3, and configures a tpacket_req3 ring buffer with a tp_block_size value in the ranges that trigger 32-bit overflow (such as 256 MiB on 1 Gbps links); this passes a negative interval to the hrtimer, which the callback logic converts into continuous maximum-rate firing.

How to fix it

Apply the upstream fix that changes the mbits calculation in prb_calc_retire_blk_tmo() to use 64-bit arithmetic; rebuild and deploy updated kernels, or backport the change from the commit resolving the 32-bit overflow.

How to confirm the fix worked

Inspect the kernel source for 64-bit computation of retire block timeout; attempt the published reproducer on a test system and confirm the timer no longer fires continuously or produces negative intervals.

Typical attack path

  1. Create AF_PACKET SOCK_RAW socket
  2. Set PACKET_VERSION to TPACKET_V3 via setsockopt
  3. Prepare tpacket_req3 structure with tp_block_size in overflow trigger ranges and call PACKET_RX_RING setsockopt
  4. Trigger the retire_blk_timer which spins in softirq holding the socket lock
  5. Repeat across multiple rings or sockets to amplify CPU consumption

How to detect it

Search kernel or audit logs for unusual AF_PACKET socket creation with TPACKET_V3 and large block sizes; monitor for sustained softirq CPU usage correlated with packet socket activity; examine processes holding sk_receive_queue locks during high load.

  • setsockopt.*PACKET_VERSION.*TPACKET_V3
  • setsockopt.*PACKET_RX_RING.*tp_block_size
  • prb_calc_retire_blk_tmo

What your security team should do

  • Prioritize kernel updates for systems exposing AF_PACKET to untrusted code or containers
  • Restrict CAP_NET_RAW capability using seccomp, AppArmor, or container runtime policies
  • Monitor EPSS and KEV updates for this issue given its recent publication

The record

In the Linux kernel, the following vulnerability has been resolved: af_packet: fix integer overflow in prb_calc_retire_blk_tmo() prb_calc_retire_blk_tmo() computes in 32-bit int arithmetic: mbits = (blk_size_in_bytes * 8) / (1024 * 1024); If I'm reading the validation right, tp_block_size is user controlled and packet_set_ring() only rejects values that are <= 0 as int or not page aligned, so a 256MiB block goes right through (and alloc_one_pg_vec_page() even has a vzalloc fallback for it). 0x10000000 * 8 wraps to INT_MIN, and on a NIC reporting 1 Gbps (div == 1) the function ends up returning -2047. The condition is actually (8 * size) mod 2^32 >= 2^31 && div == 1, so the trigger set is [256,512), [768,1024), [1280,1536) and [1792,2048) MiB. Other sizes wrap to non-negative values and faster links divide the unsigned value back below 2^31, which is why this doesn't blow up for everyone. What makes it fatal is what happens next in init_prb_bdqc(): p1->interval_ktime = ms_to_ktime(prb_calc_retire_blk_tmo(...)); hrtimer_start(&p1->retire_blk_timer, p1->interval_ktime, HRTIMER_MODE_REL_SOFT); A negative relative timeout expires immediately. The callback unconditionally returns HRTIMER_RESTART, and hrtimer_forward() turns the negative interval into hrtimer_resolution: if (interval < hrtimer_resolution) interval = hrtimer_resolution; So the SOFT timer re-fires at the maximum rate forever, holding sk_receive_queue.lock each pass. One CPU spins in softirq until the socket is closed. Repeat with more rings and the machine is gone. The overflow itself is ancient - it was introduced together with TPACKET_V3 in f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation."). Its effect prior to f7460d2989fa ("net: af_packet: Use hrtimer to do the retire operation", v6.18) was not as clear-cut, though: the return value was stored into an unsigned short retire_blk_tov, so a negative result was truncated, and a 0-jiffy delay loop could be programmed as well. Neither is nearly as detrimental as the immediate maximum-rate spin the hrtimer conversion turned it into. (Unrelated to CVE-2019-20812 - that one was the ethtool failure path returning 0, which now returns DEFAULT_PRB_RETIRE_TOV.) Reproducer, needs CAP_NET_RAW (a --network host container has it by default) and a 1 Gbps NIC (QEMU e1000 works): int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); bind(fd, ...); int v = TPACKET_V3; setsockopt(fd, SOL_PACKET, PACKET_VERSION, &v, sizeof(v)); struct tpacket_req3 req = { .tp_block_size = 0x10000000, .tp_block_nr = 1, .tp_frame_size = 2048, .tp_frame_nr = 0x10000000 / 2048, .tp_retire_blk_tov = 0, }; setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req)); Compute in 64 bits instead. The operands are already bounded by the existing validation, so nothing else changes. If you'd prefer a different fix, just say so and I'll respin.

Affected packages

Ecosystem Package Introduced Fixed