{"id":"CVE-2026-79976","kind":"vulnerability","aliases":["CVE-2026-79976"],"related":[],"title":"Zephyr: stale I2C register state causes NULL dereference in MCTP target","description":"The MCTP-over-I2C+GPIO target binding in subsys/pmci/mctp/mctp_i2c_gpio_target.c emulates a small pseudo-register file, where the bus controller first writes a register number and then writes or reads payload bytes. The selected register (b->reg_addr) and the data-phase flag (b->rxtx) were never cleared when the controller issued an I2C STOP, so after a completed transfer the target still had a data register selected while the packet buffer that register refers to had already been consumed and set to NULL by mctp_i2c_gpio_target_stop().\n\nA controller on the bus can re-enter the same branch of mctp_i2c_gpio_target_stop() with a NULL buffer using two ordinary transactions and no authentication: first a normal packet write to MCTP_I2C_GPIO_RX_MSG_ADDR followed by STOP (which delivers and frees b->rx_pkt), then a bare read transaction followed by STOP. The failing read_requested() call leaves the stale state untouched and the I2C driver still delivers the STOP callback, which then calls mctp_bus_rx() with a NULL packet. The symmetric case exists on the transmit side, where the stale MCTP_I2C_GPIO_TX_MSG_ADDR selection dereferences b->tx_pkt->end after b->tx_pkt has been cleared and additionally signals b->tx_complete a second time, causing the next outbound packet to be dropped.\n\nThe dereference happens in the I2C target interrupt handler, so on any target that traps accesses to address 0 the result is a fatal exception and a device reset or halt — a denial of service inflicted by any device able to act as controller on the shared management bus (for example compromised firmware on a peer MCTP endpoint or on the BMC). On parts where address 0 is readable, the impact degrades to a malformed packet buffer being handed to the MCTP stack and lost transmit packets. No attacker-controlled value is written and no confidentiality or integrity boundary is crossed.\n\nThe fix resets b->reg_addr to MCTP_I2C_GPIO_INVALID_ADDR and clears b->rxtx at every STOP, so a new register must be selected before any data phase can run again. Only builds that opt into the experimental CONFIG_MCTP subsystem with CONFIG_MCTP_I2C_GPIO_TARGET=y are affected.","summary":"The MCTP-over-I2C+GPIO target driver keeps a selected register and data-phase flag after an I2C STOP, so a second bus transaction can reach a path that uses a NULL packet buffer. A device acting as bus controller can crash the target with a fatal exception, a denial of service, and on parts where address 0 is readable the transmit path can drop packets.","severity":"high","cvss":7.1,"epss":0.00207,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["bmc","embedded","i2c","mctp","runtime","zephyr"],"not_affected_if":["default-config","mctp-disabled"],"how_to_check":"- Check whether the build enables `CONFIG_MCTP` and `CONFIG_MCTP_I2C_GPIO_TARGET=y` in its configuration\n- Confirm the firmware source includes `subsys/pmci/mctp/mctp_i2c_gpio_target.c`\n- Check the Zephyr version in use against the fixed release (unknown from sources)","fix":"- Apply the upstream fix that resets `b->reg_addr` to `MCTP_I2C_GPIO_INVALID_ADDR` and clears `b->rxtx` at every STOP\n- Disable `CONFIG_MCTP_I2C_GPIO_TARGET` if the MCTP I2C+GPIO target is not needed (unknown whether this is the only mitigation)\n- Fixed version: unknown from sources","status":"open","published_at":"2026-10-21T19:17:04+00:00","first_seen_at":"2026-10-23T21:57:29+00:00","triaged_at":"2026-10-25T03:31:46+00:00","updated_at":"2026-10-25T03:31:46+00:00","category":"runtime","confidence":0.6,"triage":{"at":"2026-10-25T03:31:46Z","model":"claude-haiku-5-5","output":{"fix":"- Apply the upstream fix that resets `b->reg_addr` to `MCTP_I2C_GPIO_INVALID_ADDR` and clears `b->rxtx` at every STOP\n- Disable `CONFIG_MCTP_I2C_GPIO_TARGET` if the MCTP I2C+GPIO target is not needed (unknown whether this is the only mitigation)\n- Fixed version: unknown from sources","reach":"network","title":"Zephyr: stale I2C register state causes NULL dereference in MCTP target","impact":"low","summary":"The MCTP-over-I2C+GPIO target driver keeps a selected register and data-phase flag after an I2C STOP, so a second bus transaction can reach a path that uses a NULL packet buffer. A device acting as bus controller can crash the target with a fatal exception, a denial of service, and on parts where address 0 is readable the transmit path can drop packets.","category":"runtime","nicknames":[],"who_cares":["zephyr","embedded","mctp","bmc","i2c"],"confidence":0.6,"needs_auth":"no","worst_case":"Fatal exception halts or resets the device, denying service on the bus","analyst_note":"Confirm the fixed Zephyr version and the exact affected release range from the NVD entry and the upstream advisory.","how_to_check":"- Check whether the build enables `CONFIG_MCTP` and `CONFIG_MCTP_I2C_GPIO_TARGET=y` in its configuration\n- Confirm the firmware source includes `subsys/pmci/mctp/mctp_i2c_gpio_target.c`\n- Check the Zephyr version in use against the fixed release (unknown from sources)","needs_analyst":true,"not_affected_if":["default-config","mctp-disabled"],"who_is_affected":"Only builds that opt into the experimental MCTP subsystem with the I2C+GPIO target binding enabled are exposed. The exposure is through the shared management bus, where any device able to act as I2C controller, such as compromised firmware on a peer MCTP endpoint or a BMC, can trigger it. Systems without that configuration can skip it.","user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"high"},"cost_usd":0.000796,"input_tokens":4074,"output_tokens":777,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-2026':13A,16A '-79976':14A,17A '0':83B,337C,385C 'abl':358C 'access':334C 'act':62B,360C 'addit':303C 'addr':130C,224C,288C,426C,432C 'address':82B,336C,384C 'affect':472C 'alreadi':171C 'attack':408C 'attacker-control':407C 'authent':212C 'b':128C,137C,232C,291C,296C,305C,424C,435C 'bare':237C 'bind':99C 'bmc':18B,380C 'boundari':418C 'branch':195C 'buffer':59B,165C,205C,395C 'build':455C 'bus':48B,64B,111C,188C,266C,367C 'byte':124C 'call':247C,264C 'callback':261C 'case':274C 'caus':6A,311C 'clear':141C,301C,434C 'complet':152C,307C 'compromis':370C 'confidenti':415C 'config':461C,465C 'consum':173C 'control':65B,112C,144C,185C,362C,409C 'crash':67B 'cross':420C 'cve':12A,15A 'data':38B,134C,159C,449C 'data-phas':37B,133C 'degrad':390C 'deliv':229C,258C 'denial':75B,351C 'derefer':8A,290C,320C 'devic':61B,346C,357C 'driver':31B,256C 'drop':90B,318C 'embed':19B 'emul':102C 'end':294C 'endpoint':376C 'enter':192C 'everi':438C 'exampl':369C 'except':73B,343C 'exist':275C 'experiment':460C 'fail':244C 'fatal':72B,342C 'file':108C 'firmwar':371C 'first':113C,213C 'fix':422C 'flag':40B,136C 'follow':225C,240C 'free':231C 'gpio':29B,97C,181C,199C,221C,285C,430C,468C 'halt':349C 'hand':397C 'handler':327C 'happen':321C 'i2c':3A,20B,28B,43B,96C,147C,180C,198C,220C,255C,284C,324C,429C,467C 'impact':389C 'inflict':354C 'integr':417C 'interrupt':326C 'invalid':431C 'issu':145C 'keep':32B 'leav':248C 'lost':403C 'malform':393C 'manag':366C 'mctp':10A,21B,26B,94C,179C,197C,219C,265C,283C,375C,400C,428C,462C,466C 'mctp-over-i2c':25B,93C 'msg':223C,287C 'must':444C 'never':140C 'new':442C 'next':313C 'normal':215C 'null':7A,57B,177C,204C,270C 'number':117C 'opt':457C 'ordinari':208C 'outbound':314C 'packet':58B,91B,164C,216C,271C,315C,394C,405C 'part':80B,382C 'path':53B,88B 'payload':123C 'peer':374C 'phase':39B,135C,450C 'pkt':234C,293C,298C 'pseudo':106C 'pseudo-regist':105C 're':191C 're-ent':190C 'reach':51B 'read':122C,238C,245C 'readabl':85B,387C 'refer':168C 'reg':129C,425C 'regist':4A,35B,107C,116C,127C,160C,167C,443C 'request':246C 'reset':347C,423C 'result':339C 'run':452C 'runtim':22B 'rx':222C,233C,267C 'rxtx':138C,436C 'second':47B,309C 'select':34B,126C,161C,289C,446C 'servic':77B,353C 'set':175C 'share':365C 'side':279C 'signal':304C 'small':104C 'stack':401C 'stale':2A,250C,282C 'state':5A,251C 'still':156C,257C 'stop':44B,148C,183C,201C,227C,242C,260C,439C 'subsys/pmci/mctp/mctp_i2c_gpio_target.c':101C 'subsystem':463C 'symmetr':273C 'target':11A,30B,69B,98C,155C,182C,200C,325C,331C,469C 'time':310C 'transact':49B,209C,239C 'transfer':153C 'transmit':87B,278C,404C 'trap':333C 'two':207C 'tx':286C,292C,297C,306C 'untouch':252C 'use':55B,206C 'valu':410C 'write':114C,120C,217C 'written':412C 'y':470C 'zephyr':1A,23B","nicknames":[],"mitigations":[],"who_affected":"Only builds that opt into the experimental MCTP subsystem with the I2C+GPIO target binding enabled are exposed. The exposure is through the shared management bus, where any device able to act as I2C controller, such as compromised firmware on a peer MCTP endpoint or a BMC, can trigger it. Systems without that configuration can skip it.","tier":"B","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-21T19:17:04+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H","cvss_by":"vulnerabilities@zephyrproject.org","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-79976","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-79976","severity":null,"published_at":"2026-10-21T19:17:04+00:00","modified_at":"2026-10-23T22:17:01+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-79976","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-79976","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"}