{"id":"CVE-2026-85035","kind":"vulnerability","aliases":["CVE-2026-85035"],"related":[],"title":"Zephyr: CAN filter keeps freed message queue pointer, enabling kernel heap corruption","description":"The can_add_rx_filter_msgq() system call installs a CAN RX filter whose callback (can_msgq_put() in drivers/can/can_common.c) is handed the caller's struct k_msgq * as user_data. The controller driver stores that raw pointer in its filter table and dereferences it from the RX path every time a matching frame arrives. The system call verifier z_vrfy_can_add_rx_filter_msgq() in drivers/can/can_handlers.c validated the queue only with K_SYSCALL_OBJ(), which is a point-in-time check of type, initialization and caller permission and says nothing about the object's lifetime.\n\nOn a build with CONFIG_USERSPACE=y and CONFIG_DYNAMIC_OBJECTS=y, an unprivileged user-mode thread that has been granted access to a CAN device can obtain a message queue whose lifetime it fully controls: k_object_alloc(K_OBJ_MSGQ) followed by k_msgq_alloc_init(). The lifetime of such an object is driven solely by its permission bitmask, and a pointer retained by the kernel is not represented there. After registering the filter, the thread calls k_object_release() — or simply terminates — and unref_check() frees the struct k_msgq storage while the CAN driver still holds the pointer.\n\nThe next matching CAN frame causes k_msgq_put() to run in supervisor context against freed memory that the attacker can have groomed with another kernel allocation: the frame payload is memcpy()d through the reused block's write_ptr, and the queue's wait_q (and poll_events under CONFIG_POLL) list nodes are manipulated. This yields kernel-heap corruption reachable from a user-mode thread, defeating the isolation CONFIG_USERSPACE is intended to provide; the same dangling pointer also arises benignly when an application thread exits without calling can_remove_rx_filter().\n\nThe fix validates the queue with K_SYSCALL_OBJ_STATIC(), which additionally rejects objects carrying K_OBJ_FLAG_ALLOC, so only statically defined queues (CAN_MSGQ_DEFINE()) may be registered from user mode. Supervisor-mode callers bypass the verifier and must themselves keep the queue valid until the filter is removed.","summary":"Zephyr's CAN receive filter API can be given a dynamically allocated message queue that a user-mode thread can free while the CAN driver still holds a pointer to it. When a matching CAN frame arrives, the kernel writes into freed memory, which lets a user-mode thread corrupt kernel heap and escape the isolation that CONFIG_USERSPACE provides.","severity":"high","cvss":8.8,"epss":null,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["can-bus","embedded","runtime","userspace","zephyr"],"not_affected_if":["no-can-driver","no-dynamic-objects","no-userspace","static-msgq-only"],"how_to_check":"- Check whether the build sets `CONFIG_USERSPACE=y` and `CONFIG_DYNAMIC_OBJECTS=y` together with a CAN driver.\n- Search the application for calls to `can_add_rx_filter_msgq()` and confirm the queues are defined with `CAN_MSGQ_DEFINE()`, not allocated at runtime.\n- Check the Zephyr version in use against the fixed release named in the patch.","fix":"- Zephyr: move to the release that includes the patch linked in the sources (version not stated in the sources provided).","status":"open","published_at":"2026-11-03T14:17:39+00:00","first_seen_at":"2026-11-03T14:21:08+00:00","triaged_at":"2026-11-03T14:22:05+00:00","updated_at":"2026-11-03T14:22:05+00:00","category":"runtime","confidence":0.8,"triage":{"at":"2026-11-03T14:22:05Z","model":"claude-haiku-5-5","output":{"fix":"- Zephyr: move to the release that includes the patch linked in the sources (version not stated in the sources provided).","reach":"local","title":"Zephyr: CAN filter keeps freed message queue pointer, enabling kernel heap corruption","impact":"high","summary":"Zephyr's CAN receive filter API can be given a dynamically allocated message queue that a user-mode thread can free while the CAN driver still holds a pointer to it. When a matching CAN frame arrives, the kernel writes into freed memory, which lets a user-mode thread corrupt kernel heap and escape the isolation that CONFIG_USERSPACE provides.","audience":"developers","category":"runtime","nicknames":[],"who_cares":["zephyr","embedded","can-bus","userspace"],"confidence":0.8,"fix_status":"available","needs_auth":"yes","worst_case":"unprivileged user thread corrupts kernel heap memory","analyst_note":"Confirm the fixed Zephyr version from the linked patch and advisory; the sources given do not name it.","how_to_check":"- Check whether the build sets `CONFIG_USERSPACE=y` and `CONFIG_DYNAMIC_OBJECTS=y` together with a CAN driver.\n- Search the application for calls to `can_add_rx_filter_msgq()` and confirm the queues are defined with `CAN_MSGQ_DEFINE()`, not allocated at runtime.\n- Check the Zephyr version in use against the fixed release named in the patch.","plain_action":"","needs_analyst":true,"not_affected_if":["no-can-driver","static-msgq-only","no-userspace","no-dynamic-objects"],"who_is_affected":"Applications built on Zephyr that use CAN receive filters with message queues and run user-mode threads on a build with dynamic kernel objects enabled. The risk comes from dynamically allocated queues passed to the filter API; applications that define all queues statically with CAN_MSGQ_DEFINE() are not exposed through this path. Builds without CONFIG_USERSPACE or without CONFIG_DYNAMIC_OBJECTS can skip it.","user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"high"},"cost_usd":0.000868,"input_tokens":4820,"output_tokens":772,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-2026':14A,17A '-85035':15A,18A 'access':208C 'add':90C,150C 'addit':396C 'alloc':37B,225C,233C,315C,403C 'also':371C 'anoth':313C 'api':31B 'applic':376C 'aris':372C 'arriv':63B,142C 'attack':308C 'benign':373C 'bitmask':247C 'block':325C 'build':188C 'bus':21B 'bypass':422C 'call':95C,145C,265C,380C 'callback':102C 'caller':111C,176C,421C 'can-bus':19B 'carri':399C 'caus':294C 'check':171C,274C 'config':85B,190C,194C,339C,361C 'context':302C 'control':120C,222C 'corrupt':12A,77B,350C 'cve':13A,16A 'd':321C 'dangl':369C 'data':118C 'defeat':358C 'defin':407C,411C 'derefer':131C 'devic':212C 'driven':242C 'driver':51B,121C,284C 'drivers/can/can_common.c':107C 'drivers/can/can_handlers.c':155C 'dynam':36B,195C 'embed':22B 'enabl':9A 'escap':81B 'event':337C 'everi':137C 'exit':378C 'filter':3A,30B,92C,100C,128C,152C,262C,384C,434C 'fix':386C 'flag':402C 'follow':229C 'frame':62B,141C,293C,317C 'free':47B,275C 'freed':5A,68B,304C 'fulli':221C 'given':34B 'grant':207C 'groom':311C 'hand':109C 'heap':11A,79B,349C 'hold':53B,286C 'init':234C 'initi':174C 'instal':96C 'intend':364C 'isol':83B,360C 'k':114C,161C,223C,226C,231C,266C,278C,295C,391C,400C 'keep':4A,428C 'kernel':10A,65B,78B,254C,314C,348C 'kernel-heap':347C 'let':71B 'lifetim':185C,219C,236C 'list':341C 'manipul':344C 'match':60B,140C,291C 'may':412C 'memcpi':320C 'memori':69B,305C 'messag':6A,38B,216C 'mode':44B,75B,202C,356C,417C,420C 'msgq':93C,104C,115C,153C,228C,232C,279C,296C,410C 'must':426C 'next':290C 'node':342C 'noth':180C 'obj':163C,227C,393C,401C 'object':183C,196C,224C,240C,267C,398C 'obtain':214C 'path':136C 'payload':318C 'permiss':177C,246C 'point':168C 'point-in-tim':167C 'pointer':8A,55B,125C,250C,288C,370C 'poll':336C,340C 'provid':87B,366C 'ptr':328C 'put':105C,297C 'q':334C 'queue':7A,39B,158C,217C,331C,389C,408C,430C 'raw':124C 'reachabl':351C 'receiv':29B 'regist':260C,414C 'reject':397C 'releas':268C 'remov':382C,436C 'repres':257C 'retain':251C 'reus':324C 'run':299C 'runtim':23B 'rx':91C,99C,135C,151C,383C 'say':179C 'simpli':270C 'sole':243C 'static':394C,406C 'still':52B,285C 'storag':280C 'store':122C 'struct':113C,277C 'supervisor':301C,419C 'supervisor-mod':418C 'syscal':162C,392C 'system':94C,144C 'tabl':129C 'termin':271C 'thread':45B,76B,203C,264C,357C,377C 'time':138C,170C 'type':173C 'unprivileg':199C 'unref':273C 'user':43B,74B,117C,201C,355C,416C 'user-mod':42B,73B,200C,354C 'userspac':24B,86B,191C,362C 'valid':156C,387C,431C 'verifi':146C,424C 'vrfi':148C 'wait':333C 'whose':101C,218C 'without':379C 'write':66B,327C 'y':192C,197C 'yield':346C 'z':147C 'zephyr':1A,25B,26B","nicknames":[],"mitigations":[],"who_affected":"Applications built on Zephyr that use CAN receive filters with message queues and run user-mode threads on a build with dynamic kernel objects enabled. The risk comes from dynamically allocated queues passed to the filter API; applications that define all queues statically with CAN_MSGQ_DEFINE() are not exposed through this path. Builds without CONFIG_USERSPACE or without CONFIG_DYNAMIC_OBJECTS can skip it.","tier":"B","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":[],"ptokens":[],"labels":["canbus","embedded","high","runtime","userspace","zephyr"],"first_public_at":"2026-11-02T22:19:56+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","cvss_by":"vulnerabilities@zephyrproject.org","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-85035","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-85035","severity":null,"published_at":"2026-11-03T14:17:39+00:00","modified_at":"2026-11-03T14:17:39+00:00","first_seen_at":"2026-11-03T14:21:08+00:00","fetched_at":"2026-11-03T14:21:08+00:00","note":null}],"documents":[{"id":58022,"url":"https://github.com/zephyrproject-rtos/zephyr/commit/0114bee266211c72a49f3b6a914d3eaf821dd460","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":58023,"url":"https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-6pxv-r7ww-3g2q","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-11-02T22:19:56+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"}],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}