From b99debf92f590200a441b215fb8546c6ae6fdaab Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Thu, 12 May 2022 10:23:27 -0600 Subject: [PATCH] Add arm-specific code to set the system call number. Fixes rejection of commands due to policy on arm when in intercept mode. --- src/exec_ptrace.c | 12 ++++++------ src/exec_ptrace.h | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/exec_ptrace.c b/src/exec_ptrace.c index 40782386f..26c7f669c 100644 --- a/src/exec_ptrace.c +++ b/src/exec_ptrace.c @@ -84,12 +84,12 @@ get_syscallno(struct sudo_ptrace_regs *regs) } static inline void -set_syscallno(struct sudo_ptrace_regs *regs, int syscallno) +set_syscallno(pid_t pid, struct sudo_ptrace_regs *regs, int syscallno) { if (regs->compat) { - compat_reg_syscall(regs->u.compat) = syscallno; + compat_reg_set_syscall(regs->u.compat, syscallno); } else { - reg_syscall(regs->u.native) = syscallno; + reg_set_syscall(regs->u.native, syscallno); } } @@ -194,9 +194,9 @@ get_syscallno(struct sudo_ptrace_regs *regs) } static inline void -set_syscallno(struct sudo_ptrace_regs *regs, int syscallno) +set_syscallno(pid_t pid, struct sudo_ptrace_regs *regs, int syscallno) { - reg_syscall(regs->u.native) = syscallno; + reg_set_syscall(regs->u.native, syscallno); } static inline unsigned long @@ -687,7 +687,7 @@ ptrace_fail_syscall(pid_t pid, struct sudo_ptrace_regs *regs, int ecode) debug_decl(ptrace_fail_syscall, SUDO_DEBUG_EXEC); /* Cause the syscall to fail by changing its number to -1. */ - set_syscallno(regs, -1); + set_syscallno(pid, regs, -1); if (!ptrace_setregs(pid, regs)) { sudo_warn(U_("unable to set registers for process %d"), (int)pid); debug_return_bool(false); diff --git a/src/exec_ptrace.h b/src/exec_ptrace.h index 1927a539e..722538852 100644 --- a/src/exec_ptrace.h +++ b/src/exec_ptrace.h @@ -74,6 +74,13 @@ # define reg_arg2(x) (x).regs[1] /* x1 */ # define reg_arg3(x) (x).regs[2] /* x2 */ # define reg_arg4(x) (x).regs[3] /* x3 */ +# 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__) /* Note: assumes arm EABI, not OABI */ /* Untested */ @@ -86,6 +93,9 @@ # 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__) /* Untested (should also support hppa64) */ # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_PARISC @@ -228,6 +238,9 @@ struct arm_pt_regs { # define compat_reg_arg2(x) (x).uregs[1] /* r1 */ # define compat_reg_arg3(x) (x).uregs[2] /* r2 */ # define compat_reg_arg4(x) (x).uregs[3] /* r3 */ +# define compat_reg_set_syscall(_r, _nr) do { \ + ptrace(PTRACE_SET_SYSCALL, pid, NULL, _nr); \ +} while (0) #elif defined(__powerpc64__) struct ppc_pt_regs { unsigned int gpr[32]; @@ -263,6 +276,18 @@ struct ppc_pt_regs { # define compat_reg_set_retval(_r, _v) reg_set_retval(_r, _v) #endif +/* Set the syscall number the "normal" way by default. */ +#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 + /* Set the syscall return value the "normal" way by default. */ #ifndef reg_set_retval # define reg_set_retval(_r, _v) do { \