Unbounded count in memx_fops_read copy_to_user — possible kernel memory disclosure

Ok i am going to be super clear, i am not a programmer, i have worked in software for 20 years including security enviroments that include TLA. So when i see an AI unsolicitedly tell me it found a potential buffer ovelow i am both sketpical but pay attenttion. The text below is claudes analysis after i pushed it several time to make sure i dont end up looking stupid for speaking up. I would prefer to look stupid than not pass on a real issue. So with that…


Flagging a possible out-of-bounds read in the PCIe driver’s read path. Up front: I found this with AI-assisted analysis while looking at an unrelated logging change, and I haven’t exploited it or fully traced the userspace side, so please treat it as something to verify against the intended read() contract rather than a confirmed CVE.

In kdriver/linux/pcie/memx_cascade_pciemain.c, memx_fops_read() copies the user-supplied count directly:

if (copy_to_user((void __user *)buf, memx_dev->mpu_data.rx_dma_coherent_buffer_virtual_base, count)) {

count comes straight from read(2) and isn’t bounded against the source buffer. That buffer is a single ~2 MB kzalloc allocation (DMA_COHERENT_BUFFER_SIZE_2MB + cache_line_size()), of which a real output map is at most 512 KB. A read() with count larger than the allocation copies adjacent kernel memory out to userspace until copy_to_user faults, leaking kernel heap contents (kernel pointers, etc.).

The reason I think it’s worth a look rather than purely theoretical: the device node is created 0666 (DEVICE_NODE_DEFAULT_ACCESS_RIGHT), so any local user can open it, and the copy is reachable after a normal inference completes. The same pattern is in the 32bit_driver/ copy.

Normal SDK use does appear bounded — the in-repo Python wrapper sizes its reads from memx_get_ofmap_size(), and the demo test app reads a fixed 4 bytes — so legitimate traffic shouldn’t trip this. But the actual read() call lives inside the closed libmemx.so (no source in the repo, only the ARM32 blob), so I couldn’t confirm the syscall-level count directly. And it doesn’t really matter where the bound is: with a 0666 node, an unprivileged process can bypass the SDK entirely and pass an arbitrary count straight to the syscall, so the kernel shouldn’t rely on userspace to bound it.

Suggested fix is to reject or clamp before the copy, e.g.:

if (count > OFMAP_EGRESS_DCORE_DMA_COHERENT_BUFFER_SIZE_512KB)
    return -EINVAL;

or clamp to the actual payload length the header already exposes (the total-length field read at buffer offset 12). Tightening the node would help as defense in depth, but note it isn’t a drop-in change: the devnode callback only sets the mode, so the node comes up root:root, and going to 0660 without also assigning a group would lock out non-root processes (including a containerized Frigate). Doing it properly means a dedicated group, a udev rule to set group ownership, and adding the service account to that group — the usual render/video pattern. Given that, the count clamp is the more important and self-contained fix.