DF-0023 / run.log
==== BASELINE RUN (unpatched #0 kernel: 6.5-DEVELOPMENT #0, Thu Jul 2 06:02:54 UTC 2026) ====
$ ./einval_noop
read(fd,buf,SIZE_MAX) = 0, errno=0 (NOT EINVAL)
write child PID 869: probing write(fd,buf,SSIZE_MAX+1)...
write child PID 869: HUNG in kernel after 4s (DoS - uninterruptible infinite loop in mmrw)
after SIGKILL: child STILL ALIVE (unkillable in kernel loop)
RUN_EXIT=0
(ssh connection then lingered due to the orphaned, wedged child keeping the
session's process group open -> parent tool timed out at RC=124 while the
PoC process itself had already printed RUN_EXIT=0.)
==== INTERPRETATION ====
1. read(/dev/null, buf, SIZE_MAX) returns 0 with errno=0 instead of -1/EINVAL.
=> the guard `if ((ssize_t)uap->nbyte < 0) error = EINVAL;` in sys_read
(sys/kern/sys_generic.c:130-131) is a dead store: `error` is unconditionally
overwritten by `error = kern_preadv(...)` at line 143 before the `return`.
2. write(/dev/null, buf, SSIZE_MAX+1) HANGS in an infinite, uninterruptible
kernel loop. Chain:
sys_write (sys_generic.c:336-337) -- same dead-store EINVAL
-> kern_pwritev (:456) -> dofilewrite (:506 fo_write)
-> /dev/null cdev d_write = mmwrite (kern_memio.c:396) -> mmrw (:222)
mmrw line 225 declares `u_int c;` (32-bit);
line 298 does `c = iov->iov_len;` where iov_len is size_t 64-bit =
0x8000000000000000, so c truncates to 0.
line 382 `uio->uio_resid -= c;` subtracts 0, so `while(uio_resid>0)`
(line 232) never terminates. No signal check in the loop => SIGKILL
cannot be delivered => the process is unkillable while pinning a CPU.
=> local DoS: any unprivileged user can permanently pin every CPU core
with unkillable processes via a single write() syscall each.
Contrast the CORRECT sibling sys_extpread (sys_generic.c:161-162) which uses
`return(EINVAL);` and thus rejects nbyte>SSIZE_MAX as POSIX requires.