Enable ptrace support for MIPS but only for log_subcmds.
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.
This commit is contained in:
@@ -109,9 +109,9 @@ static inline void
|
||||
set_sc_arg1(struct sudo_ptrace_regs *regs, unsigned long addr)
|
||||
{
|
||||
if (regs->compat) {
|
||||
compat_reg_arg1(regs->u.compat) = addr;
|
||||
compat_reg_set_arg1(regs->u.compat, addr);
|
||||
} else {
|
||||
reg_arg1(regs->u.native) = addr;
|
||||
reg_set_arg1(regs->u.native, addr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,9 +129,9 @@ static inline void
|
||||
set_sc_arg2(struct sudo_ptrace_regs *regs, unsigned long addr)
|
||||
{
|
||||
if (regs->compat) {
|
||||
compat_reg_arg2(regs->u.compat) = addr;
|
||||
compat_reg_set_arg2(regs->u.compat, addr);
|
||||
} else {
|
||||
reg_arg2(regs->u.native) = addr;
|
||||
reg_set_arg2(regs->u.native, addr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,9 +150,9 @@ static inline void
|
||||
set_sc_arg3(struct sudo_ptrace_regs *regs, unsigned long addr)
|
||||
{
|
||||
if (regs->compat) {
|
||||
compat_reg_arg3(regs->u.compat) = addr;
|
||||
compat_reg_set_arg3(regs->u.compat, addr);
|
||||
} else {
|
||||
reg_arg3(regs->u.native) = addr;
|
||||
reg_set_arg3(regs->u.native, addr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,9 +170,9 @@ static inline void
|
||||
set_sc_arg4(struct sudo_ptrace_regs *regs, unsigned long addr)
|
||||
{
|
||||
if (regs->compat) {
|
||||
compat_reg_arg4(regs->u.compat) = addr;
|
||||
compat_reg_set_arg4(regs->u.compat, addr);
|
||||
} else {
|
||||
reg_arg4(regs->u.native) = addr;
|
||||
reg_set_arg4(regs->u.native, addr);
|
||||
}
|
||||
}
|
||||
# endif /* notyet */
|
||||
@@ -212,7 +212,7 @@ get_sc_arg1(struct sudo_ptrace_regs *regs)
|
||||
static inline void
|
||||
set_sc_arg1(struct sudo_ptrace_regs *regs, unsigned long addr)
|
||||
{
|
||||
reg_arg1(regs->u.native) = addr;
|
||||
reg_set_arg1(regs->u.native, addr);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
@@ -224,7 +224,7 @@ get_sc_arg2(struct sudo_ptrace_regs *regs)
|
||||
static inline void
|
||||
set_sc_arg2(struct sudo_ptrace_regs *regs, unsigned long addr)
|
||||
{
|
||||
reg_arg2(regs->u.native) = addr;
|
||||
reg_set_arg2(regs->u.native, addr);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
@@ -237,7 +237,7 @@ get_sc_arg3(struct sudo_ptrace_regs *regs)
|
||||
static inline void
|
||||
set_sc_arg3(struct sudo_ptrace_regs *regs, unsigned long addr)
|
||||
{
|
||||
reg_arg3(regs->u.native) = addr;
|
||||
reg_set_arg3(regs->u.native, addr);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
@@ -249,7 +249,7 @@ get_sc_arg4(struct sudo_ptrace_regs *regs)
|
||||
static inline void
|
||||
set_sc_arg4(struct sudo_ptrace_regs *regs, unsigned long addr)
|
||||
{
|
||||
reg_arg4(regs->u.native) = addr;
|
||||
reg_set_arg4(regs->u.native, addr);
|
||||
}
|
||||
# endif /* notyet */
|
||||
# endif /* SECCOMP_AUDIT_ARCH_COMPAT */
|
||||
@@ -1280,10 +1280,15 @@ exec_ptrace_stopped(pid_t pid, int status, void *intercept)
|
||||
bool
|
||||
exec_ptrace_intercept_supported(void)
|
||||
{
|
||||
# ifdef __mips__
|
||||
/* MIPS doesn't support changing the syscall return value. */
|
||||
return false;
|
||||
# else
|
||||
if (seccomp_trap_supported == -1)
|
||||
seccomp_trap_supporetd = have_seccomp_action("trap");
|
||||
seccomp_trap_supported = have_seccomp_action("trap");
|
||||
|
||||
return seccomp_trap_supported == true;
|
||||
# endif
|
||||
}
|
||||
|
||||
bool
|
||||
|
@@ -37,6 +37,10 @@
|
||||
# define __X32_SYSCALL_BIT 0x40000000
|
||||
#endif
|
||||
|
||||
#if defined(__mips__) && !defined(__NR_O32_Linux)
|
||||
# define __NR_O32_Linux 4000
|
||||
#endif
|
||||
|
||||
/* Align address to a (compat) word boundary. */
|
||||
#define WORDALIGN(_a, _r) \
|
||||
(((_a) + ((long)(_r).wordsize - 1L)) & ~((long)(_r).wordsize - 1L))
|
||||
@@ -141,20 +145,60 @@
|
||||
# else
|
||||
# error "Unsupported MIPS ABI"
|
||||
# endif
|
||||
/* Untested/incomplete.
|
||||
/*
|
||||
* If called via syscall(__NR_###), v0 holds __NR_O32_Linux and the real
|
||||
* syscall the first arg (a0) and other args are shifted by one.
|
||||
* We don't currently support this.
|
||||
* syscall is in the first arg (a0). The actual args are shifted by one.
|
||||
* MIPS does not support setting the syscall return value via ptrace.
|
||||
*/
|
||||
# define sudo_pt_regs struct pt_regs
|
||||
# define reg_syscall(x) (x).regs[2] /* v0 */
|
||||
# define reg_syscall(_r) ({ \
|
||||
__u64 _nr; \
|
||||
if ((_r).regs[2] == __NR_O32_Linux) \
|
||||
_nr = (_r).regs[4]; /* a0 */ \
|
||||
else \
|
||||
_nr = (_r).regs[2]; /* v0 */ \
|
||||
_nr; \
|
||||
})
|
||||
# define reg_retval(x) (x).regs[2] /* v0 */
|
||||
# define reg_sp(x) (x).regs[29] /* sp */
|
||||
# define reg_arg1(x) (x).regs[4] /* a0 */
|
||||
# define reg_arg2(x) (x).regs[5] /* a1 */
|
||||
# define reg_arg3(x) (x).regs[6] /* a2 */
|
||||
# define reg_arg4(x) (x).regs[7] /* a3 */
|
||||
# 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; /* a1 */ \
|
||||
else \
|
||||
(_r).regs[4] = _v; /* a0 */ \
|
||||
} 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; /* a2 */ \
|
||||
else \
|
||||
(_r).regs[5] = _v; /* a1 */ \
|
||||
} 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; /* a3 */ \
|
||||
else \
|
||||
(_r).regs[6] = _v; /* a2 */ \
|
||||
} 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; /* a4 */ \
|
||||
else \
|
||||
(_r).regs[7] = _v; /* a3 */ \
|
||||
} while (0)
|
||||
# define reg_set_syscall(_r, _nr) do { \
|
||||
if ((_r).regs[2] == __NR_O32_Linux) \
|
||||
(_r).regs[4] = _nr; /* a0 */ \
|
||||
else \
|
||||
(_r).regs[2] = _nr; /* v0 */ \
|
||||
} while (0)
|
||||
#elif defined(__powerpc__)
|
||||
# if defined(__powerpc64__)
|
||||
# if BYTE_ORDER == LITTLE_ENDIAN
|
||||
@@ -333,6 +377,48 @@ struct ppc_pt_regs {
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Set the syscall arguments the "normal" way by default. */
|
||||
#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;
|
||||
|
@@ -92,10 +92,11 @@ union sudo_token_un {
|
||||
|
||||
/*
|
||||
* Use ptrace-based intercept (using seccomp) on Linux if possible.
|
||||
* On MIPS we can't change the syscall return and only support log_subcmds.
|
||||
*/
|
||||
#if defined(_PATH_SUDO_INTERCEPT) && defined(__linux__)
|
||||
# if defined(HAVE_DECL_SECCOMP_SET_MODE_FILTER) && HAVE_DECL_SECCOMP_SET_MODE_FILTER
|
||||
# if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || defined(__arm__) || defined(__powerpc__) || (defined(__riscv) && __riscv_xlen == 64) || defined(__s390__)
|
||||
# if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || defined(__arm__) || defined(__mips__) || defined(__powerpc__) || (defined(__riscv) && __riscv_xlen == 64) || defined(__s390__)
|
||||
# ifndef HAVE_PTRACE_INTERCEPT
|
||||
# define HAVE_PTRACE_INTERCEPT 1
|
||||
# endif /* HAVE_PTRACE_INTERCEPT */
|
||||
|
Reference in New Issue
Block a user