From: Andrea Arcangeli <andrea@cpushare.com>

This patch against 12-rc1 adds seccomp to the ppc64 arch.  I tested it
successfully with the seccomp_test.  I didn't bother to change the syscall
exit not to check for TIF_SECCOMP, in theory that bit could be optimized
but it's an optimization in the slow path, and current code is a bit
simpler.  I also verified it still compiles and works fine on x86 and
x86-64.

Instead of the TIF_32BIT redefine, if you want to change x86-64 to use
TIF_32BIT too (instead of TIF_IA32), let me know.

Signed-off-by: Andrea Arcangeli <andrea@cpushare.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/ppc64/Kconfig              |   17 +++++++++++++++++
 25-akpm/arch/ppc64/kernel/ptrace.c      |    3 +++
 25-akpm/include/asm-i386/seccomp.h      |   16 ++++++++++++++++
 25-akpm/include/asm-ppc64/seccomp.h     |   21 +++++++++++++++++++++
 25-akpm/include/asm-ppc64/thread_info.h |    4 +++-
 25-akpm/include/asm-x86_64/seccomp.h    |   24 ++++++++++++++++++++++++
 25-akpm/include/asm-x86_64/unistd.h     |    2 +-
 25-akpm/include/linux/seccomp.h         |    1 +
 25-akpm/kernel/seccomp.c                |   32 +++++++-------------------------
 9 files changed, 93 insertions(+), 27 deletions(-)

diff -puN arch/ppc64/Kconfig~seccomp-for-ppc64 arch/ppc64/Kconfig
--- 25/arch/ppc64/Kconfig~seccomp-for-ppc64	2005-03-28 16:14:21.000000000 -0800
+++ 25-akpm/arch/ppc64/Kconfig	2005-03-28 16:14:21.000000000 -0800
@@ -278,6 +278,23 @@ config LPARCFG
 	Provide system capacity information via human readable
 	<key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
 
+config SECCOMP
+	bool "Enable seccomp to safely compute untrusted bytecode"
+	depends on PROC_FS
+	default y
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via /proc/<pid>/seccomp, it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y. Only embedded should say N here.
+
 endmenu
 
 
diff -puN arch/ppc64/kernel/ptrace.c~seccomp-for-ppc64 arch/ppc64/kernel/ptrace.c
--- 25/arch/ppc64/kernel/ptrace.c~seccomp-for-ppc64	2005-03-28 16:14:21.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/ptrace.c	2005-03-28 16:14:21.000000000 -0800
@@ -27,6 +27,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
+#include <linux/seccomp.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -317,6 +318,8 @@ void do_syscall_trace_enter(struct pt_re
 
 void do_syscall_trace_leave(struct pt_regs *regs)
 {
+	secure_computing(regs->gpr[0]);
+
 	if (unlikely(current->audit_context))
 		audit_syscall_exit(current,
 				   (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
diff -puN /dev/null include/asm-i386/seccomp.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-i386/seccomp.h	2005-03-28 16:14:21.000000000 -0800
@@ -0,0 +1,16 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h>
+
+#ifdef TIF_32BIT
+#error "unexpected TIF_32BIT on i386"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff -puN /dev/null include/asm-ppc64/seccomp.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-ppc64/seccomp.h	2005-03-28 16:14:21.000000000 -0800
@@ -0,0 +1,21 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h> /* already defines TIF_32BIT */
+
+#ifndef TIF_32BIT
+#error "unexpected TIF_32BIT on ppc64"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_read
+#define __NR_seccomp_write_32 __NR_write
+#define __NR_seccomp_exit_32 __NR_exit
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff -puN include/asm-ppc64/thread_info.h~seccomp-for-ppc64 include/asm-ppc64/thread_info.h
--- 25/include/asm-ppc64/thread_info.h~seccomp-for-ppc64	2005-03-28 16:14:21.000000000 -0800
+++ 25-akpm/include/asm-ppc64/thread_info.h	2005-03-28 16:14:21.000000000 -0800
@@ -101,6 +101,7 @@ static inline struct thread_info *curren
 #define TIF_SYSCALL_AUDIT	8	/* syscall auditing active */
 #define TIF_SINGLESTEP		9	/* singlestepping active */
 #define TIF_MEMDIE		10
+#define TIF_SECCOMP		11	/* secure computing */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -113,7 +114,8 @@ static inline struct thread_info *curren
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
-#define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+#define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
 				 _TIF_NEED_RESCHED)
diff -puN /dev/null include/asm-x86_64/seccomp.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-x86_64/seccomp.h	2005-03-28 16:14:21.000000000 -0800
@@ -0,0 +1,24 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h>
+
+#ifdef TIF_32BIT
+#error "unexpected TIF_32BIT on x86_64"
+#else
+#define TIF_32BIT TIF_IA32
+#endif
+
+#include <linux/unistd.h>
+#include <asm/ia32_unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_ia32_read
+#define __NR_seccomp_write_32 __NR_ia32_write
+#define __NR_seccomp_exit_32 __NR_ia32_exit
+#define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff -puN include/asm-x86_64/unistd.h~seccomp-for-ppc64 include/asm-x86_64/unistd.h
--- 25/include/asm-x86_64/unistd.h~seccomp-for-ppc64	2005-03-28 16:14:21.000000000 -0800
+++ 25-akpm/include/asm-x86_64/unistd.h	2005-03-28 16:14:21.000000000 -0800
@@ -774,7 +774,7 @@ asmlinkage long sys_pipe(int *fildes);
 
 asmlinkage long sys_ptrace(long request, long pid,
 				unsigned long addr, long data);
-asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs);
+asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs);
 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
diff -puN include/linux/seccomp.h~seccomp-for-ppc64 include/linux/seccomp.h
--- 25/include/linux/seccomp.h~seccomp-for-ppc64	2005-03-28 16:14:21.000000000 -0800
+++ 25-akpm/include/linux/seccomp.h	2005-03-28 16:14:21.000000000 -0800
@@ -8,6 +8,7 @@
 #define NR_SECCOMP_MODES 1
 
 #include <linux/thread_info.h>
+#include <asm/seccomp.h>
 
 typedef struct { int mode; } seccomp_t;
 
diff -puN kernel/seccomp.c~seccomp-for-ppc64 kernel/seccomp.c
--- 25/kernel/seccomp.c~seccomp-for-ppc64	2005-03-28 16:14:21.000000000 -0800
+++ 25-akpm/kernel/seccomp.c	2005-03-28 16:14:21.000000000 -0800
@@ -8,10 +8,6 @@
 
 #include <linux/seccomp.h>
 #include <linux/sched.h>
-#include <asm/unistd.h>
-#ifdef TIF_IA32
-#include <asm/ia32_unistd.h>
-#endif
 
 /* #define SECCOMP_DEBUG 1 */
 
@@ -21,27 +17,13 @@
  * to limit the stack allocations too.
  */
 static int mode1_syscalls[] = {
-	__NR_read, __NR_write, __NR_exit,
-	/*
-	 * Allow either sigreturn or rt_sigreturn, newer archs
-	 * like x86-64 only defines __NR_rt_sigreturn.
-	 */
-#ifdef __NR_sigreturn
-	__NR_sigreturn,
-#else
-	__NR_rt_sigreturn,
-#endif
+	__NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn,
 	0, /* null terminated */
 };
 
-#ifdef TIF_IA32
-static int mode1_syscalls_32bit[] = {
-	__NR_ia32_read, __NR_ia32_write, __NR_ia32_exit,
-	/*
-	 * Allow either sigreturn or rt_sigreturn, newer archs
-	 * like x86-64 only defines __NR_rt_sigreturn.
-	 */
-	__NR_ia32_sigreturn,
+#ifdef TIF_32BIT
+static int mode1_syscalls_32[] = {
+	__NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
 	0, /* null terminated */
 };
 #endif
@@ -54,9 +36,9 @@ void __secure_computing(int this_syscall
 	switch (mode) {
 	case 1:
 		syscall = mode1_syscalls;
-#ifdef TIF_IA32
-		if (test_thread_flag(TIF_IA32))
-			syscall = mode1_syscalls_32bit;
+#ifdef TIF_32BIT
+		if (test_thread_flag(TIF_32BIT))
+			syscall = mode1_syscalls_32;
 #endif
 		do {
 			if (*syscall == this_syscall)
_