#ifndef SUDO_EXEC_PTRACE_H
#define SUDO_EXEC_PTRACE_H
#include <sys/prctl.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <asm/unistd.h>
#include <linux/audit.h>
#include <linux/ptrace.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <elf.h>
#ifndef __NR_execveat
# define __NR_execveat -1
#endif
#if defined(__aarch64__) && !defined(NT_ARM_SYSTEM_CALL)
# define NT_ARM_SYSTEM_CALL 0x404
#endif
#if defined(__x86_64__) && !defined(__X32_SYSCALL_BIT)
# define __X32_SYSCALL_BIT 0x40000000
#endif
#ifdef __mips__
# ifndef __NR_O32_Linux
# define __NR_O32_Linux 4000
# endif
# ifndef __NR_N32_Linux
# define __NR_N32_Linux 6000
# endif
#endif
#define WORDALIGN(_a, _r) \
(((_a) + ((unsigned long)(_r).wordsize - 1UL)) & ~((unsigned long)(_r).wordsize - 1UL))
#define LONGALIGN(_p) \
(((unsigned long)(_p) + (sizeof(unsigned long) - 1UL)) & ~(sizeof(unsigned long) - 1UL))
#if defined(__x86_64__)
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64
# ifndef __ILP32__
# define X32_execve __X32_SYSCALL_BIT + 520
# define X32_execveat __X32_SYSCALL_BIT + 545
# endif
# define sudo_pt_regs struct user_regs_struct
# define reg_syscall(x) (x).orig_rax
# define reg_retval(x) (x).rax
# define reg_sp(x) (x).rsp
# define reg_arg1(x) (x).rdi
# define reg_arg2(x) (x).rsi
# define reg_arg3(x) (x).rdx
# define reg_arg4(x) (x).r10
#elif defined(__aarch64__)
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64
# define sudo_pt_regs struct user_pt_regs
# define reg_syscall(x) (x).regs[8]
# define reg_retval(x) (x).regs[0]
# define reg_sp(x) (x).sp
# define reg_arg1(x) (x).regs[0]
# define reg_arg2(x) (x).regs[1]
# define reg_arg3(x) (x).regs[2]
# define reg_arg4(x) (x).regs[3]
# define reg_set_syscall(_r, _nr) do { \
struct iovec _iov; \
long _syscallno = (_nr); \
_iov.iov_base = &_syscallno; \
_iov.iov_len = sizeof(_syscallno); \
ptrace(PTRACE_SETREGSET, pid, NT_ARM_SYSTEM_CALL, &_iov); \
} while (0)
#elif defined(__arm__)
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM
# define sudo_pt_regs struct pt_regs
# define reg_syscall(x) (x).ARM_r7
# define reg_retval(x) (x).ARM_r0
# define reg_sp(x) (x).ARM_sp
# define reg_arg1(x) (x).ARM_r0
# define reg_arg2(x) (x).ARM_r1
# define reg_arg3(x) (x).ARM_r2
# define reg_arg4(x) (x).ARM_r3
# define reg_set_syscall(_r, _nr) do { \
ptrace(PTRACE_SET_SYSCALL, pid, NULL, _nr); \
} while (0)
#elif defined (__hppa__)
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_PARISC
# define sudo_pt_regs struct user_regs_struct
# define reg_syscall(x) (x).gr[20]
# define reg_retval(x) (x).gr[28]
# define reg_sp(x) (x).gr[30]
# define reg_arg1(x) (x).gr[26]
# define reg_arg2(x) (x).gr[25]
# define reg_arg3(x) (x).gr[24]
# define reg_arg4(x) (x).gr[23]
#elif defined(__i386__)
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386
# define sudo_pt_regs struct user_regs_struct
# define reg_syscall(x) (x).orig_eax
# define reg_retval(x) (x).eax
# define reg_sp(x) (x).esp
# define reg_arg1(x) (x).ebx
# define reg_arg2(x) (x).ecx
# define reg_arg3(x) (x).edx
# define reg_arg4(x) (x).esi
#elif defined(__mips__)
# if _MIPS_SIM == _MIPS_SIM_ABI32
#
# if BYTE_ORDER == LITTLE_ENDIAN
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL
# else
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS
# endif
# elif _MIPS_SIM == _MIPS_SIM_ABI64
#
# if BYTE_ORDER == LITTLE_ENDIAN
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL64
# else
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS64
# endif
# elif _MIPS_SIM == _MIPS_SIM_NABI32
#
# if BYTE_ORDER == LITTLE_ENDIAN
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL64N32
# else
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS64N32
# endif
# else
# error "Unsupported MIPS ABI"
# endif
# define sudo_pt_regs struct pt_regs
# define reg_syscall(_r) ({ \
__u64 _nr; \
if ((_r).regs[2] == __NR_O32_Linux) \
_nr = (_r).regs[4]; \
else \
_nr = (_r).regs[2]; \
_nr; \
})
# define reg_retval(x) (x).regs[2]
# define reg_sp(x) (x).regs[29]
# define reg_arg1(x) \
((x).regs[2] == __NR_O32_Linux ? (x).regs[5] : (x).regs[4])
# define reg_set_arg1(_r, _v) do { \
if ((_r).regs[2] == __NR_O32_Linux) \
(_r).regs[5] = _v; \
else \
(_r).regs[4] = _v; \
} while (0)
# define reg_arg2(x) \
((x).regs[2] == __NR_O32_Linux ? (x).regs[6] : (x).regs[5])
# define reg_set_arg2(_r, _v) do { \
if ((_r).regs[2] == __NR_O32_Linux) \
(_r).regs[6] = _v; \
else \
(_r).regs[5] = _v; \
} while (0)
# define reg_arg3(x) \
((x).regs[2] == __NR_O32_Linux ? (x).regs[7] : (x).regs[6])
# define reg_set_arg3(_r, _v) do { \
if ((_r).regs[2] == __NR_O32_Linux) \
(_r).regs[7] = _v; \
else \
(_r).regs[6] = _v; \
} while (0)
# define reg_arg4(x) \
((x).regs[2] == __NR_O32_Linux ? (x).regs[8] : (x).regs[7])
# define reg_set_arg4(_r, _v) do { \
if ((_r).regs[2] == __NR_O32_Linux) \
(_r).regs[8] = _v; \
else \
(_r).regs[7] = _v; \
} while (0)
# define reg_set_syscall(_r, _nr) do { \
if ((_r).regs[2] == __NR_O32_Linux) \
(_r).regs[4] = _nr; \
else \
(_r).regs[2] = _nr; \
} while (0)
#elif defined(__powerpc__)
# if defined(__powerpc64__)
# if BYTE_ORDER == LITTLE_ENDIAN
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_PPC64LE
# else
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_PPC64
# endif
# else
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_PPC
# endif
# define sudo_pt_regs struct pt_regs
# define reg_syscall(x) (x).gpr[0]
# define reg_retval(x) (x).gpr[3]
# define reg_sp(x) (x).gpr[1]
# define reg_arg1(x) (x).orig_gpr3
# define reg_arg2(x) (x).gpr[4]
# define reg_arg3(x) (x).gpr[5]
# define reg_arg4(x) (x).gpr[6]
# define reg_set_retval(_r, _v) do { \
if (((_r).trap & 0xfff0) == 0x3000) { \
\
reg_retval(_r) = (_v); \
} else { \
\
reg_retval(_r) = -(_v); \
(_r).ccr |= 0x10000000; \
} \
} while (0)
#elif defined(__riscv) && __riscv_xlen == 64
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_RISCV64
# define sudo_pt_regs struct user_regs_struct
# define reg_syscall(x) (x).a7
# define reg_retval(x) (x).a0
# define reg_sp(x) (x).sp
# define reg_arg1(x) (x).a0
# define reg_arg2(x) (x).a1
# define reg_arg3(x) (x).a2
# define reg_arg4(x) (x).a3
#elif defined(__s390__)
# if defined(__s390x__)
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_S390X
# else
# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_S390
# endif
# define sudo_pt_regs s390_regs
# define reg_syscall(x) (x).gprs[2]
# define reg_retval(x) (x).gprs[2]
# define reg_sp(x) (x).gprs[15]
# define reg_arg1(x) (x).orig_gpr2
# define reg_arg2(x) (x).gprs[3]
# define reg_arg3(x) (x).gprs[4]
# define reg_arg4(x) (x).gprs[5]
#else
# error "Do not know how to find your architecture's registers"
#endif
#if defined(__x86_64__)
struct i386_user_regs_struct {
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
unsigned int esi;
unsigned int edi;
unsigned int ebp;
unsigned int eax;
unsigned int xds;
unsigned int xes;
unsigned int xfs;
unsigned int xgs;
unsigned int orig_eax;
unsigned int eip;
unsigned int xcs;
unsigned int eflags;
unsigned int esp;
unsigned int xss;
};
# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_I386
# define COMPAT_execve 11
# define COMPAT_execveat 358
# define compat_sudo_pt_regs struct i386_user_regs_struct
# define compat_reg_syscall(x) (x).orig_eax
# define compat_reg_retval(x) (x).eax
# define compat_reg_sp(x) (x).esp
# define compat_reg_arg1(x) (x).ebx
# define compat_reg_arg2(x) (x).ecx
# define compat_reg_arg3(x) (x).edx
# define compat_reg_arg4(x) (x).esi
#elif defined(__aarch64__)
struct arm_pt_regs {
unsigned int uregs[18];
};
# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_ARM
# define COMPAT_execve 11
# define COMPAT_execveat 387
# define compat_sudo_pt_regs struct arm_pt_regs
# define compat_reg_syscall(x) (x).uregs[7]
# define compat_reg_retval(x) (x).uregs[0]
# define compat_reg_sp(x) (x).uregs[13]
# define compat_reg_arg1(x) (x).uregs[0]
# define compat_reg_arg2(x) (x).uregs[1]
# define compat_reg_arg3(x) (x).uregs[2]
# define compat_reg_arg4(x) (x).uregs[3]
# define compat_reg_set_syscall(_r, _nr) reg_set_syscall(_r, _nr)
#elif defined(__mips__)
# if _MIPS_SIM == _MIPS_SIM_ABI64
# if BYTE_ORDER == LITTLE_ENDIAN
# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_MIPSEL
# define SECCOMP_AUDIT_ARCH_COMPAT2 AUDIT_ARCH_MIPSEL64N32
# else
# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_MIPS
# define SECCOMP_AUDIT_ARCH_COMPAT2 AUDIT_ARCH_MIPS64N32
# endif
# define COMPAT_execve __NR_O32_Linux + 11
# define COMPAT_execveat __NR_O32_Linux + 356
# define COMPAT2_execve __NR_N32_Linux + 57
# define COMPAT2_execveat __NR_N32_Linux + 320
# elif _MIPS_SIM == _MIPS_SIM_NABI32
# if BYTE_ORDER == LITTLE_ENDIAN
# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_MIPSEL
# else
# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_MIPS
# endif
# define COMPAT_execve __NR_O32_Linux + 11
# define COMPAT_execveat __NR_O32_Linux + 356
# endif
# define compat_sudo_pt_regs struct pt_regs
# define compat_reg_syscall(x) reg_syscall(x)
# define compat_reg_retval(x) reg_retval(x)
# define compat_reg_sp(x) reg_sp(x)
# define compat_reg_arg1(x) reg_arg1(x)
# define compat_reg_set_arg1(_r, _v) reg_set_arg1(_r, _v)
# define compat_reg_arg2(x) reg_arg2(x)
# define compat_reg_set_arg2(_r, _v) reg_set_arg2(_r, _v)
# define compat_reg_arg3(x) reg_arg3(x)
# define compat_reg_set_arg3(_r, _v) reg_set_arg3(_r, _v)
# define compat_reg_arg4(x) reg_arg4(x)
# define compat_reg_set_arg4(_r, _v) reg_set_arg4(_r, _v)
# define compat_reg_set_syscall(_r, _nr) reg_set_syscall(_r, _nr)
#elif defined(__powerpc64__)
struct ppc_pt_regs {
unsigned int gpr[32];
unsigned int nip;
unsigned int msr;
unsigned int orig_gpr3;
unsigned int ctr;
unsigned int link;
unsigned int xer;
unsigned int ccr;
unsigned int mq;
unsigned int trap;
unsigned int dar;
unsigned int dsisr;
unsigned int result;
};
# if BYTE_ORDER == LITTLE_ENDIAN
# define SECCOMP_AUDIT_ARCH_COMPAT (AUDIT_ARCH_PPC|__AUDIT_ARCH_LE)
# else
# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_PPC
# endif
# define COMPAT_execve __NR_execve
# define COMPAT_execveat __NR_execveat
# define compat_sudo_pt_regs struct ppc_pt_regs
# define compat_reg_syscall(x) (x).gpr[0]
# define compat_reg_retval(x) (x).gpr[3]
# define compat_reg_sp(x) (x).gpr[1]
# define compat_reg_arg1(x) (x).orig_gpr3
# define compat_reg_arg2(x) (x).gpr[4]
# define compat_reg_arg3(x) (x).gpr[5]
# define compat_reg_arg4(x) (x).gpr[6]
# define compat_reg_set_retval(_r, _v) reg_set_retval(_r, _v)
#endif
#ifndef reg_set_syscall
# define reg_set_syscall(_r, _nr) do { \
reg_syscall(_r) = (_nr); \
} while (0)
#endif
#ifndef compat_reg_set_syscall
# define compat_reg_set_syscall(_r, _nr) do { \
compat_reg_syscall(_r) = (_nr); \
} while (0)
#endif
#ifndef reg_set_retval
# define reg_set_retval(_r, _v) do { \
reg_retval(_r) = (_v); \
} while (0)
#endif
#ifndef compat_reg_set_retval
# define compat_reg_set_retval(_r, _v) do { \
compat_reg_retval(_r) = (_v); \
} while (0)
#endif
#ifndef reg_set_arg1
# define reg_set_arg1(_r, _v) do { \
reg_arg1(_r) = (_v); \
} while (0)
#endif
#ifndef compat_reg_set_arg1
# define compat_reg_set_arg1(_r, _v) do { \
compat_reg_arg1(_r) = (_v); \
} while (0)
#endif
#ifndef reg_set_arg2
# define reg_set_arg2(_r, _v) do { \
reg_arg2(_r) = (_v); \
} while (0)
#endif
#ifndef compat_reg_set_arg2
# define compat_reg_set_arg2(_r, _v) do { \
compat_reg_arg2(_r) = (_v); \
} while (0)
#endif
#ifndef reg_set_arg3
# define reg_set_arg3(_r, _v) do { \
reg_arg3(_r) = (_v); \
} while (0)
#endif
#ifndef compat_reg_set_arg3
# define compat_reg_set_arg3(_r, _v) do { \
compat_reg_arg3(_r) = (_v); \
} while (0)
#endif
#ifndef reg_set_arg4
# define reg_set_arg4(_r, _v) do { \
reg_arg4(_r) = (_v); \
} while (0)
#endif
#ifndef compat_reg_set_arg4
# define compat_reg_set_arg4(_r, _v) do { \
compat_reg_arg4(_r) = (_v); \
} while (0)
#endif
#ifndef reg_set_arg1
# define reg_set_arg1(_r, _v) do { \
reg_arg1(_r) = (_v); \
} while (0)
#endif
#ifndef compat_reg_set_arg1
# define compat_reg_set_arg1(_r, _v) do { \
compat_reg_arg1(_r) = (_v); \
} while (0)
#endif
#ifndef reg_set_arg2
# define reg_set_arg2(_r, _v) do { \
reg_arg2(_r) = (_v); \
} while (0)
#endif
#ifndef compat_reg_set_arg2
# define compat_reg_set_arg2(_r, _v) do { \
compat_reg_arg2(_r) = (_v); \
} while (0)
#endif
#ifndef reg_set_arg3
# define reg_set_arg3(_r, _v) do { \
reg_arg3(_r) = (_v); \
} while (0)
#endif
#ifndef compat_reg_set_arg3
# define compat_reg_set_arg3(_r, _v) do { \
compat_reg_arg3(_r) = (_v); \
} while (0)
#endif
#ifndef reg_set_arg4
# define reg_set_arg4(_r, _v) do { \
reg_arg4(_r) = (_v); \
} while (0)
#endif
#ifndef compat_reg_set_arg4
# define compat_reg_set_arg4(_r, _v) do { \
compat_reg_arg4(_r) = (_v); \
} while (0)
#endif
struct sudo_ptrace_regs {
union {
sudo_pt_regs native;
#ifdef SECCOMP_AUDIT_ARCH_COMPAT
compat_sudo_pt_regs compat;
#endif
} u;
unsigned int wordsize;
bool compat;
};
#endif