Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

move seccomp from /proc to a prctl

This reduces the memory footprint and it enforces that only the current
task can enable seccomp on itself (this is a requirement for a
strightforward [modulo preempt ;) ] TIF_NOTSC implementation).

Signed-off-by: Andrea Arcangeli <andrea@cpushare.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Andrea Arcangeli and committed by
Linus Torvalds
1d9d02fe be0ef957

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