aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorWill Drewry <wad@chromium.org>2012-04-12 17:47:57 -0400
committerJames Morris <james.l.morris@oracle.com>2012-04-13 21:13:20 -0400
commite2cfabdfd075648216f99c2c03821cf3f47c1727 (patch)
treed207e062d5b0bbd421aace9f7dfdc144aab4ed18 /include
parentb7456536cf9466b402b540c5588d79a4177c723a (diff)
seccomp: add system call filtering using BPF
[This patch depends on luto@mit.edu's no_new_privs patch: https://lkml.org/lkml/2012/1/30/264 The whole series including Andrew's patches can be found here: https://github.com/redpig/linux/tree/seccomp Complete diff here: https://github.com/redpig/linux/compare/1dc65fed...seccomp ] This patch adds support for seccomp mode 2. Mode 2 introduces the ability for unprivileged processes to install system call filtering policy expressed in terms of a Berkeley Packet Filter (BPF) program. This program will be evaluated in the kernel for each system call the task makes and computes a result based on data in the format of struct seccomp_data. A filter program may be installed by calling: struct sock_fprog fprog = { ... }; ... prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &fprog); The return value of the filter program determines if the system call is allowed to proceed or denied. If the first filter program installed allows prctl(2) calls, then the above call may be made repeatedly by a task to further reduce its access to the kernel. All attached programs must be evaluated before a system call will be allowed to proceed. Filter programs will be inherited across fork/clone and execve. However, if the task attaching the filter is unprivileged (!CAP_SYS_ADMIN) the no_new_privs bit will be set on the task. This ensures that unprivileged tasks cannot attach filters that affect privileged tasks (e.g., setuid binary). There are a number of benefits to this approach. A few of which are as follows: - BPF has been exposed to userland for a long time - BPF optimization (and JIT'ing) are well understood - Userland already knows its ABI: system call numbers and desired arguments - No time-of-check-time-of-use vulnerable data accesses are possible. - system call arguments are loaded on access only to minimize copying required for system call policy decisions. Mode 2 support is restricted to architectures that enable HAVE_ARCH_SECCOMP_FILTER. In this patch, the primary dependency is on syscall_get_arguments(). The full desired scope of this feature will add a few minor additional requirements expressed later in this series. Based on discussion, SECCOMP_RET_ERRNO and SECCOMP_RET_TRACE seem to be the desired additional functionality. No architectures are enabled in this patch. Signed-off-by: Will Drewry <wad@chromium.org> Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Reviewed-by: Indan Zupancic <indan@nul.nu> Acked-by: Eric Paris <eparis@redhat.com> Reviewed-by: Kees Cook <keescook@chromium.org> v18: - rebase to v3.4-rc2 - s/chk/check/ (akpm@linux-foundation.org,jmorris@namei.org) - allocate with GFP_KERNEL|__GFP_NOWARN (indan@nul.nu) - add a comment for get_u32 regarding endianness (akpm@) - fix other typos, style mistakes (akpm@) - added acked-by v17: - properly guard seccomp filter needed headers (leann@ubuntu.com) - tighten return mask to 0x7fff0000 v16: - no change v15: - add a 4 instr penalty when counting a path to account for seccomp_filter size (indan@nul.nu) - drop the max insns to 256KB (indan@nul.nu) - return ENOMEM if the max insns limit has been hit (indan@nul.nu) - move IP checks after args (indan@nul.nu) - drop !user_filter check (indan@nul.nu) - only allow explicit bpf codes (indan@nul.nu) - exit_code -> exit_sig v14: - put/get_seccomp_filter takes struct task_struct (indan@nul.nu,keescook@chromium.org) - adds seccomp_chk_filter and drops general bpf_run/chk_filter user - add seccomp_bpf_load for use by net/core/filter.c - lower max per-process/per-hierarchy: 1MB - moved nnp/capability check prior to allocation (all of the above: indan@nul.nu) v13: - rebase on to 88ebdda6159ffc15699f204c33feb3e431bf9bdc v12: - added a maximum instruction count per path (indan@nul.nu,oleg@redhat.com) - removed copy_seccomp (keescook@chromium.org,indan@nul.nu) - reworded the prctl_set_seccomp comment (indan@nul.nu) v11: - reorder struct seccomp_data to allow future args expansion (hpa@zytor.com) - style clean up, @compat dropped, compat_sock_fprog32 (indan@nul.nu) - do_exit(SIGSYS) (keescook@chromium.org, luto@mit.edu) - pare down Kconfig doc reference. - extra comment clean up v10: - seccomp_data has changed again to be more aesthetically pleasing (hpa@zytor.com) - calling convention is noted in a new u32 field using syscall_get_arch. This allows for cross-calling convention tasks to use seccomp filters. (hpa@zytor.com) - lots of clean up (thanks, Indan!) v9: - n/a v8: - use bpf_chk_filter, bpf_run_filter. update load_fns - Lots of fixes courtesy of indan@nul.nu: -- fix up load behavior, compat fixups, and merge alloc code, -- renamed pc and dropped __packed, use bool compat. -- Added a hidden CONFIG_SECCOMP_FILTER to synthesize non-arch dependencies v7: (massive overhaul thanks to Indan, others) - added CONFIG_HAVE_ARCH_SECCOMP_FILTER - merged into seccomp.c - minimal seccomp_filter.h - no config option (part of seccomp) - no new prctl - doesn't break seccomp on systems without asm/syscall.h (works but arg access always fails) - dropped seccomp_init_task, extra free functions, ... - dropped the no-asm/syscall.h code paths - merges with network sk_run_filter and sk_chk_filter v6: - fix memory leak on attach compat check failure - require no_new_privs || CAP_SYS_ADMIN prior to filter installation. (luto@mit.edu) - s/seccomp_struct_/seccomp_/ for macros/functions (amwang@redhat.com) - cleaned up Kconfig (amwang@redhat.com) - on block, note if the call was compat (so the # means something) v5: - uses syscall_get_arguments (indan@nul.nu,oleg@redhat.com, mcgrathr@chromium.org) - uses union-based arg storage with hi/lo struct to handle endianness. Compromises between the two alternate proposals to minimize extra arg shuffling and account for endianness assuming userspace uses offsetof(). (mcgrathr@chromium.org, indan@nul.nu) - update Kconfig description - add include/seccomp_filter.h and add its installation - (naive) on-demand syscall argument loading - drop seccomp_t (eparis@redhat.com) v4: - adjusted prctl to make room for PR_[SG]ET_NO_NEW_PRIVS - now uses current->no_new_privs (luto@mit.edu,torvalds@linux-foundation.com) - assign names to seccomp modes (rdunlap@xenotime.net) - fix style issues (rdunlap@xenotime.net) - reworded Kconfig entry (rdunlap@xenotime.net) v3: - macros to inline (oleg@redhat.com) - init_task behavior fixed (oleg@redhat.com) - drop creator entry and extra NULL check (oleg@redhat.com) - alloc returns -EINVAL on bad sizing (serge.hallyn@canonical.com) - adds tentative use of "always_unprivileged" as per torvalds@linux-foundation.org and luto@mit.edu v2: - (patch 2 only) Signed-off-by: James Morris <james.l.morris@oracle.com>
Diffstat (limited to 'include')
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/seccomp.h76
2 files changed, 73 insertions, 4 deletions
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 3c9b616c834a..5c93d6c5d591 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -332,6 +332,7 @@ header-y += scc.h
332header-y += sched.h 332header-y += sched.h
333header-y += screen_info.h 333header-y += screen_info.h
334header-y += sdla.h 334header-y += sdla.h
335header-y += seccomp.h
335header-y += securebits.h 336header-y += securebits.h
336header-y += selinux_netlink.h 337header-y += selinux_netlink.h
337header-y += sem.h 338header-y += sem.h
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index d61f27fcaa97..86bb68fc7683 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -1,14 +1,67 @@
1#ifndef _LINUX_SECCOMP_H 1#ifndef _LINUX_SECCOMP_H
2#define _LINUX_SECCOMP_H 2#define _LINUX_SECCOMP_H
3 3
4#include <linux/compiler.h>
5#include <linux/types.h>
6
7
8/* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */
9#define SECCOMP_MODE_DISABLED 0 /* seccomp is not in use. */
10#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
11#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
12
13/*
14 * All BPF programs must return a 32-bit value.
15 * The bottom 16-bits are reserved for future use.
16 * The upper 16-bits are ordered from least permissive values to most.
17 *
18 * The ordering ensures that a min_t() over composed return values always
19 * selects the least permissive choice.
20 */
21#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
22#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
23
24/* Masks for the return value sections. */
25#define SECCOMP_RET_ACTION 0x7fff0000U
26#define SECCOMP_RET_DATA 0x0000ffffU
27
28/**
29 * struct seccomp_data - the format the BPF program executes over.
30 * @nr: the system call number
31 * @arch: indicates system call convention as an AUDIT_ARCH_* value
32 * as defined in <linux/audit.h>.
33 * @instruction_pointer: at the time of the system call.
34 * @args: up to 6 system call arguments always stored as 64-bit values
35 * regardless of the architecture.
36 */
37struct seccomp_data {
38 int nr;
39 __u32 arch;
40 __u64 instruction_pointer;
41 __u64 args[6];
42};
4 43
44#ifdef __KERNEL__
5#ifdef CONFIG_SECCOMP 45#ifdef CONFIG_SECCOMP
6 46
7#include <linux/thread_info.h> 47#include <linux/thread_info.h>
8#include <asm/seccomp.h> 48#include <asm/seccomp.h>
9 49
50struct seccomp_filter;
51/**
52 * struct seccomp - the state of a seccomp'ed process
53 *
54 * @mode: indicates one of the valid values above for controlled
55 * system calls available to a process.
56 * @filter: The metadata and ruleset for determining what system calls
57 * are allowed for a task.
58 *
59 * @filter must only be accessed from the context of current as there
60 * is no locking.
61 */
10struct seccomp { 62struct seccomp {
11 int mode; 63 int mode;
64 struct seccomp_filter *filter;
12}; 65};
13 66
14extern void __secure_computing(int); 67extern void __secure_computing(int);
@@ -19,7 +72,7 @@ static inline void secure_computing(int this_syscall)
19} 72}
20 73
21extern long prctl_get_seccomp(void); 74extern long prctl_get_seccomp(void);
22extern long prctl_set_seccomp(unsigned long); 75extern long prctl_set_seccomp(unsigned long, char __user *);
23 76
24static inline int seccomp_mode(struct seccomp *s) 77static inline int seccomp_mode(struct seccomp *s)
25{ 78{
@@ -31,15 +84,16 @@ static inline int seccomp_mode(struct seccomp *s)
31#include <linux/errno.h> 84#include <linux/errno.h>
32 85
33struct seccomp { }; 86struct seccomp { };
87struct seccomp_filter { };
34 88
35#define secure_computing(x) do { } while (0) 89#define secure_computing(x) 0
36 90
37static inline long prctl_get_seccomp(void) 91static inline long prctl_get_seccomp(void)
38{ 92{
39 return -EINVAL; 93 return -EINVAL;
40} 94}
41 95
42static inline long prctl_set_seccomp(unsigned long arg2) 96static inline long prctl_set_seccomp(unsigned long arg2, char __user *arg3)
43{ 97{
44 return -EINVAL; 98 return -EINVAL;
45} 99}
@@ -48,7 +102,21 @@ static inline int seccomp_mode(struct seccomp *s)
48{ 102{
49 return 0; 103 return 0;
50} 104}
51
52#endif /* CONFIG_SECCOMP */ 105#endif /* CONFIG_SECCOMP */
53 106
107#ifdef CONFIG_SECCOMP_FILTER
108extern void put_seccomp_filter(struct task_struct *tsk);
109extern void get_seccomp_filter(struct task_struct *tsk);
110extern u32 seccomp_bpf_load(int off);
111#else /* CONFIG_SECCOMP_FILTER */
112static inline void put_seccomp_filter(struct task_struct *tsk)
113{
114 return;
115}
116static inline void get_seccomp_filter(struct task_struct *tsk)
117{
118 return;
119}
120#endif /* CONFIG_SECCOMP_FILTER */
121#endif /* __KERNEL__ */
54#endif /* _LINUX_SECCOMP_H */ 122#endif /* _LINUX_SECCOMP_H */