GHSA-68cj-3hg4-5vpm: Missing device-pointer validation in flash_copy() syscall allows userspace privilege escalation
The flashcopy() system call is verified by zvrfyflashcopy() in drivers/flash/flashutil.c. On builds with CONFIGUSERSPACE enabled, this handler is the kernel-side trust boundary for a user-mode caller. Prior to the fix it validated only the output buffer (KSYSCALLMEMORYWRITE) and passed the two struct device arguments, srcdev and dstdev, directly into the implementation without any object validation — unlike every sibling flash syscall, which guards its device pointer with KSYSCALLDRIVERFLASH.
A user-mode thread fully controls the values of srcdev/dstdev and the contents of its own address space. The implementation zimplflashcopy() dereferences these pointers and calls through their driver-API function tables (e.g. api->getparameters(dstdev), flashread(srcdev, ...), flashwrite(dstdev, ...)). By supplying a pointer to a forged struct device whose api table contains attacker-chosen function pointers, an unprivileged thread can cause the kernel to call arbitrary code in supervisor mode; passing any arbitrary or invalid address otherwise yields a kernel crash or out-of-bounds read.
The result is a local privilege escalation out of the userspace sandbox (with kernel denial-of-service and information disclosure as lesser outcomes). The fix adds KSYSCALLDRIVERFLASH(srcdev, read) and KSYSCALLDRIVERFLASH(dstdev, write) to zvrfyflashcopy(), which verify each device is a registered flash-driver kernel object the calling thread is permitted to use before any dereference, closing the path completely.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Compensating control
In z_vrfy_flash_copy(), validate src_dev with K_SYSCALL_DRIVER_FLASH(src_dev, read) and dst_dev with K_SYSCALL_DRIVER_FLASH(dst_dev, write) before dereferencing either device pointer.