diff options
Diffstat (limited to 'src/fseccomp/seccomp_secondary.c')
-rw-r--r-- | src/fseccomp/seccomp_secondary.c | 97 |
1 files changed, 64 insertions, 33 deletions
diff --git a/src/fseccomp/seccomp_secondary.c b/src/fseccomp/seccomp_secondary.c index fceb2c3ec..dd69b58cc 100644 --- a/src/fseccomp/seccomp_secondary.c +++ b/src/fseccomp/seccomp_secondary.c | |||
@@ -19,8 +19,29 @@ | |||
19 | */ | 19 | */ |
20 | #include "fseccomp.h" | 20 | #include "fseccomp.h" |
21 | #include "../include/seccomp.h" | 21 | #include "../include/seccomp.h" |
22 | #include <sys/personality.h> | ||
22 | #include <sys/syscall.h> | 23 | #include <sys/syscall.h> |
23 | 24 | ||
25 | static void write_filter(const char *fname, size_t size, const void *filter) { | ||
26 | // save filter to file | ||
27 | int dst = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | ||
28 | if (dst < 0) { | ||
29 | fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname); | ||
30 | exit(1); | ||
31 | } | ||
32 | |||
33 | size_t written = 0; | ||
34 | while (written < size) { | ||
35 | ssize_t rv = write(dst, (unsigned char *) filter + written, size - written); | ||
36 | if (rv == -1) { | ||
37 | fprintf(stderr, "Error fseccomp: cannot write %s file\n", fname); | ||
38 | exit(1); | ||
39 | } | ||
40 | written += rv; | ||
41 | } | ||
42 | close(dst); | ||
43 | } | ||
44 | |||
24 | void seccomp_secondary_64(const char *fname) { | 45 | void seccomp_secondary_64(const char *fname) { |
25 | // hardcoded syscall values | 46 | // hardcoded syscall values |
26 | struct sock_filter filter[] = { | 47 | struct sock_filter filter[] = { |
@@ -84,23 +105,7 @@ void seccomp_secondary_64(const char *fname) { | |||
84 | }; | 105 | }; |
85 | 106 | ||
86 | // save filter to file | 107 | // save filter to file |
87 | int dst = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | 108 | write_filter(fname, sizeof(filter), filter); |
88 | if (dst < 0) { | ||
89 | fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname); | ||
90 | exit(1); | ||
91 | } | ||
92 | |||
93 | int size = (int) sizeof(filter); | ||
94 | int written = 0; | ||
95 | while (written < size) { | ||
96 | int rv = write(dst, (unsigned char *) filter + written, size - written); | ||
97 | if (rv == -1) { | ||
98 | fprintf(stderr, "Error fseccomp: cannot write %s file\n", fname); | ||
99 | exit(1); | ||
100 | } | ||
101 | written += rv; | ||
102 | } | ||
103 | close(dst); | ||
104 | } | 109 | } |
105 | 110 | ||
106 | // i386 filter installed on amd64 architectures | 111 | // i386 filter installed on amd64 architectures |
@@ -166,21 +171,47 @@ void seccomp_secondary_32(const char *fname) { | |||
166 | }; | 171 | }; |
167 | 172 | ||
168 | // save filter to file | 173 | // save filter to file |
169 | int dst = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | 174 | write_filter(fname, sizeof(filter), filter); |
170 | if (dst < 0) { | 175 | } |
171 | fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname); | ||
172 | exit(1); | ||
173 | } | ||
174 | 176 | ||
175 | int size = (int) sizeof(filter); | 177 | #define jmp_from_to(from_addr, to_addr) ((to_addr) - (from_addr) - 1) |
176 | int written = 0; | 178 | |
177 | while (written < size) { | 179 | #if __BYTE_ORDER == __BIG_ENDIAN |
178 | int rv = write(dst, (unsigned char *) filter + written, size - written); | 180 | #define MSW 0 |
179 | if (rv == -1) { | 181 | #define LSW (sizeof(int)) |
180 | fprintf(stderr, "Error fseccomp: cannot write %s file\n", fname); | 182 | #else |
181 | exit(1); | 183 | #define MSW (sizeof(int)) |
182 | } | 184 | #define LSW 0 |
183 | written += rv; | 185 | #endif |
184 | } | 186 | |
185 | close(dst); | 187 | void seccomp_secondary_block(const char *fname) { |
188 | struct sock_filter filter[] = { | ||
189 | // block other architectures | ||
190 | VALIDATE_ARCHITECTURE_KILL, | ||
191 | EXAMINE_SYSCALL, | ||
192 | #if defined(__x86_64__) | ||
193 | // block x32 | ||
194 | HANDLE_X32_KILL, | ||
195 | #endif | ||
196 | // block personality(2) where domain != PER_LINUX or 0xffffffff (query current personality) | ||
197 | // 0: if personality(2), continue to 1, else goto 7 (allow) | ||
198 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYS_personality, 0, jmp_from_to(0, 7)), | ||
199 | // 1: get LSW of system call argument 0 | ||
200 | BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, args[0])) + LSW), | ||
201 | // 2: if LSW(arg0) == PER_LINUX, goto step 4, else continue to 3 | ||
202 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, PER_LINUX, jmp_from_to(2, 4), 0), | ||
203 | // 3: if LSW(arg0) == 0xffffffff, continue to 4, else goto 6 (kill) | ||
204 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0xffffffff, 0, jmp_from_to(3, 6)), | ||
205 | // 4: get MSW of system call argument 0 | ||
206 | BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, args[0])) + MSW), | ||
207 | // 5: if MSW(arg0) == 0, goto 7 (allow) else continue to 6 (kill) | ||
208 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, jmp_from_to(5, 7), 0), | ||
209 | // 6: | ||
210 | KILL_PROCESS, | ||
211 | // 7: | ||
212 | RETURN_ALLOW | ||
213 | }; | ||
214 | |||
215 | // save filter to file | ||
216 | write_filter(fname, sizeof(filter), filter); | ||
186 | } | 217 | } |