Fixes a problem for intercept_method=trace when running a relative
command from a different directory than what sudo ws started from.
GitHub issue #194
We now store the vector immediately after the string table.
It is possible for argv and its contents to be invalidated
by realloc() when reading envp so we store the pointers as
offsets until we are done allocating.
In ptrace_verify_post_exec(), we don't know whether the executable
that is now running is a native or compat binary. In most cases
ptrace_getregs() will be able to figure it out for us.
If the execve(2) args are bogus pointers, we should just return an
error instead of killing the process. For consistency with the
kernel, convert EIO from ptrace(2) to EFAULT.
Also convert some ptrace(2) warnings to debug printfs so sudo is less chatty.
We can now verify that the arguments match what we accepted before
the command actually runs. If there is a mismatch, the process is
killed. Shell scripts must be handled specially since the path
executed will be the interpreter, not the script name.
Linux allows interpreters to be nested up to 4 deep.
It is not possible to change the syscall return value on MIPS
so we cannot support full intercept mode.
Another complication on MIPS is that if a system call is invoked
via syscall(__NR_###), v0 holds __NR_O32_Linux and the real syscall
is in the first arg (a0) and other args are shifted by one.
When ptracing a process, we receive the signal-delivery-stop signal
before the group-stop signal. If sudo is running the command in
the same terminal, we need to wait until the stop signal is actually
delivered to the command before we can suspend sudo itself. If we
suspend sudo before receiving the group-stop, the command will be
restarted with PTRACE_LISTEN too late and will miss the SIGCONT
from sudo.
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.