🇰🇷 한글 설명
Zephyr RTOS의 ESP32 I2S 드라이버에서 방향(direction) 검증 미흡으로 인해 발생하는 NULL 포인터 역참조 취약점입니다. 사용자 모드 스레드가 권한이 있는 I2S 장치에 대해 지원되지 않는 방향으로 i2s_trigger()를 호출할 경우, 커널 모드에서 주소 0을 읽으려 시도하여 시스템이 중단됩니다. 이로 인해 비특권 사용자 모드 스레드가 시스템 전체에 대한 서비스 거부(DoS)를 유발할 수 있습니다.
💡 쉬운 설명
오디오 장치를 제어하는 소프트웨어에서 잘못된 명령을 내렸을 때, 이를 제대로 확인하지 못해 시스템이 갑자기 멈춰버리는 문제입니다. 해커가 이 취약점을 이용하면 기기를 정상적으로 작동하지 못하게 만들 수 있습니다.
🇺🇸 원문 (English)
i2s_esp32_trigger_check() in drivers/i2s/i2s_esp32.c validates the requested direction only for I2S_DIR_BOTH. The I2S_DIR_RX and I2S_DIR_TX branches read dev_cfg->rx.data->configured / dev_cfg->tx.data->configured without first checking the stream pointers. The device instantiation macro I2S_ESP32_STREAM_INIT() sets both .conf and .data to NULL for a direction the devicetree does not describe, so on an instance that wires only one direction — the normal shape for audio output or a worldsemi,ws2812-i2s LED strip — the other direction dereferences a NULL pointer instead of returning an error.
i2s_trigger() is a Zephyr syscall, and z_vrfy_i2s_trigger() in drivers/i2s/i2s_handlers.c validates only the device object and the presence of the trigger API pointer; the dir argument is passed to the driver unvalidated. On a build with CONFIG_USERSPACE enabled, a user-mode thread that has been granted the I2S device can issue a single i2s_trigger() call naming the unwired direction and cause a load from address 0 in kernel mode. Among the Espressif parts that carry this driver, userspace is available in-tree only on RISC-V SoCs with CONFIG_RISCV_PMP, and v4.4.0 is the first release where that is buildable: the ESP32-C6 HPCORE selects RISCV_PMP when it is not built for MCUboot. ESP32-C5 in v4.4.x carries the same PMP-region and userspace linker support but does not select RISCV_PMP by default. Espressif Xtensa targets do not support Zephyr userspace, and in a non-userspace build the bad direction can only come from in-kernel application code.
The impact is limited to availability: the access is a read at offset 0 of the missing stream structure, so there is no attacker-controlled offset, no write primitive and no information disclosure. With the default fatal-error handler the resulting exception halts the system, giving an unprivileged user-mode thread a system-wide denial of service. The fix adds the same pointer check the I2S_DIR_BOTH branch already performed and returns -ENOSYS for a direction the instance does not implement; the driver's other entry points (i2s_esp32_config_check(), i2s_esp32_config_get(), i2s_esp32_read(), i2s_esp32_write()) already guarded the pointers, and a static audit found no equivalent unguarded path.
The driver defect is older than the affected range. The unguarded dereference is present from v4.2.0 (reached through i2s_esp32_trigger_stream(), whose if (stream) guard tests the address of a struct member and is never false) and takes its present i2s_esp32_trigger_check() form in v4.3.0. No in-tree Espressif configuration before v4.4.0 can run a user-mode thread, so in v4.2.x and v4.3.x the direction argument can only come from trusted kernel code. Those releases carry the bug but are not listed as affected; the fix has also been merged to v4.3-branch as hardening.
📍 영향받는 시스템
Zephyr RTOS v4.4.0 이상 (RISC-V SoC 기반 ESP32-C6 등 사용자 모드 지원 환경)
⚔️ 공격 벡터
I2S 장치 권한을 가진 사용자 모드 스레드가 지원되지 않는 방향(unwired direction)으로 i2s_trigger() 시스템 콜 호출
🛡️ 대응 방법
I2S 드라이버의 i2s_esp32_trigger_check() 함수에 스트림 포인터 유효성 검사 로직을 추가하여 패치된 최신 버전으로 업데이트
🔧 검증 코드
출력된 버전이 취약점이 존재하는 v4.4.0 이상인지 확인합니다.
zephyr-sdk-version | grep -E 'v4.4.0|v4.5.0'