From 1a1a23da04d9ea913d2e98c001b89e9f94873deb Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 4 Jul 2019 18:25:49 +0000 Subject: [PATCH] sparc, sparc64: fix syscall tampering when PTRACE_GET_SYSCALL_INFO is in use When PTRACE_GET_SYSCALL_INFO is in use on sparc, psr is not loaded, so it has to be loaded explicitly before tampering. Likewise, when PTRACE_GET_SYSCALL_INFO is in use on sparc64, tstate is not loaded, so it has to be loaded explicitly before tampering. * linux/sparc/set_error.c (arch_set_error, arch_set_success): Explicitly call get_regs before changing psr when PTRACE_GET_SYSCALL_INFO is in use. * linux/sparc64/set_error.c (arch_set_error, arch_set_success): Explicitly call get_regs before changing tstate when PTRACE_GET_SYSCALL_INFO is in use. * NEWS: Mention this fix. --- NEWS | 2 +- linux/sparc/set_error.c | 4 ++++ linux/sparc64/set_error.c | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 84ad39a3..70dff88f 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,7 @@ Noteworthy changes in release ?.? (????-??-??) ============================================== * Bug fixes - * Fixed syscall tampering on powerpc and powerpc64 when + * Fixed syscall tampering on powerpc, powerpc64, sparc, and sparc64 when PTRACE_GET_SYSCALL_INFO is in use. * Improvements diff --git a/linux/sparc/set_error.c b/linux/sparc/set_error.c index 7cffdd3f..1679df0f 100644 --- a/linux/sparc/set_error.c +++ b/linux/sparc/set_error.c @@ -8,6 +8,8 @@ static int arch_set_error(struct tcb *tcp) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; sparc_regs.psr |= PSR_C; sparc_regs.u_regs[U_REG_O0] = tcp->u_error; return set_regs(tcp->pid); @@ -16,6 +18,8 @@ arch_set_error(struct tcb *tcp) static int arch_set_success(struct tcb *tcp) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; sparc_regs.psr &= ~PSR_C; sparc_regs.u_regs[U_REG_O0] = tcp->u_rval; return set_regs(tcp->pid); diff --git a/linux/sparc64/set_error.c b/linux/sparc64/set_error.c index e89c578e..290fad34 100644 --- a/linux/sparc64/set_error.c +++ b/linux/sparc64/set_error.c @@ -8,6 +8,8 @@ static int arch_set_error(struct tcb *tcp) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; sparc_regs.tstate |= 0x1100000000UL; sparc_regs.u_regs[U_REG_O0] = tcp->u_error; return set_regs(tcp->pid); @@ -16,6 +18,8 @@ arch_set_error(struct tcb *tcp) static int arch_set_success(struct tcb *tcp) { + if (ptrace_syscall_info_is_valid() && get_regs(tcp) < 0) + return -1; sparc_regs.tstate &= ~0x1100000000UL; sparc_regs.u_regs[U_REG_O0] = tcp->u_rval; return set_regs(tcp->pid); -- 2.40.0