aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/base.c72
-rw-r--r--include/linux/prctl.h4
-rw-r--r--include/linux/seccomp.h15
-rw-r--r--kernel/seccomp.c26
-rw-r--r--kernel/sys.c8
5 files changed, 51 insertions, 74 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index d0921944e68c..ae3627337a92 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -67,7 +67,6 @@
67#include <linux/mount.h> 67#include <linux/mount.h>
68#include <linux/security.h> 68#include <linux/security.h>
69#include <linux/ptrace.h> 69#include <linux/ptrace.h>
70#include <linux/seccomp.h>
71#include <linux/cpuset.h> 70#include <linux/cpuset.h>
72#include <linux/audit.h> 71#include <linux/audit.h>
73#include <linux/poll.h> 72#include <linux/poll.h>
@@ -817,71 +816,6 @@ static const struct file_operations proc_loginuid_operations = {
817}; 816};
818#endif 817#endif
819 818
820#ifdef CONFIG_SECCOMP
821static ssize_t seccomp_read(struct file *file, char __user *buf,
822 size_t count, loff_t *ppos)
823{
824 struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
825 char __buf[20];
826 size_t len;
827
828 if (!tsk)
829 return -ESRCH;
830 /* no need to print the trailing zero, so use only len */
831 len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
832 put_task_struct(tsk);
833
834 return simple_read_from_buffer(buf, count, ppos, __buf, len);
835}
836
837static ssize_t seccomp_write(struct file *file, const char __user *buf,
838 size_t count, loff_t *ppos)
839{
840 struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
841 char __buf[20], *end;
842 unsigned int seccomp_mode;
843 ssize_t result;
844
845 result = -ESRCH;
846 if (!tsk)
847 goto out_no_task;
848
849 /* can set it only once to be even more secure */
850 result = -EPERM;
851 if (unlikely(tsk->seccomp.mode))
852 goto out;
853
854 result = -EFAULT;
855 memset(__buf, 0, sizeof(__buf));
856 count = min(count, sizeof(__buf) - 1);
857 if (copy_from_user(__buf, buf, count))
858 goto out;
859
860 seccomp_mode = simple_strtoul(__buf, &end, 0);
861 if (*end == '\n')
862 end++;
863 result = -EINVAL;
864 if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
865 tsk->seccomp.mode = seccomp_mode;
866 set_tsk_thread_flag(tsk, TIF_SECCOMP);
867 } else
868 goto out;
869 result = -EIO;
870 if (unlikely(!(end - __buf)))
871 goto out;
872 result = end - __buf;
873out:
874 put_task_struct(tsk);
875out_no_task:
876 return result;
877}
878
879static const struct file_operations proc_seccomp_operations = {
880 .read = seccomp_read,
881 .write = seccomp_write,
882};
883#endif /* CONFIG_SECCOMP */
884
885#ifdef CONFIG_FAULT_INJECTION 819#ifdef CONFIG_FAULT_INJECTION
886static ssize_t proc_fault_inject_read(struct file * file, char __user * buf, 820static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
887 size_t count, loff_t *ppos) 821 size_t count, loff_t *ppos)
@@ -2042,9 +1976,6 @@ static const struct pid_entry tgid_base_stuff[] = {
2042 REG("numa_maps", S_IRUGO, numa_maps), 1976 REG("numa_maps", S_IRUGO, numa_maps),
2043#endif 1977#endif
2044 REG("mem", S_IRUSR|S_IWUSR, mem), 1978 REG("mem", S_IRUSR|S_IWUSR, mem),
2045#ifdef CONFIG_SECCOMP
2046 REG("seccomp", S_IRUSR|S_IWUSR, seccomp),
2047#endif
2048 LNK("cwd", cwd), 1979 LNK("cwd", cwd),
2049 LNK("root", root), 1980 LNK("root", root),
2050 LNK("exe", exe), 1981 LNK("exe", exe),
@@ -2329,9 +2260,6 @@ static const struct pid_entry tid_base_stuff[] = {
2329 REG("numa_maps", S_IRUGO, numa_maps), 2260 REG("numa_maps", S_IRUGO, numa_maps),
2330#endif 2261#endif
2331 REG("mem", S_IRUSR|S_IWUSR, mem), 2262 REG("mem", S_IRUSR|S_IWUSR, mem),
2332#ifdef CONFIG_SECCOMP
2333 REG("seccomp", S_IRUSR|S_IWUSR, seccomp),
2334#endif
2335 LNK("cwd", cwd), 2263 LNK("cwd", cwd),
2336 LNK("root", root), 2264 LNK("root", root),
2337 LNK("exe", exe), 2265 LNK("exe", exe),
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index 52a9be41250d..e2eff9079fe9 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -59,4 +59,8 @@
59# define PR_ENDIAN_LITTLE 1 /* True little endian mode */ 59# define PR_ENDIAN_LITTLE 1 /* True little endian mode */
60# define PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */ 60# define PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */
61 61
62/* Get/set process seccomp mode */
63#define PR_GET_SECCOMP 21
64#define PR_SET_SECCOMP 22
65
62#endif /* _LINUX_PRCTL_H */ 66#endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 3e8b1cf54303..d708974dbfe3 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -4,8 +4,6 @@
4 4
5#ifdef CONFIG_SECCOMP 5#ifdef CONFIG_SECCOMP
6 6
7#define NR_SECCOMP_MODES 1
8
9#include <linux/thread_info.h> 7#include <linux/thread_info.h>
10#include <asm/seccomp.h> 8#include <asm/seccomp.h>
11 9
@@ -23,6 +21,9 @@ static inline int has_secure_computing(struct thread_info *ti)
23 return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP)); 21 return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP));
24} 22}
25 23
24extern long prctl_get_seccomp(void);
25extern long prctl_set_seccomp(unsigned long);
26
26#else /* CONFIG_SECCOMP */ 27#else /* CONFIG_SECCOMP */
27 28
28typedef struct { } seccomp_t; 29typedef struct { } seccomp_t;
@@ -34,6 +35,16 @@ static inline int has_secure_computing(struct thread_info *ti)
34 return 0; 35 return 0;
35} 36}
36 37
38static inline long prctl_get_seccomp(void)
39{
40 return -EINVAL;
41}
42
43static inline long prctl_set_seccomp(unsigned long arg2)
44{
45 return -EINVAL;
46}
47
37#endif /* CONFIG_SECCOMP */ 48#endif /* CONFIG_SECCOMP */
38 49
39#endif /* _LINUX_SECCOMP_H */ 50#endif /* _LINUX_SECCOMP_H */
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index c3391b6020e8..1dfa8a509726 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -10,6 +10,7 @@
10#include <linux/sched.h> 10#include <linux/sched.h>
11 11
12/* #define SECCOMP_DEBUG 1 */ 12/* #define SECCOMP_DEBUG 1 */
13#define NR_SECCOMP_MODES 1
13 14
14/* 15/*
15 * Secure computing mode 1 allows only read/write/exit/sigreturn. 16 * Secure computing mode 1 allows only read/write/exit/sigreturn.
@@ -54,3 +55,28 @@ void __secure_computing(int this_syscall)
54#endif 55#endif
55 do_exit(SIGKILL); 56 do_exit(SIGKILL);
56} 57}
58
59long prctl_get_seccomp(void)
60{
61 return current->seccomp.mode;
62}
63
64long prctl_set_seccomp(unsigned long seccomp_mode)
65{
66 long ret;
67
68 /* can set it only once to be even more secure */
69 ret = -EPERM;
70 if (unlikely(current->seccomp.mode))
71 goto out;
72
73 ret = -EINVAL;
74 if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
75 current->seccomp.mode = seccomp_mode;
76 set_thread_flag(TIF_SECCOMP);
77 ret = 0;
78 }
79
80 out:
81 return ret;
82}
diff --git a/kernel/sys.c b/kernel/sys.c
index ed92e2f03342..4d141ae3e802 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -31,6 +31,7 @@
31#include <linux/cn_proc.h> 31#include <linux/cn_proc.h>
32#include <linux/getcpu.h> 32#include <linux/getcpu.h>
33#include <linux/task_io_accounting_ops.h> 33#include <linux/task_io_accounting_ops.h>
34#include <linux/seccomp.h>
34 35
35#include <linux/compat.h> 36#include <linux/compat.h>
36#include <linux/syscalls.h> 37#include <linux/syscalls.h>
@@ -2242,6 +2243,13 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
2242 error = SET_ENDIAN(current, arg2); 2243 error = SET_ENDIAN(current, arg2);
2243 break; 2244 break;
2244 2245
2246 case PR_GET_SECCOMP:
2247 error = prctl_get_seccomp();
2248 break;
2249 case PR_SET_SECCOMP:
2250 error = prctl_set_seccomp(arg2);
2251 break;
2252
2245 default: 2253 default:
2246 error = -EINVAL; 2254 error = -EINVAL;
2247 break; 2255 break;