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