mirror of
https://github.com/archlinuxarm/PKGBUILDs.git
synced 2024-11-28 22:57:37 +00:00
237 lines
7.8 KiB
Diff
237 lines
7.8 KiB
Diff
|
From 1d7729de997ef9ecb1c9eef1ccf8d191197f984c Mon Sep 17 00:00:00 2001
|
||
|
From: Kees Cook <keescook@chromium.org>
|
||
|
Date: Wed, 25 Jun 2014 16:08:24 -0700
|
||
|
Subject: [PATCH 06/16] seccomp: add "seccomp" syscall
|
||
|
|
||
|
This adds the new "seccomp" syscall with both an "operation" and "flags"
|
||
|
parameter for future expansion. The third argument is a pointer value,
|
||
|
used with the SECCOMP_SET_MODE_FILTER operation. Currently, flags must
|
||
|
be 0. This is functionally equivalent to prctl(PR_SET_SECCOMP, ...).
|
||
|
|
||
|
In addition to the TSYNC flag later in this patch series, there is a
|
||
|
non-zero chance that this syscall could be used for configuring a fixed
|
||
|
argument area for seccomp-tracer-aware processes to pass syscall arguments
|
||
|
in the future. Hence, the use of "seccomp" not simply "seccomp_add_filter"
|
||
|
for this syscall. Additionally, this syscall uses operation, flags,
|
||
|
and user pointer for arguments because strictly passing arguments via
|
||
|
a user pointer would mean seccomp itself would be unable to trivially
|
||
|
filter the seccomp syscall itself.
|
||
|
|
||
|
Signed-off-by: Kees Cook <keescook@chromium.org>
|
||
|
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
|
||
|
Reviewed-by: Andy Lutomirski <luto@amacapital.net>
|
||
|
(cherry picked from commit 48dc92b9fc3926844257316e75ba11eb5c742b2c)
|
||
|
---
|
||
|
arch/Kconfig | 1 +
|
||
|
arch/x86/syscalls/syscall_32.tbl | 1 +
|
||
|
arch/x86/syscalls/syscall_64.tbl | 1 +
|
||
|
include/linux/syscalls.h | 2 ++
|
||
|
include/uapi/asm-generic/unistd.h | 3 +-
|
||
|
include/uapi/linux/seccomp.h | 4 +++
|
||
|
kernel/seccomp.c | 55 ++++++++++++++++++++++++++++---
|
||
|
kernel/sys_ni.c | 3 ++
|
||
|
8 files changed, 64 insertions(+), 6 deletions(-)
|
||
|
|
||
|
diff --git a/arch/Kconfig b/arch/Kconfig
|
||
|
index 94e811ef45f5..6ba80554149c 100644
|
||
|
--- a/arch/Kconfig
|
||
|
+++ b/arch/Kconfig
|
||
|
@@ -321,6 +321,7 @@ config HAVE_ARCH_SECCOMP_FILTER
|
||
|
- 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.
|
||
|
+ - seccomp syscall wired up
|
||
|
|
||
|
config SECCOMP_FILTER
|
||
|
def_bool y
|
||
|
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
|
||
|
index 16209a990be7..cc4c8b448867 100644
|
||
|
--- a/arch/x86/syscalls/syscall_32.tbl
|
||
|
+++ b/arch/x86/syscalls/syscall_32.tbl
|
||
|
@@ -360,4 +360,5 @@
|
||
|
351 i386 sched_setattr sys_sched_setattr
|
||
|
352 i386 sched_getattr sys_sched_getattr
|
||
|
353 i386 renameat2 sys_renameat2
|
||
|
+354 i386 seccomp sys_seccomp
|
||
|
356 i386 memfd_create sys_memfd_create
|
||
|
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
|
||
|
index 9fdc507c0641..a22cd271b891 100644
|
||
|
--- a/arch/x86/syscalls/syscall_64.tbl
|
||
|
+++ b/arch/x86/syscalls/syscall_64.tbl
|
||
|
@@ -323,6 +323,7 @@
|
||
|
314 common sched_setattr sys_sched_setattr
|
||
|
315 common sched_getattr sys_sched_getattr
|
||
|
316 common renameat2 sys_renameat2
|
||
|
+317 common seccomp sys_seccomp
|
||
|
319 common memfd_create sys_memfd_create
|
||
|
|
||
|
#
|
||
|
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
|
||
|
index 9836e157fc5e..1e6977f03277 100644
|
||
|
--- a/include/linux/syscalls.h
|
||
|
+++ b/include/linux/syscalls.h
|
||
|
@@ -867,4 +867,6 @@ asmlinkage long sys_process_vm_writev(pid_t pid,
|
||
|
asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
|
||
|
unsigned long idx1, unsigned long idx2);
|
||
|
asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
|
||
|
+asmlinkage long sys_seccomp(unsigned int op, unsigned int flags,
|
||
|
+ const char __user *uargs);
|
||
|
#endif
|
||
|
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
|
||
|
index b4588752d50f..4f1d521e0af3 100644
|
||
|
--- a/include/uapi/asm-generic/unistd.h
|
||
|
+++ b/include/uapi/asm-generic/unistd.h
|
||
|
@@ -699,7 +699,8 @@ __SYSCALL(__NR_sched_setattr, sys_sched_setattr)
|
||
|
__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
|
||
|
#define __NR_renameat2 276
|
||
|
__SYSCALL(__NR_renameat2, sys_renameat2)
|
||
|
-__SYSCALL(277, sys_ni_syscall)
|
||
|
+#define __NR_seccomp 277
|
||
|
+__SYSCALL(__NR_seccomp, sys_seccomp)
|
||
|
__SYSCALL(278, sys_ni_syscall)
|
||
|
#define __NR_memfd_create 279
|
||
|
__SYSCALL(__NR_memfd_create, sys_memfd_create)
|
||
|
diff --git a/include/uapi/linux/seccomp.h b/include/uapi/linux/seccomp.h
|
||
|
index ac2dc9f72973..b258878ba754 100644
|
||
|
--- a/include/uapi/linux/seccomp.h
|
||
|
+++ b/include/uapi/linux/seccomp.h
|
||
|
@@ -10,6 +10,10 @@
|
||
|
#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
|
||
|
#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
|
||
|
|
||
|
+/* Valid operations for seccomp syscall. */
|
||
|
+#define SECCOMP_SET_MODE_STRICT 0
|
||
|
+#define SECCOMP_SET_MODE_FILTER 1
|
||
|
+
|
||
|
/*
|
||
|
* All BPF programs must return a 32-bit value.
|
||
|
* The bottom 16-bits are for optional return data.
|
||
|
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
|
||
|
index d82359968d57..d2596136b0d1 100644
|
||
|
--- a/kernel/seccomp.c
|
||
|
+++ b/kernel/seccomp.c
|
||
|
@@ -18,6 +18,7 @@
|
||
|
#include <linux/compat.h>
|
||
|
#include <linux/sched.h>
|
||
|
#include <linux/seccomp.h>
|
||
|
+#include <linux/syscalls.h>
|
||
|
|
||
|
/* #define SECCOMP_DEBUG 1 */
|
||
|
|
||
|
@@ -314,7 +315,7 @@ free_prog:
|
||
|
*
|
||
|
* Returns 0 on success and non-zero otherwise.
|
||
|
*/
|
||
|
-static long seccomp_attach_user_filter(char __user *user_filter)
|
||
|
+static long seccomp_attach_user_filter(const char __user *user_filter)
|
||
|
{
|
||
|
struct sock_fprog fprog;
|
||
|
long ret = -EFAULT;
|
||
|
@@ -517,6 +518,7 @@ out:
|
||
|
#ifdef CONFIG_SECCOMP_FILTER
|
||
|
/**
|
||
|
* seccomp_set_mode_filter: internal function for setting seccomp filter
|
||
|
+ * @flags: flags to change filter behavior
|
||
|
* @filter: struct sock_fprog containing filter
|
||
|
*
|
||
|
* This function may be called repeatedly to install additional filters.
|
||
|
@@ -527,11 +529,16 @@ out:
|
||
|
*
|
||
|
* Returns 0 on success or -EINVAL on failure.
|
||
|
*/
|
||
|
-static long seccomp_set_mode_filter(char __user *filter)
|
||
|
+static long seccomp_set_mode_filter(unsigned int flags,
|
||
|
+ const char __user *filter)
|
||
|
{
|
||
|
const unsigned long seccomp_mode = SECCOMP_MODE_FILTER;
|
||
|
long ret = -EINVAL;
|
||
|
|
||
|
+ /* Validate flags. */
|
||
|
+ if (flags != 0)
|
||
|
+ goto out;
|
||
|
+
|
||
|
if (!seccomp_may_assign_mode(seccomp_mode))
|
||
|
goto out;
|
||
|
|
||
|
@@ -544,12 +551,35 @@ out:
|
||
|
return ret;
|
||
|
}
|
||
|
#else
|
||
|
-static inline long seccomp_set_mode_filter(char __user *filter)
|
||
|
+static inline long seccomp_set_mode_filter(unsigned int flags,
|
||
|
+ const char __user *filter)
|
||
|
{
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
+/* Common entry point for both prctl and syscall. */
|
||
|
+static long do_seccomp(unsigned int op, unsigned int flags,
|
||
|
+ const char __user *uargs)
|
||
|
+{
|
||
|
+ switch (op) {
|
||
|
+ case SECCOMP_SET_MODE_STRICT:
|
||
|
+ if (flags != 0 || uargs != NULL)
|
||
|
+ return -EINVAL;
|
||
|
+ return seccomp_set_mode_strict();
|
||
|
+ case SECCOMP_SET_MODE_FILTER:
|
||
|
+ return seccomp_set_mode_filter(flags, uargs);
|
||
|
+ default:
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+SYSCALL_DEFINE3(seccomp, unsigned int, op, unsigned int, flags,
|
||
|
+ const char __user *, uargs)
|
||
|
+{
|
||
|
+ return do_seccomp(op, flags, uargs);
|
||
|
+}
|
||
|
+
|
||
|
/**
|
||
|
* prctl_set_seccomp: configures current->seccomp.mode
|
||
|
* @seccomp_mode: requested mode to use
|
||
|
@@ -559,12 +589,27 @@ static inline long seccomp_set_mode_filter(char __user *filter)
|
||
|
*/
|
||
|
long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
|
||
|
{
|
||
|
+ unsigned int op;
|
||
|
+ char __user *uargs;
|
||
|
+
|
||
|
switch (seccomp_mode) {
|
||
|
case SECCOMP_MODE_STRICT:
|
||
|
- return seccomp_set_mode_strict();
|
||
|
+ op = SECCOMP_SET_MODE_STRICT;
|
||
|
+ /*
|
||
|
+ * Setting strict mode through prctl always ignored filter,
|
||
|
+ * so make sure it is always NULL here to pass the internal
|
||
|
+ * check in do_seccomp().
|
||
|
+ */
|
||
|
+ uargs = NULL;
|
||
|
+ break;
|
||
|
case SECCOMP_MODE_FILTER:
|
||
|
- return seccomp_set_mode_filter(filter);
|
||
|
+ op = SECCOMP_SET_MODE_FILTER;
|
||
|
+ uargs = filter;
|
||
|
+ break;
|
||
|
default:
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
+
|
||
|
+ /* prctl interface doesn't have flags, so they are always zero. */
|
||
|
+ return do_seccomp(op, 0, uargs);
|
||
|
}
|
||
|
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
|
||
|
index 489a4e6498c7..1f79e3714533 100644
|
||
|
--- a/kernel/sys_ni.c
|
||
|
+++ b/kernel/sys_ni.c
|
||
|
@@ -214,3 +214,6 @@ cond_syscall(compat_sys_open_by_handle_at);
|
||
|
|
||
|
/* compare kernel pointers */
|
||
|
cond_syscall(sys_kcmp);
|
||
|
+
|
||
|
+/* operate on Secure Computing state */
|
||
|
+cond_syscall(sys_seccomp);
|
||
|
--
|
||
|
2.18.0
|
||
|
|