Use PTRACE_SETREGSET with NT_ARM_SYSTEM_CALL instead just like we
would for a 64-bit binary. Newer Linux headers don't define
PTRACE_SET_SYSCALL for aarch64.
Mips is a bit different in that most Linux distros appear to use
the n32 ABI on 64-bit CPUs. We don't currently support tracing a
64-bit binary from a 32-bit sudo. We could suport tracing o32
ABI binaries in compat mode, though.
For compat binaries, use the upper 32-bits as the next word instead
of calling ptrace(2) to get it. This reduces the number of ptrace(2)
calls when reading argv and envp for compat binaries.
We align the start of the string table to a word boundary to help
prevent overlap when writing the pointers. However, the actual
strings themselves don't need to be aligned.
In compat mode, if argc is odd, writing the last pointer of argv will
overlap with the address of argv[0], so leave an extra word in between.
Also remove incorrect comments about PTRACE_PEEKDATA unaligned access.
If we try to use the compat word size we can end up in a situation
where a subsequent PTRACE_POKEDATA overwrites part of what we've
already written since it always writes in sizeof(long) units.
We need to define the ptrace register struct ourselves for the
32-bit system since there is no good way to get it from the system
headers. Currently only implemented for x86_64 and aarch64.
We need to continue the traced process even if there is a fatal
error. Otherwise, sudo will appear to hang as the running process
is left in PTRACE_EVENT stop.
Unlike PTRACE_GETREGSET, PTRACE_GETREGS requires that we manually
map registers from 64-bit to 32-bit layouts when running, e.g. a
32-bit binary from a 64-bit sudo process.
For command_matches_all() we should only perform the setid check
if the file exists and intercept is enabled. Otherwise, we can end
up returning an error if the fully-qualified command does not exist.
Fixes a regression introduced in sudo 1.9.0 with the support for
digests in conjunction with "sudo ALL".
We can skip the policy check for the execve(2) of the initial command
since it has already been check. Otherwise, we would log the command
twice. When using fexecve(2) due to a digest check, there should
be no need to skip the initial command since it will be executed
via execveat(2) not execve(2). However, on older kernels without
execveat(2), glibc will emulate fexecve(2) using /proc which will
result in the extra log entry.