{"id":"CVE-2026-19947","kind":"vulnerability","aliases":["CVE-2026-19947"],"related":[],"title":"Zephyr: unprivileged user threads can switch devmux console routing","description":"The device multiplexer pseudo-driver in drivers/misc/devmux/devmux.c exposes two system calls, devmux_select_get() and devmux_select_set(). When CONFIG_USERSPACE is enabled, their user-mode verifiers z_vrfy_devmux_select_get() and z_vrfy_devmux_select_set() forwarded directly to the kernel implementations without performing any kernel-object validation — no k_object_access_check() and no driver object check. Compounding this, DEVICE_DT_INST_DEFINE() registered devmux instances with a NULL driver API pointer, which causes scripts/build/gen_kobject_list.py to skip them entirely, so a devmux device had no struct k_object and no permission on it could be granted or withheld in the first place.\n\nAny thread running in user mode can reach the defect: device pointers such as DEVICE_DT_GET(DT_NODELABEL(devmux0)) are compile-time constants available to application code, and the syscall accepted them from a thread that had never been granted access to the device. The kernel implementations do validate the pointer against the static devmux instance table and bounds-check the selection index, so this is not a memory-safety issue; the failure is purely one of authorization. Exposure requires CONFIG_USERSPACE=y together with the experimental CONFIG_DEVMUX=y (which depends on CONFIG_DEVICE_MUTABLE) and a zephyr,devmux devicetree node.\n\nAn unprivileged user-mode thread can read and change which downstream device a multiplexer forwards to, bypassing the userspace object-permission model. Because a devmux forwards the data, configuration and API of the selected device — its documented use being zephyr,console and zephyr,shell-uart switching — an attacker can suppress console, log and shell output, redirect that output to a downstream device it is able to observe, or flip the selection underneath another thread that is legitimately using the multiplexer. The impact is bounded to the devicetree-fixed set of downstream devices; no out-of-bounds access or arbitrary pointer dereference is reachable.\n\nThe fix declares __subsystem struct devmux_driver_api and attaches a DEVICE_API(devmux, devmux_api) instance to each devmux device so that it becomes a tracked K_OBJ_DRIVER_DEVMUX kernel object, and adds K_OOPS(devmux_inst_get(dev) == SIZE_MAX) plus K_OOPS(k_object_access_check(dev) != 0) to both verifiers.","summary":"The Zephyr devmux pseudo-driver's user-mode syscalls for reading and changing the selected downstream device skipped the kernel object permission check, so any user-mode thread could use them. An attacker can silence or redirect console, log and shell output, or change the selection under another thread that uses the multiplexer.","severity":"medium","cvss":5.3,"epss":0.00097,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["devicetree","embedded","runtime","userspace","zephyr"],"not_affected_if":["default-config","no-devmux"],"how_to_check":"- Check whether the build sets `CONFIG_USERSPACE=y` and the experimental `CONFIG_DEVMUX=y` in the project configuration.\n- Look for a `zephyr,devmux` node in the devicetree sources.\n- Check the Zephyr version in use against the fixed release, which the sources do not name: unknown.","fix":"- Move Zephyr to a release that includes the devmux verifier fix (version unknown from the sources).\n- Until patched, disable `CONFIG_DEVMUX` if the multiplexer is not needed.","status":"open","published_at":"2026-10-21T19:17:02+00:00","first_seen_at":"2026-10-23T21:57:29+00:00","triaged_at":"2026-10-25T04:20:46+00:00","updated_at":"2026-10-25T04:20:46+00:00","category":"runtime","confidence":0.7,"triage":{"at":"2026-10-25T04:20:46Z","model":"claude-haiku-5-5","output":{"fix":"- Move Zephyr to a release that includes the devmux verifier fix (version unknown from the sources).\n- Until patched, disable `CONFIG_DEVMUX` if the multiplexer is not needed.","reach":"local","title":"Zephyr: unprivileged user threads can switch devmux console routing","impact":"low","summary":"The Zephyr devmux pseudo-driver's user-mode syscalls for reading and changing the selected downstream device skipped the kernel object permission check, so any user-mode thread could use them. An attacker can silence or redirect console, log and shell output, or change the selection under another thread that uses the multiplexer.","category":"runtime","nicknames":[],"who_cares":["zephyr","embedded","userspace","devicetree"],"confidence":0.7,"needs_auth":"yes","worst_case":"Console and shell output suppressed or redirected by unprivileged user thread","analyst_note":"","how_to_check":"- Check whether the build sets `CONFIG_USERSPACE=y` and the experimental `CONFIG_DEVMUX=y` in the project configuration.\n- Look for a `zephyr,devmux` node in the devicetree sources.\n- Check the Zephyr version in use against the fixed release, which the sources do not name: unknown.","needs_analyst":false,"not_affected_if":["default-config","no-devmux"],"who_is_affected":"Only projects that enable the experimental devmux driver together with userspace support and have a zephyr,devmux node in the devicetree are exposed. Projects that build without CONFIG_USERSPACE or without CONFIG_DEVMUX can skip it. The impact is limited to switching between devicetree-fixed downstream devices, with no memory corruption.","user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.000725,"input_tokens":4108,"output_tokens":628,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-19947':12A,15A '-2026':11A,14A '0':450C 'abl':358C 'accept':217C 'access':133C,227C,392C,447C 'add':433C 'anoth':71B,366C 'api':153C,323C,406C,411C,414C 'applic':212C 'arbitrari':394C 'attach':408C 'attack':56B,341C 'author':266C 'avail':210C 'becom':423C 'bound':246C,377C,391C 'bounds-check':245C 'bypass':308C 'call':88C 'caus':156C 'chang':35B,67B,300C 'check':45B,134C,139C,247C,448C 'code':213C 'compil':207C 'compile-tim':206C 'compound':140C 'config':97C,269C,276C,282C 'configur':321C 'consol':8A,61B,333C,344C 'constant':209C 'could':52B,176C 'cve':10A,13A 'data':320C 'declar':401C 'defect':194C 'defin':145C 'depend':280C 'derefer':396C 'dev':439C,449C 'devic':39B,78C,142C,165C,195C,199C,230C,283C,303C,327C,355C,386C,410C,419C 'devicetre':16B,289C,381C 'devicetree-fix':380C 'devmux':7A,23B,89C,93C,108C,114C,147C,164C,241C,277C,288C,317C,404C,412C,413C,418C,429C,436C 'devmux0':204C 'direct':118C 'document':329C 'downstream':38B,302C,354C,385C 'driver':26B,82C,137C,152C,405C,428C 'drivers/misc/devmux/devmux.c':84C 'dt':143C,200C,202C 'embed':17B 'enabl':100C 'entir':161C 'experiment':275C 'expos':85C 'exposur':267C 'failur':261C 'first':183C 'fix':382C,400C 'flip':362C 'forward':117C,306C,318C 'get':91C,110C,201C,438C 'grant':178C,226C 'impact':375C 'implement':122C,233C 'index':250C 'inst':144C,437C 'instanc':148C,242C,415C 'issu':259C 'k':131C,169C,426C,434C,443C,445C 'kernel':42B,121C,127C,232C,430C 'kernel-object':126C 'legitim':370C 'log':62B,345C 'max':441C 'memori':257C 'memory-safeti':256C 'mode':30B,50B,104C,190C,295C 'model':314C 'multiplex':76B,79C,305C,373C 'mutabl':284C 'never':224C 'node':290C 'nodelabel':203C 'null':151C 'obj':427C 'object':43B,128C,132C,138C,170C,312C,431C,446C 'object-permiss':311C 'observ':360C 'one':264C 'oop':435C,444C 'out-of-bound':388C 'output':65B,348C,351C 'perform':124C 'permiss':44B,173C,313C 'place':184C 'plus':442C 'pointer':154C,196C,237C,395C 'pseudo':25B,81C 'pseudo-driv':24B,80C 'pure':263C 'reach':192C 'reachabl':398C 'read':33B,298C 'redirect':60B,349C 'regist':146C 'requir':268C 'rout':9A 'run':187C 'runtim':18B 'safeti':258C 'scripts/build/gen_kobject_list.py':157C 'select':37B,69B,90C,94C,109C,115C,249C,326C,364C 'set':95C,116C,383C 'shell':64B,337C,347C 'shell-uart':336C 'silenc':58B 'size':440C 'skip':40B,159C 'static':240C 'struct':168C,403C 'subsystem':402C 'suppress':343C 'switch':6A,339C 'syscal':31B,216C 'system':87C 'tabl':243C 'thread':4A,51B,72B,186C,221C,296C,367C 'time':208C 'togeth':272C 'track':425C 'two':86C 'uart':338C 'underneath':365C 'unprivileg':2A,292C 'use':53B,74B,330C,371C 'user':3A,29B,49B,103C,189C,294C 'user-mod':28B,48B,102C,293C 'userspac':19B,98C,270C,310C 'valid':129C,235C 'verifi':105C,453C 'vrfi':107C,113C 'withheld':180C 'without':123C 'y':271C,278C 'z':106C,112C 'zephyr':1A,20B,22B,287C,332C,335C","nicknames":[],"mitigations":[],"who_affected":"Only projects that enable the experimental devmux driver together with userspace support and have a zephyr,devmux node in the devicetree are exposed. Projects that build without CONFIG_USERSPACE or without CONFIG_DEVMUX can skip it. The impact is limited to switching between devicetree-fixed downstream devices, with no memory corruption.","tier":"C","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-21T19:17:02+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L","cvss_by":"vulnerabilities@zephyrproject.org","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-19947","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-19947","severity":null,"published_at":"2026-10-21T19:17:02+00:00","modified_at":"2026-10-23T22:16:59+00:00","first_seen_at":"2026-10-23T21:57:29+00:00","fetched_at":"2026-10-23T22:29:02+00:00","note":null},{"source":"epss","external_id":"CVE-2026-19947","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-19947","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"}