{"id":"CVE-2026-10677","aliases":["EUVD-2026-46446","GHSA-r3cc-8wcr-xfj9"],"status":"published","title":"Kernel heap memory leak in `z_vrfy_k_poll()` lets an unprivileged user thread exhaust the kernel resource pool","description":"The CONFIG_USERSPACE syscall verifier z_vrfy_k_poll() in kernel/poll.c allocates a kernel-side copy of the user-supplied k_poll_event[] via z_thread_malloc() and then validates each event's object handle. Before this fix, validation used K_OOPS(K_SYSCALL_OBJ(...)) inline inside the loop, which kills the calling thread without freeing events_copy.\n\nA user thread can pass num_events \u003e= 1 with a forged object handle to leak the allocation; because newly spawned user threads inherit the parent's resource_pool (kernel/thread.c), an attacker spawns sacrificial threads to repeat the leak until the shared kernel heap is exhausted. Once depleted, legitimate kernel allocations from that pool (k_queue alloc nodes, k_msgq buffers, future k_poll calls, etc.) fail, causing a system-level denial of service.\n\nThe fix replaces each inline K_OOPS with a conditional goto oops_free so the buffer is freed before the thread is killed. Affects Zephyr releases from v1.12.0 (when k_poll was first exposed to user mode) through v4.4.1.","severity":{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00143,"percentile":0.03641,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":false},"cwes":["CWE-401"],"published":"2026-07-21T21:30:54Z","modified":"2026-11-04T04:58:55Z","products":[{"vendor":"zephyrproject","product":"zephyr"},{"vendor":"zephyrproject-rtos","product":"zephyr"}],"references":[{"url":"https://github.com/zephyrproject-rtos/zephyr/commit/8dc7a37bc75402a0a3329397887f32f5fb4da3ad","tags":["patch","Patch","fix"]},{"url":"https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-r3cc-8wcr-xfj9","tags":["Patch","Vendor Advisory","advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/10xxx/CVE-2026-10677.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-10677","tags":["advisory"]},{"url":"https://github.com/zephyrproject-rtos/zephyr","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-10677","title":"Kernel heap memory leak in `z_vrfy_k_poll()` lets an unprivileged user thread exhaust the kernel resource pool","description":"The CONFIG_USERSPACE syscall verifier z_vrfy_k_poll() in kernel/poll.c allocates a kernel-side copy of the user-supplied k_poll_event[] via z_thread_malloc() and then validates each event's object handle. Before this fix, validation used K_OOPS(K_SYSCALL_OBJ(...)) inline inside the loop, which kills the calling thread without freeing events_copy.\n\nA user thread can pass num_events \u003e= 1 with a forged object handle to leak the allocation; because newly spawned user threads inherit the parent's resource_pool (kernel/thread.c), an attacker spawns sacrificial threads to repeat the leak until the shared kernel heap is exhausted. Once depleted, legitimate kernel allocations from that pool (k_queue alloc nodes, k_msgq buffers, future k_poll calls, etc.) fail, causing a system-level denial of service.\n\nThe fix replaces each inline K_OOPS with a conditional goto oops_free so the buffer is freed before the thread is killed. Affects Zephyr releases from v1.12.0 (when k_poll was first exposed to user mode) through v4.4.1.","status":"published","published":"2026-07-21T21:30:54.69Z","modified":"2026-11-04T04:58:55.126Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H","level":"medium","assessor":"cna"}],"cwes":["CWE-401"],"updated_at":"2026-11-04T05:21:48.223566Z"}],"euvd":[{"id":"EUVD-2026-46446","description":"The CONFIG_USERSPACE syscall verifier z_vrfy_k_poll() in kernel/poll.c allocates a kernel-side copy of the user-supplied k_poll_event[] via z_thread_malloc() and then validates each event's object handle. Before this fix, validation used K_OOPS(K_SYSCALL_OBJ(...)) inline inside the loop, which kills the calling thread without freeing events_copy.\n\nA user thread can pass num_events \u003e= 1 with a forged object handle to leak the allocation; because newly spawned user threads inherit the parent's resource_pool (kernel/thread.c), an attacker spawns sacrificial threads to repeat the leak until the shared kernel heap is exhausted. Once depleted, legitimate kernel allocations from that pool (k_queue alloc nodes, k_msgq buffers, future k_poll calls, etc.) fail, causing a system-level denial of service.\n\nThe fix replaces each inline K_OOPS with a conditional goto oops_free so the buffer is freed before the thread is killed. Affects Zephyr releases from v1.12.0 (when k_poll was first exposed to user mode) through v4.4.1.","status":"published","published":"2026-07-21T21:30:54Z","modified":"2026-11-04T04:58:55Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H","level":"medium"}],"updated_at":"2026-11-04T07:00:56.720215Z"}],"nvd":[{"id":"CVE-2026-10677","description":"The CONFIG_USERSPACE syscall verifier z_vrfy_k_poll() in kernel/poll.c allocates a kernel-side copy of the user-supplied k_poll_event[] via z_thread_malloc() and then validates each event's object handle. Before this fix, validation used K_OOPS(K_SYSCALL_OBJ(...)) inline inside the loop, which kills the calling thread without freeing events_copy.\n\nA user thread can pass num_events \u003e= 1 with a forged object handle to leak the allocation; because newly spawned user threads inherit the parent's resource_pool (kernel/thread.c), an attacker spawns sacrificial threads to repeat the leak until the shared kernel heap is exhausted. Once depleted, legitimate kernel allocations from that pool (k_queue alloc nodes, k_msgq buffers, future k_poll calls, etc.) fail, causing a system-level denial of service.\n\nThe fix replaces each inline K_OOPS with a conditional goto oops_free so the buffer is freed before the thread is killed. Affects Zephyr releases from v1.12.0 (when k_poll was first exposed to user mode) through v4.4.1.","status":"published","published":"2026-07-21T22:16:59.923Z","modified":"2026-10-24T19:10:00.127Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H","level":"medium","assessor":"secondary"}],"cwes":["CWE-401"],"updated_at":"2026-11-02T14:12:31.394335Z"}],"osv":[{"id":"CVE-2026-10677","title":"Kernel heap memory leak in `z_vrfy_k_poll()` lets an unprivileged user thread exhaust the kernel resource pool","description":"The CONFIG_USERSPACE syscall verifier z_vrfy_k_poll() in kernel/poll.c allocates a kernel-side copy of the user-supplied k_poll_event[] via z_thread_malloc() and then validates each event's object handle. Before this fix, validation used K_OOPS(K_SYSCALL_OBJ(...)) inline inside the loop, which kills the calling thread without freeing events_copy.\n\nA user thread can pass num_events \u003e= 1 with a forged object handle to leak the allocation; because newly spawned user threads inherit the parent's resource_pool (kernel/thread.c), an attacker spawns sacrificial threads to repeat the leak until the shared kernel heap is exhausted. Once depleted, legitimate kernel allocations from that pool (k_queue alloc nodes, k_msgq buffers, future k_poll calls, etc.) fail, causing a system-level denial of service.\n\nThe fix replaces each inline K_OOPS with a conditional goto oops_free so the buffer is freed before the thread is killed. Affects Zephyr releases from v1.12.0 (when k_poll was first exposed to user mode) through v4.4.1.","status":"published","published":"2026-07-21T21:30:54.69Z","modified":"2026-11-05T08:04:26.113383284Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H","level":"medium"}],"cwes":["CWE-401"],"updated_at":"2026-11-05T09:08:14.330889Z"}]}}
