From 2b3d59c14b0801cd1454d3bb383be7fe333e68b0 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 15 Aug 2019 20:23:19 +0000 Subject: [PATCH] Fix syscall tampering when PTRACE_GET_SYSCALL_INFO is in use on some architectures When PTRACE_GET_SYSCALL_INFO is in use on those architectures that invoke set_regs in arch_set_scno, get_regs is not called, so it has to be invoked explicitly before tampering. * linux/arc/set_scno.c (arch_set_scno): Explicitly call get_regs when PTRACE_GET_SYSCALL_INFO is in use. * linux/avr32/set_scno.c: Likewise. * linux/csky/set_scno.c: Likewise. * linux/ia64/set_scno.c: Likewise. * linux/m68k/set_scno.c: Likewise. * linux/metag/set_scno.c: Likewise. * linux/mips/set_scno.c: Likewise. * linux/nios2/set_scno.c: Likewise. * linux/or1k/set_scno.c: Likewise. * linux/riscv/set_scno.c: Likewise. * linux/s390/set_scno.c: Likewise. * linux/sparc/set_scno.c: Likewise. * linux/tile/set_scno.c: Likewise. * NEWS: Mention this fix. Thanks-to: Anatoly Pugachev Fixes: v5.2~27 "sparc, sparc64: fix syscall tampering when PTRACE_GET_SYSCALL_INFO is in use" --- NEWS | 3 +++ linux/arc/set_scno.c | 2 ++ linux/avr32/set_scno.c | 2 ++ linux/csky/set_scno.c | 2 ++ linux/ia64/set_scno.c | 3 ++- linux/m68k/set_scno.c | 2 ++ linux/metag/set_scno.c | 2 ++ linux/mips/set_scno.c | 2 ++ linux/nios2/set_scno.c | 2 ++ linux/or1k/set_scno.c | 2 ++ linux/riscv/set_scno.c | 2 ++ linux/s390/set_scno.c | 2 ++ linux/sparc/set_scno.c | 2 ++ linux/tile/set_scno.c | 2 ++ 14 files changed, 29 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 17125b8d..a23b361b 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,9 @@ Noteworthy changes in release ?.? (????-??-??) XDP_*, and *_MAGIC constants. * Bug fixes + * Fixed syscall tampering on arc, avr32, csky, ia64, m68k, metag, mips, + nios2, or1k, riscv, s390, s390x, sparc, sparc64, and tile architectures + when PTRACE_GET_SYSCALL_INFO is in use. * Fixed tests on alpha with Linux kernel headers 5.1+. * Portability diff --git a/linux/arc/set_scno.c b/linux/arc/set_scno.c index adbf218e..5314e87f 100644 --- a/linux/arc/set_scno.c +++ b/linux/arc/set_scno.c @@ -8,6 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; arc_regs.scratch.r8 = scno; return set_regs(tcp->pid); } diff --git a/linux/avr32/set_scno.c b/linux/avr32/set_scno.c index da218f4a..56c84abf 100644 --- a/linux/avr32/set_scno.c +++ b/linux/avr32/set_scno.c @@ -8,6 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; avr32_regs.r8 = scno; return set_regs(tcp->pid); } diff --git a/linux/csky/set_scno.c b/linux/csky/set_scno.c index 1f043caf..655d108f 100644 --- a/linux/csky/set_scno.c +++ b/linux/csky/set_scno.c @@ -8,6 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; #if defined(__CSKYABIV2__) csky_regs.regs[3] = scno; #else diff --git a/linux/ia64/set_scno.c b/linux/ia64/set_scno.c index c1c89df9..ff6c359d 100644 --- a/linux/ia64/set_scno.c +++ b/linux/ia64/set_scno.c @@ -8,7 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; ia64_regs.gr[15] = scno; - return set_regs(tcp->pid); } diff --git a/linux/m68k/set_scno.c b/linux/m68k/set_scno.c index 84e8835c..8e748a0b 100644 --- a/linux/m68k/set_scno.c +++ b/linux/m68k/set_scno.c @@ -8,6 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; m68k_regs.orig_d0 = scno; return set_regs(tcp->pid); } diff --git a/linux/metag/set_scno.c b/linux/metag/set_scno.c index 08dc3cd9..59206e1d 100644 --- a/linux/metag/set_scno.c +++ b/linux/metag/set_scno.c @@ -8,6 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; metag_regs.dx[0][1] = scno; return set_regs(tcp->pid); } diff --git a/linux/mips/set_scno.c b/linux/mips/set_scno.c index ad312583..db572c4e 100644 --- a/linux/mips/set_scno.c +++ b/linux/mips/set_scno.c @@ -8,6 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; mips_REG_V0 = scno; return set_regs(tcp->pid); } diff --git a/linux/nios2/set_scno.c b/linux/nios2/set_scno.c index 64f226b1..e79b1cd2 100644 --- a/linux/nios2/set_scno.c +++ b/linux/nios2/set_scno.c @@ -8,6 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; nios2_regs.regs[2] = scno; return set_regs(tcp->pid); } diff --git a/linux/or1k/set_scno.c b/linux/or1k/set_scno.c index df2c5ad8..ca72f92e 100644 --- a/linux/or1k/set_scno.c +++ b/linux/or1k/set_scno.c @@ -8,6 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; or1k_regs.gpr[11] = scno; return set_regs(tcp->pid); } diff --git a/linux/riscv/set_scno.c b/linux/riscv/set_scno.c index 2c586ee9..6e3272c5 100644 --- a/linux/riscv/set_scno.c +++ b/linux/riscv/set_scno.c @@ -8,6 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; riscv_regs.a7 = scno; return set_regs(tcp->pid); } diff --git a/linux/s390/set_scno.c b/linux/s390/set_scno.c index 650deecb..bb533591 100644 --- a/linux/s390/set_scno.c +++ b/linux/s390/set_scno.c @@ -12,6 +12,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; ARCH_REGSET.gprs[2] = scno; return set_regs(tcp->pid); } diff --git a/linux/sparc/set_scno.c b/linux/sparc/set_scno.c index 813fc3a0..5aa282c8 100644 --- a/linux/sparc/set_scno.c +++ b/linux/sparc/set_scno.c @@ -13,6 +13,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; sparc_regs.u_regs[U_REG_G1] = scno; return set_regs(tcp->pid); } diff --git a/linux/tile/set_scno.c b/linux/tile/set_scno.c index c1ab0d55..6def5f4c 100644 --- a/linux/tile/set_scno.c +++ b/linux/tile/set_scno.c @@ -8,6 +8,8 @@ static int arch_set_scno(struct tcb *tcp, kernel_ulong_t scno) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; tile_regs.regs[10] = scno; return set_regs(tcp->pid); } -- 2.40.0