Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/kernel/seccomp.c | |
3 | * | |
4 | * Copyright 2004-2005 Andrea Arcangeli <andrea@cpushare.com> | |
5 | * | |
6 | * This defines a simple but solid secure-computing mode. | |
7 | */ | |
8 | ||
85e7bac3 | 9 | #include <linux/audit.h> |
1da177e4 LT |
10 | #include <linux/seccomp.h> |
11 | #include <linux/sched.h> | |
5b101740 | 12 | #include <linux/compat.h> |
1da177e4 LT |
13 | |
14 | /* #define SECCOMP_DEBUG 1 */ | |
1d9d02fe | 15 | #define NR_SECCOMP_MODES 1 |
1da177e4 LT |
16 | |
17 | /* | |
18 | * Secure computing mode 1 allows only read/write/exit/sigreturn. | |
19 | * To be fully secure this must be combined with rlimit | |
20 | * to limit the stack allocations too. | |
21 | */ | |
22 | static int mode1_syscalls[] = { | |
23 | __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn, | |
24 | 0, /* null terminated */ | |
25 | }; | |
26 | ||
5b101740 | 27 | #ifdef CONFIG_COMPAT |
1da177e4 LT |
28 | static int mode1_syscalls_32[] = { |
29 | __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32, | |
30 | 0, /* null terminated */ | |
31 | }; | |
32 | #endif | |
33 | ||
34 | void __secure_computing(int this_syscall) | |
35 | { | |
36 | int mode = current->seccomp.mode; | |
37 | int * syscall; | |
38 | ||
39 | switch (mode) { | |
40 | case 1: | |
41 | syscall = mode1_syscalls; | |
5b101740 RM |
42 | #ifdef CONFIG_COMPAT |
43 | if (is_compat_task()) | |
1da177e4 LT |
44 | syscall = mode1_syscalls_32; |
45 | #endif | |
46 | do { | |
47 | if (*syscall == this_syscall) | |
48 | return; | |
49 | } while (*++syscall); | |
50 | break; | |
51 | default: | |
52 | BUG(); | |
53 | } | |
54 | ||
55 | #ifdef SECCOMP_DEBUG | |
56 | dump_stack(); | |
57 | #endif | |
85e7bac3 | 58 | audit_seccomp(this_syscall); |
1da177e4 LT |
59 | do_exit(SIGKILL); |
60 | } | |
1d9d02fe AA |
61 | |
62 | long prctl_get_seccomp(void) | |
63 | { | |
64 | return current->seccomp.mode; | |
65 | } | |
66 | ||
67 | long prctl_set_seccomp(unsigned long seccomp_mode) | |
68 | { | |
69 | long ret; | |
70 | ||
71 | /* can set it only once to be even more secure */ | |
72 | ret = -EPERM; | |
73 | if (unlikely(current->seccomp.mode)) | |
74 | goto out; | |
75 | ||
76 | ret = -EINVAL; | |
77 | if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) { | |
78 | current->seccomp.mode = seccomp_mode; | |
79 | set_thread_flag(TIF_SECCOMP); | |
cf99abac AA |
80 | #ifdef TIF_NOTSC |
81 | disable_TSC(); | |
82 | #endif | |
1d9d02fe AA |
83 | ret = 0; |
84 | } | |
85 | ||
86 | out: | |
87 | return ret; | |
88 | } |