GuestCopyOut_nid_no_patch fell back to memcpy when process_vm_writev failed
with anything but EFAULT, and on every non-Linux/non-Windows host. Throw
instead (macOS uses mach_vm_write as Udp.cpp does) and cover read-only and
PROT_NONE pages plus a seccomp EPERM child in guest_fstat_fault.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
fstat, _fstat, sceKernelFstat, stat, lstat, sceKernelStat and _fstatfs
filled the caller's struct in place, or copied into it after a check that
only tests for null, so a pointer into unmapped memory crashed the host.
Fill a local struct and copy it out with a checked write that fails with
EFAULT. FreeBSD 11.4 does the same after the lookup has succeeded:
copyout(&ub, uap->sb) in sys_fstat (sys/kern/kern_descrip.c:1328),
copyout(&sb, uap->ub) in sys_stat (sys/kern/vfs_syscalls.c:2066) and
copyout(sfp, uap->buf) in sys_fstatfs (sys/kern/vfs_syscalls.c:337).
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
guest_fstatfs and guest_fstat_fault skipped the "closed descriptor fails
with EBADF" checks on Windows (#ifndef _WIN32). Both pass there, so the
guards are removed and the checks run on every host.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
FreeBSD's fstat looks the descriptor up before it copies the result
out, so a bad descriptor still fails with EBADF and an open one fails
with EFAULT when sb is null. fstat and sceKernelFstat threw
std::invalid_argument instead.
Co-Authored-By: Claude Opus 5.5 <[email protected]>