{"id":"CVE-2026-79978","kind":"vulnerability","aliases":["CVE-2026-79978"],"related":[],"title":"Zephyr: ADXL345 FIFO streaming writes past RTIO buffer end","description":"The RTIO streaming completion callback adxl345_process_fifo_samples_cb() in drivers/sensor/adi/adxl345/adxl345_stream.c clamps the amount of FIFO data it will report (read_len = MIN(fifo_bytes, buf_avail)) to the space actually returned by rtio_sqe_rx_buf(), but then queues one 6-byte bus read per hardware FIFO entry at consecutive offsets from read_buf, bounded by the device-reported entry count rather than by the clamp. When the allocated buffer is smaller than a full batch, the driver writes up to 186 bytes past the end of the allocation; a companion defect left data->fifo_total_bytes un-reset at batch start, so an aborted or errored chain could leave a stale write offset that pushes the next batch's writes out of bounds as well.\n\nA short buffer is an expected, first-class outcome of the RTIO allocator: rtio_block_pool_alloc() walks the requested size down one block at a time until a contiguous run is available, and the driver only demands sizeof(struct adxl345_fifo_data) + 6 bytes as its minimum. Any streaming configuration whose mempool block granularity is smaller than a full FIFO batch (204 bytes) — for example the sensor shell's RTIO_DEFINE_WITH_MEMPOOL(sensor_read_rtio, 8, 8, 32, 64, 4) used by sensor stream <dev> on fifo_wm incl, or the 16-byte-block streaming example in the documentation — takes this path whenever the pool is fragmented or the consuming thread falls behind.\n\nThe out-of-bounds writes are performed by the I2C/SPI RTIO backend (DMA on many SoCs) into the shared RTIO block pool, corrupting neighbouring live buffers or, for a pool smaller than one batch, memory beyond the pool itself. The written bytes are accelerometer samples and the destination follows the allocation, so there is no controllable corruption primitive: the realistic impact is silent corruption of other RTIO consumers' data or a crash. Reaching it requires a board with an interrupt-wired ADXL345 built with CONFIG_ADXL345_STREAM, plus buffer-pool starvation, which a co-resident local workload can induce but which also occurs spontaneously under load; there is no network, USB or radio path to this code.","summary":"The Zephyr ADXL345 accelerometer driver's streaming callback writes FIFO samples beyond the end of a too-small RTIO buffer when the pool is fragmented or starved. The out-of-bounds writes can corrupt neighbouring buffers or crash the system, but the attacker cannot control the written data.","severity":"low","cvss":3.6,"epss":0.00124,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["adxl345","embedded","rtio","runtime","sensors","zephyr"],"not_affected_if":["default-config","large-rtio-blocks","no-adxl345-streaming"],"how_to_check":"- Check whether the board's Kconfig enables `CONFIG_ADXL345_STREAM` with an interrupt-wired ADXL345.\n- Check the RTIO mempool block size used for streaming (for example `RTIO_DEFINE_WITH_MEMPOOL`) and whether it is smaller than a 204-byte FIFO batch.\n- Check the Zephyr version in use against the fixed release.","fix":"- Upgrade Zephyr to a release that includes the fix for this ADXL345 driver (fixed version: unknown from the sources).\n- Until patched, avoid `CONFIG_ADXL345_STREAM` or use RTIO mempool blocks of at least 204 bytes.","status":"open","published_at":"2026-10-23T20:17:27+00:00","first_seen_at":"2026-10-23T21:57:34+00:00","triaged_at":"2026-10-25T04:45:23+00:00","updated_at":"2026-10-25T12:38:49+00:00","category":"runtime","confidence":0.7,"triage":{"at":"2026-10-25T04:45:23Z","model":"claude-haiku-5-5","output":{"fix":"- Upgrade Zephyr to a release that includes the fix for this ADXL345 driver (fixed version: unknown from the sources).\n- Until patched, avoid `CONFIG_ADXL345_STREAM` or use RTIO mempool blocks of at least 204 bytes.","reach":"local","title":"Zephyr: ADXL345 FIFO streaming writes past RTIO buffer end","impact":"medium","summary":"The Zephyr ADXL345 accelerometer driver's streaming callback writes FIFO samples beyond the end of a too-small RTIO buffer when the pool is fragmented or starved. The out-of-bounds writes can corrupt neighbouring buffers or crash the system, but the attacker cannot control the written data.","category":"runtime","nicknames":[],"who_cares":["zephyr","embedded","sensors","adxl345","rtio"],"confidence":0.7,"needs_auth":"no","worst_case":"Silent corruption of other RTIO buffers or a device crash.","analyst_note":"Find the fixed Zephyr release and patch commit for adxl345_stream.c from the NVD entry, since the sources give no fixed version.","how_to_check":"- Check whether the board's Kconfig enables `CONFIG_ADXL345_STREAM` with an interrupt-wired ADXL345.\n- Check the RTIO mempool block size used for streaming (for example `RTIO_DEFINE_WITH_MEMPOOL`) and whether it is smaller than a 204-byte FIFO batch.\n- Check the Zephyr version in use against the fixed release.","needs_analyst":true,"not_affected_if":["default-config","no-adxl345-streaming","large-rtio-blocks"],"who_is_affected":"Only Zephyr builds that enable the ADXL345 streaming option on an interrupt-wired ADXL345, and that use RTIO memory pools with blocks smaller than one full FIFO batch. Starvation of the buffer pool, which can come from other local workloads or from load, is needed to trigger the out-of-bounds path. Boards without the ADXL345 streaming driver, or with larger block sizes, are not exposed.","user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"low"},"cost_usd":0.00079,"input_tokens":4003,"output_tokens":780,"severity_before":"low"},"analyst_status":null,"analyst_note":null,"search":"'-2026':11A,14A '-79978':12A,15A '16':295C '186':156C '204':265C '32':282C '4':284C '6':114C,246C '64':283C '8':280C,281C 'abort':180C 'acceleromet':25B,362C 'actual':103C 'adxl345':2A,16B,24B,77C,243C,401C,405C 'alloc':143C,163C,215C,219C,369C 'also':423C 'amount':86C 'attack':66B 'avail':99C,235C 'backend':330C 'batch':150C,176C,194C,264C,352C 'behind':317C 'beyond':33B,354C 'block':217C,226C,256C,298C,339C 'board':395C 'bound':54B,128C,199C,322C 'buf':98C,109C,127C 'buffer':8A,42B,59B,144C,204C,344C,409C 'buffer-pool':408C 'built':402C 'bus':116C 'byte':97C,115C,157C,171C,247C,266C,297C,360C 'byte-block':296C 'callback':29B,76C 'cannot':67B 'cb':81C 'chain':183C 'clamp':84C,140C 'class':210C 'co':415C 'co-resid':414C 'code':438C 'companion':165C 'complet':75C 'config':404C 'configur':253C 'consecut':123C 'consum':314C,386C 'contigu':232C 'control':68B,374C 'corrupt':57B,341C,375C,382C 'could':184C 'count':135C 'crash':61B,390C 'cve':10A,13A 'data':71B,89C,168C,245C,387C 'defect':166C 'defin':274C 'demand':240C 'destin':366C 'devic':132C 'device-report':131C 'dma':331C 'document':303C 'driver':26B,152C,238C 'drivers/sensor/adi/adxl345/adxl345_stream.c':83C 'embed':17B 'end':9A,35B,160C 'entri':121C,134C 'error':182C 'exampl':268C,300C 'expect':207C 'fall':316C 'fifo':3A,31B,79C,88C,96C,120C,169C,244C,263C,290C 'first':209C 'first-class':208C 'follow':367C 'fragment':47B,311C 'full':149C,262C 'granular':257C 'hardwar':119C 'i2c/spi':328C 'impact':379C 'incl':292C 'induc':420C 'interrupt':399C 'interrupt-wir':398C 'leav':185C 'left':167C 'len':94C 'live':343C 'load':427C 'local':417C 'mani':333C 'memori':353C 'mempool':255C,276C 'min':95C 'minimum':250C 'neighbour':58B,342C 'network':431C 'next':193C 'occur':424C 'offset':124C,189C 'one':113C,225C,351C 'out-of-bound':51B,319C 'outcom':211C 'past':6A,158C 'path':306C,435C 'per':118C 'perform':325C 'plus':407C 'pool':45B,218C,309C,340C,348C,356C,410C 'primit':376C 'process':78C 'push':191C 'queue':112C 'radio':434C 'rather':136C 'reach':391C 'read':93C,117C,126C,278C 'realist':378C 'report':92C,133C 'request':222C 'requir':393C 'reset':174C 'resid':416C 'return':104C 'rtio':7A,18B,41B,73C,106C,214C,216C,273C,279C,329C,338C,385C 'run':233C 'runtim':19B 'rx':108C 'sampl':32B,80C,363C 'sensor':20B,270C,277C,287C 'share':337C 'shell':271C 'short':203C 'silent':381C 'size':223C 'sizeof':241C 'small':40B 'smaller':146C,259C,349C 'soc':334C 'space':102C 'spontan':425C 'sqe':107C 'stale':187C 'start':177C 'starv':49B 'starvat':411C 'stream':4A,28B,74C,252C,288C,299C,406C 'struct':242C 'system':63B 'take':304C 'thread':315C 'time':229C 'too-smal':38B 'total':170C 'un':173C 'un-reset':172C 'usb':432C 'use':285C 'walk':220C 'well':201C 'whenev':307C 'whose':254C 'wire':400C 'wm':291C 'workload':418C 'write':5A,30B,55B,153C,188C,196C,323C 'written':70B,359C 'zephyr':1A,21B,23B","nicknames":[],"mitigations":[],"who_affected":"Only Zephyr builds that enable the ADXL345 streaming option on an interrupt-wired ADXL345, and that use RTIO memory pools with blocks smaller than one full FIFO batch. Starvation of the buffer pool, which can come from other local workloads or from load, is needed to trigger the out-of-bounds path. Boards without the ADXL345 streaming driver, or with larger block sizes, are not exposed.","tier":"C","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-23T20:17:27+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:L","cvss_by":"vulnerabilities@zephyrproject.org","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-79978","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-79978","severity":null,"published_at":"2026-10-23T20:17:27+00:00","modified_at":"2026-10-23T20:17:27+00:00","first_seen_at":"2026-10-23T21:57:34+00:00","fetched_at":"2026-10-23T22:29:04+00:00","note":null},{"source":"epss","external_id":"CVE-2026-79978","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-79978","severity":null,"published_at":null,"modified_at":null,"first_seen_at":"2026-10-25T12:38:49+00:00","fetched_at":"2026-10-25T12:38:49+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"}