lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 11 Aug 2017 21:56:53 +0100
From:   James Hogan <james.hogan@...tec.com>
To:     <linux-mips@...ux-mips.org>
CC:     <linux-kernel@...r.kernel.org>,
        James Hogan <james.hogan@...tec.com>,
        Ralf Baechle <ralf@...ux-mips.org>,
        Oleg Nesterov <oleg@...hat.com>,
        Kees Cook <keescook@...omium.org>,
        Andy Lutomirski <luto@...capital.net>,
        Will Drewry <wad@...omium.org>
Subject: [PATCH 4/4] MIPS/ptrace: Add PTRACE_SET_SYSCALL operation

Add a PTRACE_SET_SYSCALL ptrace operation to allow the system call to be
cancelled independently to the value of the v0 system call number
register.

This is needed for SECCOMP_RET_TRACE when the tracer wants to cancel the
system call, since it has to set both the system call number to -1 and
the chosen return value, both of which reside in the same register (v0).
The tracer should set the return value first, followed by
PTRACE_SET_SYSCALL to set the system call number to -1.

That is in contrast to the normal ptrace syscall hook which triggers the
tracer on both entry and exit, allowing the system call to be cancelled
during the entry hook (setting system call number register to -1, or
optionally using PTRACE_SET_SYSCALL), separately to setting the return
value during the exit hook.

Positive values (to change the syscall that should be executed instead
of cancelling it entirely) are explicitly disallowed at the moment. The
same thing can be done safely already by writing the v0 system call
number register and the argument registers, and allowing
thread_info::syscall to be changed to a different value independently of
the v0 register would potentially allow seccomp or the syscall trace
events to be fooled into thinking a different system call was being
executed.

Signed-off-by: James Hogan <james.hogan@...tec.com>
Cc: Ralf Baechle <ralf@...ux-mips.org>
Cc: Oleg Nesterov <oleg@...hat.com>
Cc: Kees Cook <keescook@...omium.org>
Cc: Andy Lutomirski <luto@...capital.net>
Cc: Will Drewry <wad@...omium.org>
Cc: linux-mips@...ux-mips.org
---
 arch/mips/include/uapi/asm/ptrace.h |  1 +
 arch/mips/kernel/ptrace.c           | 11 +++++++++++
 arch/mips/kernel/ptrace32.c         | 11 +++++++++++
 3 files changed, 23 insertions(+)

diff --git a/arch/mips/include/uapi/asm/ptrace.h b/arch/mips/include/uapi/asm/ptrace.h
index 91a3d197ede3..23af103c4e8d 100644
--- a/arch/mips/include/uapi/asm/ptrace.h
+++ b/arch/mips/include/uapi/asm/ptrace.h
@@ -58,6 +58,7 @@ struct pt_regs {
 
 #define PTRACE_GET_THREAD_AREA	25
 #define PTRACE_SET_THREAD_AREA	26
+#define PTRACE_SET_SYSCALL	27
 
 /* Calls to trace a 64bit program from a 32bit program.	 */
 #define PTRACE_PEEKTEXT_3264	0xc0
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 465fc5633e61..9bf31a990c6e 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -853,6 +853,17 @@ long arch_ptrace(struct task_struct *child, long request,
 		ret = put_user(task_thread_info(child)->tp_value, datalp);
 		break;
 
+	case PTRACE_SET_SYSCALL:
+		/*
+		 * This is currently only useful to cancel the syscall from a
+		 * seccomp RET_TRACE tracer.
+		 */
+		if ((long)data >= 0)
+			return -EINVAL;
+		task_thread_info(child)->syscall = -1;
+		ret = 0;
+		break;
+
 	case PTRACE_GET_WATCH_REGS:
 		ret = ptrace_get_watch_regs(child, addrp);
 		break;
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 2b9260f92ccd..cca76aec9c10 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -287,6 +287,17 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 				(unsigned int __user *) (unsigned long) data);
 		break;
 
+	case PTRACE_SET_SYSCALL:
+		/*
+		 * This is currently only useful to cancel the syscall from a
+		 * seccomp RET_TRACE tracer.
+		 */
+		if ((long)data >= 0)
+			return -EINVAL;
+		task_thread_info(child)->syscall = -1;
+		ret = 0;
+		break;
+
 	case PTRACE_GET_THREAD_AREA_3264:
 		ret = put_user(task_thread_info(child)->tp_value,
 				(unsigned long __user *) (unsigned long) data);
-- 
2.13.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ