Dmitry Chagin [Sat, 28 May 2022 20:45:39 +0000 (23:45 +0300)]
linux(4): Handle 64-bit SO_TIMESTAMP for 32-bit binaries
To solve y2k38 problem in the recvmsg syscall the new SO_TIMESTAMP
constant were added on v5.1 Linux kernel. So, old 32-bit binaries
that knows only 32-bit time_t uses the old value of the constant,
and binaries that knows 64-bit time_t uses the new constant.
To determine what size of time_t type is expected by the user-space,
store requested value (SO_TIMESTAMP) in the process emuldata structure.
Dmitry Chagin [Sat, 28 May 2022 20:30:22 +0000 (23:30 +0300)]
linux(4): Add a helper to copyout getsockopt value
For getsockopt(), optlen is a value-result argument, which is modified
on return to indicate the actual size of the value returned.
For some cases this was missed, fixed.
Dmitry Chagin [Sat, 28 May 2022 20:29:12 +0000 (23:29 +0300)]
linux(4): Check the socket before any others sanity checks
Strictly speaking, this check is performed by the kern_recvit(), but in
the Linux emulation layer before calling the kernel we do other sanity
checks and conversions from Linux types to the native types. This changes
an order of the error returning that is critical for some buggy Linux
applications.
For recvmmsg() syscall this fixes a panic in case when the user-supplied
vlen value is 0, then error is not initialized and garbage passed to the
bsd_to_linux_errno().
Split cpuset_getaffinity() into a two counterparts, where the
user_cpuset_getaffinity() is intended to operate on the cpuset_t from
user va, while kern_cpuset_getaffinity() expects the cpuset from kernel
va.
Accordingly, the code that clears the high bits is moved to the
user_cpuset_getaffinity(). Linux sched_getaffinity() syscall returns
the size of set copied to the user-space and then glibc wrapper clears
the high bits.
Dmitry Chagin [Sun, 15 May 2022 18:10:50 +0000 (21:10 +0300)]
linux(4): Implement signal trampoline for arm64 in a FreeBSD-way
The implemenation differs from others Linuxulators.
For unwinders Linux ucontext_t is stored, however native machine context
is used to store/restore process state to avoid code duplication.
As DWARF Aarch64 does not define a register number for PC and provides no
direct way to encode the PC of the previous frame, CFI cannot describe a
signal trampoline frame. So, modified the vdso linker script to discard
unused sections.
Dmitry Chagin [Fri, 17 Jun 2022 19:35:21 +0000 (22:35 +0300)]
linux(4): Retire handmade DWARF annotations from signal trampolines
The Linux exports __kernel_sigreturn and __kernel_rt_sigreturn from the
vdso. Modern glibc's sigaction sets the sa_restorer field of sigaction
to the corresponding vdso __sigreturn, and sets the SA_RESTORER.
Our signal trampolines uses the FreeBSD-way to call a signal handler,
so does not use the sigaction's sa_restorer.
However, as glibc's runtime linker depends on the existment of the vdso
__sigreturn symbols, for all Linuxulators was added separate trampolines
named __sigcode with DWARF anotations and left separate __sigreturn
methods, which are exported.
Dmitry Chagin [Sun, 15 May 2022 18:05:01 +0000 (21:05 +0300)]
linux(4): Rework the definition of struct siginfo to match Linux actual one
Rework the defintion of struct siginfo so that the array padding
struct siginfo to SI_MAX_SIZE can be placed in a union along side of the
rest of the struct siginfo members. The result is that we no longer need
the __ARCH_SI_PREAMBLE_SIZE or SI_PAD_SIZE definitions.
Move struct siginfo definition under /compat/linux to reduce MD part.
To avoid headers polution include linux_siginfo.h in the MD linux.h
Dmitry Chagin [Sun, 15 May 2022 18:00:05 +0000 (21:00 +0300)]
linux(4): Cleanup signal trampolines
This is the first stage of a signal trampolines refactoring.
From trampolines retired emulation of the 'call' instruction, which is
replaced by direct call of a signal handler. The signal handler address
is in the register.
The previous trampoline implemenatation used semi-Linux-way to call
a signal handler via the 'jmp' instruction. Wherefore the trampoline
emulated a 'call' instruction to into the stack the return address for
signal handler's 'ret' instruction. Wherefore handmade DWARD annotations
was used.
While here rephrased and removed excessive comments.
Dmitry Chagin [Sun, 15 May 2022 17:58:47 +0000 (20:58 +0300)]
linux(4): Retire unneeded initialization
Both uc_flags and uc_link are zeroed above. On amd64 and i386 the
uc_link field is not used at all. The UC_FP_XSTATE bit should be set
in the uc_flags if OS xsave knob is turned on (and xsave is implemented).
Dmitry Chagin [Sat, 14 May 2022 11:07:20 +0000 (14:07 +0300)]
sysvsem: Fix a typo
Per jamie@ rpr can be NULL if the jail is created with sysvsem=disable.
But at least it doesn't appear to be fatal, since rpr is never dereferenced
but is only compared to other prison pointers.
Dmitry Chagin [Fri, 17 Jun 2022 19:35:14 +0000 (22:35 +0300)]
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Rename the "copyin" and "copyout" fields of struct cpuset_copy_cb to
something less generic, since sanitizers define interceptors for
copyin() and copyout() using #define.
Reported by: syzbot+2db5d644097fc698fb6f@syzkaller.appspotmail.com Fixes: 47a57144af25 ("cpuset: Byte swap cpuset for compat32 on big endian architectures")
Sponsored by: The FreeBSD Foundation
Use Linux semantics for the thread affinity syscalls.
Linux has more tolerant checks of the user supplied cpuset_t's.
Minimum cpuset_t size that the Linux kernel permits in case of
getaffinity() is the maximum CPU id, present in the system / NBBY,
the maximum size is not limited.
For setaffinity(), Linux does not limit the size of the user-provided
cpuset_t, internally using only the meaningful part of the set, where
the upper bound is the maximum CPU id, present in the system, no larger
than the size of the kernel cpuset_t.
Unlike FreeBSD, Linux ignores high bits if set in the setaffinity(),
so clear it in the sched_setaffinity() and Linuxulator itself.
Reviewed by: Pau Amma (man pages)
In collaboration with: jhb
Differential revision: https://reviews.freebsd.org/D34849
MFC after: 2 weeks
Dmitry Chagin [Sun, 8 May 2022 13:16:47 +0000 (16:16 +0300)]
linux(4): Add a helper intended for copying timespec's from the userspace.
There are many places where we copyin Linux timespec from the userspace
and then convert it to the kernel timespec. To avoid code duplication
add a tiny halper for doing this.
Dmitry Chagin [Fri, 6 May 2022 16:58:53 +0000 (19:58 +0300)]
linux(4): Call semop directly.
As the Linux semop syscall is not defined in i386, and as it is equal
to the native semop syscall, call it directly.
Fix semop definition to match Linux actual one - nsops is size_t type.
Dmitry Chagin [Fri, 6 May 2022 16:51:48 +0000 (19:51 +0300)]
sysvsem: Add a timeout argument to the semop.
For future use in the Linux emulation layer for the semtimedop syscall
split the sys_semop syscall into two counterparts and add
struct timespec *timeout argument to the last one.