1 /*
2 * seccomp.c - seccomp utility functions
3 * Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "config.h"
9
10 #include <asm/unistd.h>
11 #include <elf.h>
12 #include <errno.h>
13 #include <sys/prctl.h>
14 #include <stddef.h>
15 #include <stdint.h>
16 #include <stdlib.h>
17 #include <sys/syscall.h>
18 #include <unistd.h>
19
20 #include <linux/audit.h>
21 #include <linux/filter.h>
22
23 #include "src/seccomp.h"
24
25 /* Linux seccomp_filter sandbox */
26 #define SECCOMP_FILTER_FAIL SECCOMP_RET_KILL
27
28 /* Use a signal handler to emit violations when debugging */
29 #ifdef SECCOMP_FILTER_DEBUG
30 # undef SECCOMP_FILTER_FAIL
31 # define SECCOMP_FILTER_FAIL SECCOMP_RET_TRAP
32 #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */
33
34 /* Simple helpers to avoid manual errors (but larger BPF programs). */
35 #define SC_DENY(_nr, _errno) \
36 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \
37 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno))
38 #define SC_ALLOW(_nr) \
39 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \
40 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
41
42 #if defined(__i386__)
43 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386
44 #elif defined(__x86_64__)
45 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64
46 #elif defined(__arm__)
47 # ifndef EM_ARM
48 # define EM_ARM 40
49 # endif
50 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM
51 #elif defined(__aarch64__)
52 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64
53 #elif defined(__mips__)
54 # if defined(__MIPSEL__)
55 # if defined(__LP64__)
56 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL64
57 # else
58 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL
59 # endif
60 # elif defined(__LP64__)
61 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS64
62 # else
63 # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS
64 # endif
65 #else
66 # error "Platform does not support seccomp filter yet"
67 #endif
68
69 /* Returns 0 if the the sandbox is enabled using
70 * the time setter policy.
71 */
72 int
enable_setter_seccomp(void)73 enable_setter_seccomp (void)
74 {
75 static const struct sock_filter insns[] =
76 {
77 /* Ensure the syscall arch convention is as expected. */
78 BPF_STMT (BPF_LD+BPF_W+BPF_ABS,
79 offsetof (struct seccomp_data, arch)),
80 BPF_JUMP (BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_AUDIT_ARCH, 1, 0),
81 BPF_STMT (BPF_RET+BPF_K, SECCOMP_FILTER_FAIL),
82 /* Load the syscall number for checking. */
83 BPF_STMT (BPF_LD+BPF_W+BPF_ABS,
84 offsetof (struct seccomp_data, nr)),
85
86 /* Process ALLOWs as quickly as possible */
87 SC_ALLOW (read),
88 SC_ALLOW (write),
89 SC_ALLOW (pwrite64),
90
91 SC_ALLOW (settimeofday),
92 SC_ALLOW (ioctl), /* TODO(wad) filter for fd and RTC_SET_TIME */
93 #ifdef __NR_time /* This is required for x86 systems */
94 SC_ALLOW (time),
95 #endif
96
97 #ifdef __NR_lseek
98 SC_ALLOW (lseek),
99 #endif
100 #ifdef __NR_llseek
101 SC_ALLOW (llseek),
102 #endif
103 #ifdef __NR_lseek64
104 SC_ALLOW (lseek64),
105 #endif
106 SC_ALLOW (close),
107 SC_ALLOW (munmap),
108
109 SC_ALLOW (exit_group),
110 SC_ALLOW (exit),
111
112 #ifdef __NR_open
113 SC_DENY (open, EINVAL),
114 #endif
115 #ifdef __NR_openat
116 SC_DENY (openat, EINVAL),
117 #endif
118 SC_DENY (fcntl, EINVAL),
119 #ifdef __NR_fstat
120 SC_DENY (fstat, EINVAL),
121 #endif
122 #ifdef __NR_fstatat
123 SC_DENY (fstatat, EINVAL),
124 #endif
125 #ifdef __NR_newfstatat
126 SC_DENY (newfstatat, EINVAL),
127 #endif
128 #ifdef __NR_mmap
129 SC_DENY (mmap, EINVAL),
130 #endif
131 #ifdef __NR_mmap2
132 SC_DENY (mmap2, EINVAL),
133 #endif
134 #ifdef __NR_sendto
135 SC_DENY (sendto, EINVAL),
136 #endif
137 #ifdef __NR_socket
138 SC_DENY (socket, EINVAL),
139 #endif
140 #ifdef __NR_socketcall
141 SC_DENY (socketcall, EINVAL),
142 #endif
143 BPF_STMT (BPF_RET+BPF_K, SECCOMP_FILTER_FAIL),
144 };
145 static const struct sock_fprog prog =
146 {
147 .len = (unsigned short) (sizeof (insns) /sizeof (insns[0])),
148 .filter = (struct sock_filter *) insns,
149 };
150 return (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
151 prctl (PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog));
152 }
153