CVE-2026-98547
En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad:
af_packet: corrige el desbordamiento de enteros en prb_calc_retire_blk_tmo()
prb_calc_retire_blk_tmo() calcula con aritmética de enteros de 32 bits:
Si estoy interpretando bien la validación, tp_block_size está controlado por el usuario y packet_set_ring() solo rechaza valores que son <= 0 como int o que no están alineados a página, así que un bloque de 256 MiB pasa sin problemas (y alloc_one_pg_vec_page() incluso tiene un mecanismo de reserva con vzalloc para ese caso). 0x10000000 * 8 da la vuelta y se convierte en INT_MIN, y en una NIC que informa de 1 Gbps (div == 1) la función acaba devolviendo -2047.
Leer descripción completaMostrar menos
La condición es en realidad (8 * size) mod 2^32 >= 2^31 && div == 1, así que el conjunto de disparo está formado por [256,512), [768,1024), [1280,1536) y [1792,2048) MiB. Otros tamaños dan la vuelta a valores no negativos, y los enlaces más rápidos dividen el valor sin signo de nuevo por debajo de 2^31, por lo que esto no provoca fallos para todos.
Lo que lo vuelve fatal es lo que ocurre a continuación en init_prb_bdqc():
Un tiempo de espera relativo negativo expira de inmediato. La función de retrollamada devuelve HRTIMER_RESTART incondicionalmente, y hrtimer_forward() convierte el intervalo negativo en hrtimer_resolution:
De este modo, el temporizador SOFT se vuelve a disparar a la máxima frecuencia indefinidamente, manteniendo sk_receive_queue.lock en cada pasada. Una CPU queda girando en softirq hasta que se cierra el socket. Si se repite con más anillos, la máquina queda inutilizable.
El desbordamiento en sí es muy antiguo: se introdujo junto con TPACKET_V3 en f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation."). Su efecto antes de f7460d2989fa ("net: af_packet: Use hrtimer to do the retire operation", v6.18) no era tan claro, sin embargo: el valor devuelto se almacenaba en un unsigned short retire_blk_tov, por lo que un resultado negativo se truncaba, y también se podía programar un bucle de retardo de 0 jiffies. Ninguno de los dos efectos es tan perjudicial como el giro inmediato a máxima frecuencia que introdujo la conversión a hrtimer.
(No tiene relación con CVE-2019-20812: en aquel caso, la ruta de fallo de ethtool devolvía 0, que ahora devuelve DEFAULT_PRB_RETIRE_TOV.)
Reproductor; necesita CAP_NET_RAW (un contenedor con --network host lo tiene por defecto) y una NIC de 1 Gbps (QEMU e1000 funciona):
Calcular con 64 bits en su lugar. Los operandos ya están acotados por la validación existente, así que no cambia nada más. Si prefiere una solución distinta, dígalo y lo rehago.
Detalles técnicos trazas, registros y código del informe original
mbits = (blk_size_in_bytes * 8) / (1024 * 1024);
p1->interval_ktime = ms_to_ktime(prb_calc_retire_blk_tmo(...));
hrtimer_start(&p1->retire_blk_timer, p1->interval_ktime,
HRTIMER_MODE_REL_SOFT);
if (interval < hrtimer_resolution)
interval = hrtimer_resolution;
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));Traducción automática del texto original de NVD (en inglés).
CVSS
NVD no ha asignado puntuación CVSS a esta CVE (habitual desde el cambio de política de abril de 2026).
Probabilidad de explotación (EPSS)
- Probabilidad de explotación en los próximos 30 días
- 0.21 %
- Percentil entre todas las CVEs puntuadas
- 11
- Fecha de la puntuación
- 20/10/2026
EPSS (Exploit Prediction Scoring System, de FIRST) estima la probabilidad de que una vulnerabilidad sea explotada en 30 días. Complementa a CVSS (impacto) y a CISA KEV (explotación confirmada).
Tecnologías afectadas (1)
⚠ Inferidas por IA a partir de la descripción — NVD aún no ha analizado esta CVE; no son CPE verificados.
Referencias
Mostrar las 8 referencias
- https://git.kernel.org/stable/c/02afd75649a4e001031ed82153a5c39312ec0737
- https://git.kernel.org/stable/c/218a944b9e035d4b47d59c69af6ca13319da15fb
- https://git.kernel.org/stable/c/297acc571d5813db76b147c745b91031d5f9c960
- https://git.kernel.org/stable/c/56d82862a0a243ac14ba11b6d7b57ddc2d064b95
- https://git.kernel.org/stable/c/6279211e7d2456ecd195d236c9ee5e5c6fa5a17a
- https://git.kernel.org/stable/c/b2bcc6a254d6f27823a56787668ae4ee8cdb6e71
- https://git.kernel.org/stable/c/be1aacff399d519cc48d6b34354a54dd79041140
- https://git.kernel.org/stable/c/eb5b3838b9200dac04bfe33483db0ee8287456fb
JSON original (NVD)
Mostrar
{
"id": "CVE-2026-98547",
"cveTags": [],
"metrics": {},
"affected": [
{
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"affectedData": [
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"product": "Linux",
"versions": [
{
"status": "affected",
"version": "f6fb8f100b807378fda19e83e5ac6828b638603a",
"lessThan": "02afd75649a4e001031ed82153a5c39312ec0737",
"versionType": "git"
},
{
"status": "affected",
"version": "f6fb8f100b807378fda19e83e5ac6828b638603a",
"lessThan": "eb5b3838b9200dac04bfe33483db0ee8287456fb",
"versionType": "git"
},
{
"status": "affected",
"version": "f6fb8f100b807378fda19e83e5ac6828b638603a",
"lessThan": "297acc571d5813db76b147c745b91031d5f9c960",
"versionType": "git"
},
{
"status": "affected",
"version": "f6fb8f100b807378fda19e83e5ac6828b638603a",
"lessThan": "be1aacff399d519cc48d6b34354a54dd79041140",
"versionType": "git"
},
{
"status": "affected",
"version": "f6fb8f100b807378fda19e83e5ac6828b638603a",
"lessThan": "b2bcc6a254d6f27823a56787668ae4ee8cdb6e71",
"versionType": "git"
},
{
"status": "affected",
"version": "f6fb8f100b807378fda19e83e5ac6828b638603a",
"lessThan": "6279211e7d2456ecd195d236c9ee5e5c6fa5a17a",
"versionType": "git"
},
{
"status": "affected",
"version": "f6fb8f100b807378fda19e83e5ac6828b638603a",
"lessThan": "218a944b9e035d4b47d59c69af6ca13319da15fb",
"versionType": "git"
},
{
"status": "affected",
"version": "f6fb8f100b807378fda19e83e5ac6828b638603a",
"lessThan": "56d82862a0a243ac14ba11b6d7b57ddc2d064b95",
"versionType": "git"
}
],
"programFiles": [
"net/packet/af_packet.c"
],
"defaultStatus": "unaffected"
},
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"product": "Linux",
"versions": [
{
"status": "affected",
"version": "3.2"
},
{
"status": "unaffected",
"version": "0",
"lessThan": "3.2",
"versionType": "semver"
},
{
"status": "unaffected",
"version": "5.10.271",
"versionType": "semver",
"lessThanOrEqual": "5.10.*"
},
{
"status": "unaffected",
"version": "5.15.222",
"versionType": "semver",
"lessThanOrEqual": "5.15.*"
},
{
"status": "unaffected",
"version": "6.1.189",
"versionType": "semver",
"lessThanOrEqual": "6.1.*"
},
{
"status": "unaffected",
"version": "6.6.158",
"versionType": "semver",
"lessThanOrEqual": "6.6.*"
},
{
"status": "unaffected",
"version": "6.12.112",
"versionType": "semver",
"lessThanOrEqual": "6.12.*"
},
{
"status": "unaffected",
"version": "6.18.55",
"versionType": "semver",
"lessThanOrEqual": "6.18.*"
},
{
"status": "unaffected",
"version": "7.2.9",
"versionType": "semver",
"lessThanOrEqual": "7.2.*"
},
{
"status": "unaffected",
"version": "7.3",
"versionType": "original_commit_for_fix",
"lessThanOrEqual": "*"
}
],
"programFiles": [
"net/packet/af_packet.c"
],
"defaultStatus": "affected"
}
]
}
],
"published": "2026-10-18T16:17:06.630",
"references": [
{
"url": "https://git.kernel.org/stable/c/02afd75649a4e001031ed82153a5c39312ec0737",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/218a944b9e035d4b47d59c69af6ca13319da15fb",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/297acc571d5813db76b147c745b91031d5f9c960",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/56d82862a0a243ac14ba11b6d7b57ddc2d064b95",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/6279211e7d2456ecd195d236c9ee5e5c6fa5a17a",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/b2bcc6a254d6f27823a56787668ae4ee8cdb6e71",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/be1aacff399d519cc48d6b34354a54dd79041140",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/eb5b3838b9200dac04bfe33483db0ee8287456fb",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
}
],
"vulnStatus": "Received",
"descriptions": [
{
"lang": "en",
"value": "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."
}
],
"lastModified": "2026-10-19T10:19:10.717",
"sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
}