An anonymous shm descriptor is recognised as shared memory only on
Linux, where the memfd link name is matched; on Windows the anonymous
%TEMP% object is not registered in the shared-descriptor table, so the
descriptor is not recognised and fpathconf never reaches the EOPNOTSUPP
branch. A named descriptor is recognised on both platforms, so the
check now opens a named object and unlinks it, keeping the same branch
coverage without a Linux-only assumption.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
_fpathconf_nid_postfix only treated FIFOs and sockets as descriptors without
a vnode, so a kqueue or shm_open descriptor fell through to the UFS constants
(LINK_MAX 32767, NAME_MAX 255, PIPE_BUF 512). FreeBSD 11.4 kern_fpathconf
(kern_descrip.c:1411-1429) answers _PC_ASYNC_IO for every descriptor and
returns EOPNOTSUPP for a no-vnode descriptor that is not a pipe or socket.
Return EOPNOTSUPP for kqueue and shared-memory descriptors.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Follow FreeBSD 11.4 sys_kenv: KENV_GET, KENV_SET, KENV_UNSET and KENV_DUMP over
an in-memory kernel environment of at most 512 variables, with the 128-byte
name and value limits, ENOENT, EINVAL, ENAMETOOLONG and EFAULT.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Follow FreeBSD 11.4's sys_kldsym: EFAULT for an unreadable lookup
structure, EINVAL for a wrong version or command, EFAULT or
ENAMETOOLONG for the symbol name, ENOENT for a negative file id. Any
other lookup throws, as no kernel module is modelled. Adds
GuestCopyIn_nid_no_patch for the checked structure read.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
oneandonlydean's review of #8457 settled that the guest is modelled as
root, and FreeBSD 11's root keeps the privilege to change a file's
owner, so EPERM for another owner has no source until a console
measurement shows it. chown, lchown and fchownat go back to
RequireGuestOwner after the path lookup, as fchown does, and their debt
entry is main's again. The EPERM assertions go without throw assertions
in their place; the lookup error checks stay.
sigreturn applies FreeBSD 11's amd64 sys_sigreturn checks:
- EFAULT for a null context;
- EINVAL for unknown mc_flags, and for rflags bits outside
PSL_USERCHANGE that differ from the current flags;
- set_fpcontext's FPU format and ownership cases.
It then restores the context through the path setcontext uses, which
now lives in RestoreContext. A non-user %cs and an extended FPU state
still throw.
FreeBSD 11's sys_sched_setscheduler checks: a null parameter is EFAULT,
another process is ESRCH and an unknown policy is EINVAL. Pid 0 sets the
calling thread through scePthreadSetschedparam. Values that call
rejects, and the guest's own pid, whose first thread is not tracked,
still throw.
An owner or group other than the guest's (0) or the unchanged value
returns EPERM after the path lookup, as FreeBSD 11's chown(2) does for
a caller without the superuser privilege. That is the answer #8457
gives for fchown. A lookup error still comes first.
Both read their caller's structures in place before validation, so an unreadable pointer crashed the host. Copy them in with a checked read first and return EFAULT, as FreeBSD 11.4 does.
Fixes#11370
lchflags is chflags without following a symbolic link in the last path
component, as FreeBSD 11.4's sys_lchflags calls kern_chflagsat with
AT_SYMLINK_NOFOLLOW. chflags now goes through a shared helper that takes
the follow choice; a link in the last component is accepted as the
target when not following, and the flag checks are unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Match the AT_REMOVEDIR and rmdir sites so file reparse points stay on the old unlink path. Cover file symlink unlinkat on Windows and point the debt at the drive-target consumers.
FreeBSD 11.4's kern_settimeofday rejects a timeval with a microsecond
field outside 0 to 999999 or a negative second field with EINVAL before
changing anything, sets the clock from a valid timeval, and then stores
the timezone, which gettimeofday reports. settimeofday now checks the
timeval the same way and throws for a valid one, as clock_settime does,
because the host clock is not changed. A timezone given without a
timeval is stored and gettimeofday reports it instead of 0 and 0.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
AmmSubmit_nid_no_patch stored the id _submit returned into lastSubmit
after _submit had released the queue's submit lock. Two submitters could
store out of order: the later id was stored first, then the earlier one
overwrote it, and a wait for the later, already submitted id failed with
ESRCH until the next submission.
The wait now checks the id against the AMM queue's own submitted count,
which _submit raises under the queue mutex before it returns, and
lastSubmit goes.
The test has four threads submit empty AMM buffers while another waits
on the newest id any of them has published, through
sceKernelWaitCommandBufferCompletion and
sceAmprAmmWaitCommandBufferCompletion, and requires every wait to
succeed.
The map, map direct and mtype-protect writers take type as a 64-bit
value and store it in the record's 32-bit field. That matches
sceKernelWriteModifyMtypeProtectCommand and the libSceAmpr siblings,
whose type is 32 bits, but nothing checked it. A type with bit 32 set
now has to record the same bytes as the sibling given the low 32 bits,
and the debt entry says the console's handling of such a type is not
measured.
sceKernelWaitCommandBufferCompletion waits for an AMM submission as
libSceAmpr's sceAmprAmmWaitCommandBufferCompletion does: 0 once the
submission has run, SCE_KERNEL_ERROR_ESRCH for an id that was never
submitted. The signature follows ampr_emu's libkernel hook targets,
where the libSceAmpr wait forwards to it.
guest_kernel_sys submits a map written by sceKernelWriteMapCommand,
waits for it and uses the mapped page, and checks ids 0 and past the
last submission.
The twelve AMM kernel writers record into a caller buffer the command
their libSceAmpr command buffer sibling appends, built with the shared
encoder: sceKernelWriteMapCommand, sceKernelWriteMapWithGpuMaskIdCommand,
sceKernelWriteMapDirectCommand, sceKernelWriteMapDirectWithGpuMaskIdCommand,
sceKernelWriteUnmapCommand, sceKernelWriteRemapCommand,
sceKernelWriteRemapWithGpuMaskIdCommand, sceKernelWriteMultiMapCommand,
sceKernelWriteMultiMapWithGpuMaskIdCommand,
sceKernelWriteModifyProtectCommand,
sceKernelWriteModifyProtectWithGpuMaskIdCommand and
sceKernelWriteModifyMtypeProtectWithGpuMaskIdCommand.
The signatures follow ampr_emu's libkernel hook targets: the sibling's
arguments as 64-bit values between the destination and the size output.
A null destination only reports the size and a null size output only
writes, as for sceKernelWriteModifyMtypeProtectCommand. Invalid ranges,
offsets and protections return the sibling's SCE_KERNEL_ERROR_EINVAL and
write nothing; protection or mask bits above 32 are rejected too.
guest_kernel_sys compares each writer with its sibling on valid and
invalid arguments, in both modes.
On Windows, mkdirat with a directory descriptor and a relative path that goes through a symbolic link pointing to itself reported EIO. CreateDirectoryW fails with ERROR_CANT_RESOLVE_FILENAME for such a path, and the error mapping had no case for it, so it fell through to GuestEio. FreeBSD fails the lookup with ELOOP. The path form of mkdir and openat with the same descriptor already return ELOOP. ERROR_CANT_RESOLVE_FILENAME now gives ELOOP.
guest_kernel_sys gains a Windows check with a file-type and a directory-type self-loop: mkdirat through the loop returns ELOOP and mkdirat of the link itself still returns EEXIST. The check is skipped when the host denies symbolic link creation.
Measured in a payload process on a PS5 (firmware 13.60) through libkernel_sys.sprx's pathconf: /system_data gives 65536 for the allocation, transfer and hole sizes, 16384 for the transfer alignment, 3 for _PC_ACL_PATH_MAX and 0 for the ACL and MAC flags, and EINVAL for _PC_MAX_CANON, _PC_MAX_INPUT, _PC_VDISABLE and _PC_ASYNC_IO, which used to throw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
kern_fpathconf answers _PC_ASYNC_IO with _POSIX_ASYNCHRONOUS_IO (200112) after the descriptor lookup, and a pipe or socket (no vnode) with PIPE_BUF for _PC_PIPE_BUF and EINVAL for every other name. Drop the unused File.hpp include and the duplicate KernelErrors.hpp include.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>