diff options
| -rw-r--r-- | arch/Kconfig | 10 | ||||
| -rw-r--r-- | include/linux/ptrace.h | 5 | ||||
| -rw-r--r-- | include/linux/seccomp.h | 1 | ||||
| -rw-r--r-- | kernel/seccomp.c | 16 | 
4 files changed, 26 insertions, 6 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 66aef13f603..c024b3ed667 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -219,15 +219,15 @@ config ARCH_WANT_OLD_COMPAT_IPC  config HAVE_ARCH_SECCOMP_FILTER  	bool  	help -	  This symbol should be selected by an architecure if it provides: -	  asm/syscall.h: +	  An arch should select this symbol if it provides all of these things:  	  - syscall_get_arch()  	  - syscall_get_arguments()  	  - syscall_rollback()  	  - syscall_set_return_value() -	  SIGSYS siginfo_t support must be implemented. -	  __secure_computing()/secure_computing()'s return value must be -	  checked, with -1 resulting in the syscall being skipped. +	  - SIGSYS siginfo_t support +	  - secure_computing is called from a ptrace_event()-safe context +	  - secure_computing return value is checked and a return value of -1 +	    results in the system call being skipped immediately.  config SECCOMP_FILTER  	def_bool y diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 5c719627c2a..597e4fdb97f 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -58,6 +58,7 @@  #define PTRACE_EVENT_EXEC	4  #define PTRACE_EVENT_VFORK_DONE	5  #define PTRACE_EVENT_EXIT	6 +#define PTRACE_EVENT_SECCOMP	7  /* Extended result codes which enabled by means other than options.  */  #define PTRACE_EVENT_STOP	128 @@ -69,8 +70,9 @@  #define PTRACE_O_TRACEEXEC	(1 << PTRACE_EVENT_EXEC)  #define PTRACE_O_TRACEVFORKDONE	(1 << PTRACE_EVENT_VFORK_DONE)  #define PTRACE_O_TRACEEXIT	(1 << PTRACE_EVENT_EXIT) +#define PTRACE_O_TRACESECCOMP	(1 << PTRACE_EVENT_SECCOMP) -#define PTRACE_O_MASK		0x0000007f +#define PTRACE_O_MASK		0x000000ff  #include <asm/ptrace.h> @@ -98,6 +100,7 @@  #define PT_TRACE_EXEC		PT_EVENT_FLAG(PTRACE_EVENT_EXEC)  #define PT_TRACE_VFORK_DONE	PT_EVENT_FLAG(PTRACE_EVENT_VFORK_DONE)  #define PT_TRACE_EXIT		PT_EVENT_FLAG(PTRACE_EVENT_EXIT) +#define PT_TRACE_SECCOMP	PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP)  /* single stepping state bits (used on ARM and PA-RISC) */  #define PT_SINGLESTEP_BIT	31 diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index 317ccb78cf4..5818e869651 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h @@ -21,6 +21,7 @@  #define SECCOMP_RET_KILL	0x00000000U /* kill the task immediately */  #define SECCOMP_RET_TRAP	0x00030000U /* disallow and force a SIGSYS */  #define SECCOMP_RET_ERRNO	0x00050000U /* returns an errno */ +#define SECCOMP_RET_TRACE	0x7ff00000U /* pass to a tracer or disallow */  #define SECCOMP_RET_ALLOW	0x7fff0000U /* allow */  /* Masks for the return value sections. */ diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 9c3830692a0..d9db6ec46bc 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -24,6 +24,7 @@  #ifdef CONFIG_SECCOMP_FILTER  #include <asm/syscall.h>  #include <linux/filter.h> +#include <linux/ptrace.h>  #include <linux/security.h>  #include <linux/slab.h>  #include <linux/tracehook.h> @@ -408,6 +409,21 @@ int __secure_computing(int this_syscall)  			/* Let the filter pass back 16 bits of data. */  			seccomp_send_sigsys(this_syscall, data);  			goto skip; +		case SECCOMP_RET_TRACE: +			/* Skip these calls if there is no tracer. */ +			if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) +				goto skip; +			/* Allow the BPF to provide the event message */ +			ptrace_event(PTRACE_EVENT_SECCOMP, data); +			/* +			 * The delivery of a fatal signal during event +			 * notification may silently skip tracer notification. +			 * Terminating the task now avoids executing a system +			 * call that may not be intended. +			 */ +			if (fatal_signal_pending(current)) +				break; +			return 0;  		case SECCOMP_RET_ALLOW:  			return 0;  		case SECCOMP_RET_KILL:  |