diff options
author | netblue30 <netblue30@yahoo.com> | 2015-12-03 08:45:52 -0500 |
---|---|---|
committer | netblue30 <netblue30@yahoo.com> | 2015-12-03 08:45:52 -0500 |
commit | f9021ef8714fee5d4eb30a2329f80eeebaeaf244 (patch) | |
tree | dd8152456b311b5539f6a8d4fb1b2a092737c1bb /src/libtracelog/libtracelog.c | |
parent | testing (diff) | |
download | firejail-f9021ef8714fee5d4eb30a2329f80eeebaeaf244.tar.gz firejail-f9021ef8714fee5d4eb30a2329f80eeebaeaf244.tar.zst firejail-f9021ef8714fee5d4eb30a2329f80eeebaeaf244.zip |
--tracelog
Diffstat (limited to 'src/libtracelog/libtracelog.c')
-rw-r--r-- | src/libtracelog/libtracelog.c | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/src/libtracelog/libtracelog.c b/src/libtracelog/libtracelog.c new file mode 100644 index 000000000..c3bbc132b --- /dev/null +++ b/src/libtracelog/libtracelog.c | |||
@@ -0,0 +1,494 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014, 2015 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #define _GNU_SOURCE | ||
21 | #include <stdio.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | #include <dlfcn.h> | ||
25 | #include <sys/types.h> | ||
26 | #include <unistd.h> | ||
27 | #include <sys/socket.h> | ||
28 | #include <netinet/in.h> | ||
29 | #include <arpa/inet.h> | ||
30 | #include <sys/un.h> | ||
31 | #include <sys/stat.h> | ||
32 | #include <syslog.h> | ||
33 | #include <dirent.h> | ||
34 | |||
35 | |||
36 | |||
37 | // break recursivity on fopen call | ||
38 | typedef FILE *(*orig_fopen_t)(const char *pathname, const char *mode); | ||
39 | static orig_fopen_t orig_fopen = NULL; | ||
40 | typedef FILE *(*orig_fopen64_t)(const char *pathname, const char *mode); | ||
41 | static orig_fopen64_t orig_fopen64 = NULL; | ||
42 | |||
43 | // | ||
44 | // blacklist storage | ||
45 | // | ||
46 | typedef struct list_elem_t { | ||
47 | struct list_elem_t *next; | ||
48 | char *path; | ||
49 | } ListElem; | ||
50 | |||
51 | static ListElem *storage; | ||
52 | |||
53 | static storage_add(const char *str) { | ||
54 | ListElem *ptr = malloc(sizeof(ListElem)); | ||
55 | if (!ptr) { | ||
56 | fprintf(stderr, "Error: cannot allocate memory\n"); | ||
57 | return; | ||
58 | } | ||
59 | ptr->path = strdup(str); | ||
60 | if (!ptr->path) { | ||
61 | fprintf(stderr, "Error: cannot allocate memory\n"); | ||
62 | return; | ||
63 | } | ||
64 | ptr->next = storage; | ||
65 | storage = ptr; | ||
66 | } | ||
67 | |||
68 | static char *storage_find(const char *str) { | ||
69 | const char *tofind = str; | ||
70 | int allocated = 0; | ||
71 | |||
72 | if (strstr(str, "..") || strstr(str, "/./")) { | ||
73 | tofind = realpath(str, NULL); | ||
74 | allocated = 1; | ||
75 | } | ||
76 | |||
77 | ListElem *ptr = storage; | ||
78 | while (ptr) { | ||
79 | if (strcmp(tofind, ptr->path) == 0) { | ||
80 | if (allocated) | ||
81 | free((char *) tofind); | ||
82 | return ptr->path; | ||
83 | } | ||
84 | ptr = ptr->next; | ||
85 | } | ||
86 | |||
87 | if (allocated) | ||
88 | free((char *) tofind); | ||
89 | return NULL; | ||
90 | } | ||
91 | |||
92 | // | ||
93 | // load blacklistst form /run/firejail/mnt/fslogger | ||
94 | // | ||
95 | #define RUN_FSLOGGER_FILE "/run/firejail/mnt/fslogger" | ||
96 | #define MAXBUF 4096 | ||
97 | static int blacklist_loaded = 0; | ||
98 | static char *sandbox_pid_str = 0; | ||
99 | static char *sandbox_name_str = NULL; | ||
100 | void load_blacklist(void) { | ||
101 | if (blacklist_loaded) | ||
102 | return; | ||
103 | |||
104 | // open filesystem log | ||
105 | if (!orig_fopen) | ||
106 | orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen"); | ||
107 | FILE *fp = orig_fopen(RUN_FSLOGGER_FILE, "r"); | ||
108 | if (!fp) | ||
109 | return; | ||
110 | |||
111 | // extract blacklists | ||
112 | char buf[MAXBUF]; | ||
113 | int cnt = 0; | ||
114 | while (fgets(buf, MAXBUF, fp)) { | ||
115 | if (strncmp(buf, "sandbox pid: ", 13) == 0) { | ||
116 | char *ptr = strchr(buf, '\n'); | ||
117 | if (ptr) | ||
118 | *ptr = '\0'; | ||
119 | sandbox_pid_str = strdup(buf + 13); | ||
120 | } | ||
121 | else if (strncmp(buf, "sandbox name: ", 14) == 0) { | ||
122 | char *ptr = strchr(buf, '\n'); | ||
123 | if (ptr) | ||
124 | *ptr = '\0'; | ||
125 | sandbox_name_str = strdup(buf + 14); | ||
126 | } | ||
127 | else if (strncmp(buf, "blacklist ", 10) == 0) { | ||
128 | char *ptr = strchr(buf, '\n'); | ||
129 | if (ptr) | ||
130 | *ptr = '\0'; | ||
131 | storage_add(buf + 10); | ||
132 | cnt++; | ||
133 | } | ||
134 | } | ||
135 | fclose(fp); | ||
136 | blacklist_loaded = 1; | ||
137 | printf("Monitoring %d blacklists\n", cnt); | ||
138 | } | ||
139 | |||
140 | |||
141 | static void sendlog(const char *name, const char *call, const char *path) { | ||
142 | openlog ("firejail", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); | ||
143 | if (sandbox_pid_str && sandbox_name_str) | ||
144 | syslog (LOG_INFO, "blacklist violation - sandbox %s, name %s, exe %s, syscall %s, path %s", | ||
145 | sandbox_pid_str, sandbox_name_str, name, call, path); | ||
146 | else if (sandbox_pid_str) | ||
147 | syslog (LOG_INFO, "blacklist violation - sandbox %s, exe %s, syscall %s, path %s", | ||
148 | sandbox_pid_str, name, call, path); | ||
149 | else | ||
150 | syslog (LOG_INFO, "blacklist violation - exe %s, syscall %s, path %s", | ||
151 | name, call, path); | ||
152 | closelog (); | ||
153 | } | ||
154 | |||
155 | |||
156 | // | ||
157 | // pid | ||
158 | // | ||
159 | static pid_t mypid = 0; | ||
160 | static inline pid_t pid(void) { | ||
161 | if (!mypid) | ||
162 | mypid = getpid(); | ||
163 | return mypid; | ||
164 | } | ||
165 | |||
166 | // | ||
167 | // process name | ||
168 | // | ||
169 | #define MAXNAME 16 | ||
170 | static char myname[MAXNAME]; | ||
171 | static int nameinit = 0; | ||
172 | static char *name(void) { | ||
173 | if (!nameinit) { | ||
174 | |||
175 | // initialize the name of the process based on /proc/PID/comm | ||
176 | memset(myname, 0, MAXNAME); | ||
177 | |||
178 | pid_t p = pid(); | ||
179 | char *fname; | ||
180 | if (asprintf(&fname, "/proc/%u/comm", p) == -1) | ||
181 | return "unknown"; | ||
182 | |||
183 | // read file | ||
184 | if (!orig_fopen) | ||
185 | orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen"); | ||
186 | FILE *fp = orig_fopen(fname, "r"); | ||
187 | if (!fp) | ||
188 | return "unknown"; | ||
189 | if (fgets(myname, MAXNAME, fp) == NULL) { | ||
190 | fclose(fp); | ||
191 | free(fname); | ||
192 | return "unknown"; | ||
193 | } | ||
194 | |||
195 | // clean '\n' | ||
196 | char *ptr = strchr(myname, '\n'); | ||
197 | if (ptr) | ||
198 | *ptr = '\0'; | ||
199 | |||
200 | fclose(fp); | ||
201 | free(fname); | ||
202 | nameinit = 1; | ||
203 | } | ||
204 | |||
205 | return myname; | ||
206 | } | ||
207 | |||
208 | // | ||
209 | // syscalls | ||
210 | // | ||
211 | |||
212 | // open | ||
213 | typedef int (*orig_open_t)(const char *pathname, int flags, mode_t mode); | ||
214 | static orig_open_t orig_open = NULL; | ||
215 | int open(const char *pathname, int flags, mode_t mode) { | ||
216 | if (!orig_open) | ||
217 | orig_open = (orig_open_t)dlsym(RTLD_NEXT, "open"); | ||
218 | |||
219 | if (!storage) | ||
220 | load_blacklist(); | ||
221 | |||
222 | int rv = orig_open(pathname, flags, mode); | ||
223 | if (storage_find(pathname)) | ||
224 | sendlog(name(), __FUNCTION__, pathname); | ||
225 | return rv; | ||
226 | } | ||
227 | |||
228 | typedef int (*orig_open64_t)(const char *pathname, int flags, mode_t mode); | ||
229 | static orig_open64_t orig_open64 = NULL; | ||
230 | int open64(const char *pathname, int flags, mode_t mode) { | ||
231 | if (!orig_open64) | ||
232 | orig_open64 = (orig_open64_t)dlsym(RTLD_NEXT, "open64"); | ||
233 | if (!storage) | ||
234 | load_blacklist(); | ||
235 | |||
236 | int rv = orig_open64(pathname, flags, mode); | ||
237 | if (storage_find(pathname)) | ||
238 | sendlog(name(), __FUNCTION__, pathname); | ||
239 | return rv; | ||
240 | } | ||
241 | |||
242 | // openat | ||
243 | typedef int (*orig_openat_t)(int dirfd, const char *pathname, int flags, mode_t mode); | ||
244 | static orig_openat_t orig_openat = NULL; | ||
245 | int openat(int dirfd, const char *pathname, int flags, mode_t mode) { | ||
246 | if (!orig_openat) | ||
247 | orig_openat = (orig_openat_t)dlsym(RTLD_NEXT, "openat"); | ||
248 | if (!storage) | ||
249 | load_blacklist(); | ||
250 | |||
251 | int rv = orig_openat(dirfd, pathname, flags, mode); | ||
252 | if (storage_find(pathname)) | ||
253 | sendlog(name(), __FUNCTION__, pathname); | ||
254 | return rv; | ||
255 | } | ||
256 | |||
257 | typedef int (*orig_openat64_t)(int dirfd, const char *pathname, int flags, mode_t mode); | ||
258 | static orig_openat64_t orig_openat64 = NULL; | ||
259 | int openat64(int dirfd, const char *pathname, int flags, mode_t mode) { | ||
260 | if (!orig_openat64) | ||
261 | orig_openat64 = (orig_openat64_t)dlsym(RTLD_NEXT, "openat64"); | ||
262 | if (!storage) | ||
263 | load_blacklist(); | ||
264 | |||
265 | int rv = orig_openat64(dirfd, pathname, flags, mode); | ||
266 | if (storage_find(pathname)) | ||
267 | sendlog(name(), __FUNCTION__, pathname); | ||
268 | return rv; | ||
269 | } | ||
270 | |||
271 | |||
272 | // fopen | ||
273 | FILE *fopen(const char *pathname, const char *mode) { | ||
274 | if (!orig_fopen) | ||
275 | orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen"); | ||
276 | if (!storage) | ||
277 | load_blacklist(); | ||
278 | |||
279 | FILE *rv = orig_fopen(pathname, mode); | ||
280 | if (storage_find(pathname)) | ||
281 | sendlog(name(), __FUNCTION__, pathname); | ||
282 | return rv; | ||
283 | } | ||
284 | |||
285 | #ifdef __GLIBC__ | ||
286 | FILE *fopen64(const char *pathname, const char *mode) { | ||
287 | if (!orig_fopen64) | ||
288 | orig_fopen64 = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen64"); | ||
289 | if (!storage) | ||
290 | load_blacklist(); | ||
291 | |||
292 | FILE *rv = orig_fopen64(pathname, mode); | ||
293 | if (storage_find(pathname)) | ||
294 | sendlog(name(), __FUNCTION__, pathname); | ||
295 | return rv; | ||
296 | } | ||
297 | #endif /* __GLIBC__ */ | ||
298 | |||
299 | |||
300 | // freopen | ||
301 | typedef FILE *(*orig_freopen_t)(const char *pathname, const char *mode, FILE *stream); | ||
302 | static orig_freopen_t orig_freopen = NULL; | ||
303 | FILE *freopen(const char *pathname, const char *mode, FILE *stream) { | ||
304 | if (!orig_freopen) | ||
305 | orig_freopen = (orig_freopen_t)dlsym(RTLD_NEXT, "freopen"); | ||
306 | if (!storage) | ||
307 | load_blacklist(); | ||
308 | |||
309 | FILE *rv = orig_freopen(pathname, mode, stream); | ||
310 | if (storage_find(pathname)) | ||
311 | sendlog(name(), __FUNCTION__, pathname); | ||
312 | return rv; | ||
313 | } | ||
314 | |||
315 | #ifdef __GLIBC__ | ||
316 | typedef FILE *(*orig_freopen64_t)(const char *pathname, const char *mode, FILE *stream); | ||
317 | static orig_freopen64_t orig_freopen64 = NULL; | ||
318 | FILE *freopen64(const char *pathname, const char *mode, FILE *stream) { | ||
319 | if (!orig_freopen64) | ||
320 | orig_freopen64 = (orig_freopen64_t)dlsym(RTLD_NEXT, "freopen64"); | ||
321 | if (!storage) | ||
322 | load_blacklist(); | ||
323 | |||
324 | FILE *rv = orig_freopen64(pathname, mode, stream); | ||
325 | if (storage_find(pathname)) | ||
326 | sendlog(name(), __FUNCTION__, pathname); | ||
327 | return rv; | ||
328 | } | ||
329 | #endif /* __GLIBC__ */ | ||
330 | |||
331 | // unlink | ||
332 | typedef int (*orig_unlink_t)(const char *pathname); | ||
333 | static orig_unlink_t orig_unlink = NULL; | ||
334 | int unlink(const char *pathname) { | ||
335 | if (!orig_unlink) | ||
336 | orig_unlink = (orig_unlink_t)dlsym(RTLD_NEXT, "unlink"); | ||
337 | if (!storage) | ||
338 | load_blacklist(); | ||
339 | |||
340 | int rv = orig_unlink(pathname); | ||
341 | if (storage_find(pathname)) | ||
342 | sendlog(name(), __FUNCTION__, pathname); | ||
343 | return rv; | ||
344 | } | ||
345 | |||
346 | typedef int (*orig_unlinkat_t)(int dirfd, const char *pathname, int flags); | ||
347 | static orig_unlinkat_t orig_unlinkat = NULL; | ||
348 | int unlinkat(int dirfd, const char *pathname, int flags) { | ||
349 | if (!orig_unlinkat) | ||
350 | orig_unlinkat = (orig_unlinkat_t)dlsym(RTLD_NEXT, "unlinkat"); | ||
351 | if (!storage) | ||
352 | load_blacklist(); | ||
353 | |||
354 | int rv = orig_unlinkat(dirfd, pathname, flags); | ||
355 | if (storage_find(pathname)) | ||
356 | sendlog(name(), __FUNCTION__, pathname); | ||
357 | return rv; | ||
358 | } | ||
359 | |||
360 | // mkdir/mkdirat/rmdir | ||
361 | typedef int (*orig_mkdir_t)(const char *pathname, mode_t mode); | ||
362 | static orig_mkdir_t orig_mkdir = NULL; | ||
363 | int mkdir(const char *pathname, mode_t mode) { | ||
364 | if (!orig_mkdir) | ||
365 | orig_mkdir = (orig_mkdir_t)dlsym(RTLD_NEXT, "mkdir"); | ||
366 | if (!storage) | ||
367 | load_blacklist(); | ||
368 | |||
369 | int rv = orig_mkdir(pathname, mode); | ||
370 | if (storage_find(pathname)) | ||
371 | sendlog(name(), __FUNCTION__, pathname); | ||
372 | return rv; | ||
373 | } | ||
374 | |||
375 | typedef int (*orig_mkdirat_t)(int dirfd, const char *pathname, mode_t mode); | ||
376 | static orig_mkdirat_t orig_mkdirat = NULL; | ||
377 | int mkdirat(int dirfd, const char *pathname, mode_t mode) { | ||
378 | if (!orig_mkdirat) | ||
379 | orig_mkdirat = (orig_mkdirat_t)dlsym(RTLD_NEXT, "mkdirat"); | ||
380 | if (!storage) | ||
381 | load_blacklist(); | ||
382 | |||
383 | int rv = orig_mkdirat(dirfd, pathname, mode); | ||
384 | if (storage_find(pathname)) | ||
385 | sendlog(name(), __FUNCTION__, pathname); | ||
386 | return rv; | ||
387 | } | ||
388 | |||
389 | typedef int (*orig_rmdir_t)(const char *pathname); | ||
390 | static orig_rmdir_t orig_rmdir = NULL; | ||
391 | int rmdir(const char *pathname) { | ||
392 | if (!orig_rmdir) | ||
393 | orig_rmdir = (orig_rmdir_t)dlsym(RTLD_NEXT, "rmdir"); | ||
394 | if (!storage) | ||
395 | load_blacklist(); | ||
396 | |||
397 | int rv = orig_rmdir(pathname); | ||
398 | if (storage_find(pathname)) | ||
399 | sendlog(name(), __FUNCTION__, pathname); | ||
400 | return rv; | ||
401 | } | ||
402 | |||
403 | // stat | ||
404 | typedef int (*orig_stat_t)(const char *pathname, struct stat *buf); | ||
405 | static orig_stat_t orig_stat = NULL; | ||
406 | int stat(const char *pathname, struct stat *buf) { | ||
407 | if (!orig_stat) | ||
408 | orig_stat = (orig_stat_t)dlsym(RTLD_NEXT, "stat"); | ||
409 | if (!storage) | ||
410 | load_blacklist(); | ||
411 | |||
412 | int rv = orig_stat(pathname, buf); | ||
413 | if (storage_find(pathname)) | ||
414 | sendlog(name(), __FUNCTION__, pathname); | ||
415 | return rv; | ||
416 | } | ||
417 | |||
418 | #ifdef __GLIBC__ | ||
419 | typedef int (*orig_stat64_t)(const char *pathname, struct stat64 *buf); | ||
420 | static orig_stat64_t orig_stat64 = NULL; | ||
421 | int stat64(const char *pathname, struct stat64 *buf) { | ||
422 | if (!orig_stat) | ||
423 | orig_stat64 = (orig_stat64_t)dlsym(RTLD_NEXT, "stat64"); | ||
424 | if (!storage) | ||
425 | load_blacklist(); | ||
426 | |||
427 | int rv = orig_stat64(pathname, buf); | ||
428 | if (storage_find(pathname)) | ||
429 | sendlog(name(), __FUNCTION__, pathname); | ||
430 | return rv; | ||
431 | } | ||
432 | #endif /* __GLIBC__ */ | ||
433 | |||
434 | typedef int (*orig_lstat_t)(const char *pathname, struct stat *buf); | ||
435 | static orig_lstat_t orig_lstat = NULL; | ||
436 | int lstat(const char *pathname, struct stat *buf) { | ||
437 | if (!orig_lstat) | ||
438 | orig_lstat = (orig_lstat_t)dlsym(RTLD_NEXT, "lstat"); | ||
439 | if (!storage) | ||
440 | load_blacklist(); | ||
441 | |||
442 | int rv = orig_lstat(pathname, buf); | ||
443 | if (storage_find(pathname)) | ||
444 | sendlog(name(), __FUNCTION__, pathname); | ||
445 | return rv; | ||
446 | } | ||
447 | |||
448 | #ifdef __GLIBC__ | ||
449 | typedef int (*orig_lstat64_t)(const char *pathname, struct stat64 *buf); | ||
450 | static orig_lstat64_t orig_lstat64 = NULL; | ||
451 | int lstat64(const char *pathname, struct stat64 *buf) { | ||
452 | if (!orig_lstat) | ||
453 | orig_lstat64 = (orig_lstat64_t)dlsym(RTLD_NEXT, "lstat64"); | ||
454 | if (!storage) | ||
455 | load_blacklist(); | ||
456 | |||
457 | int rv = orig_lstat64(pathname, buf); | ||
458 | if (storage_find(pathname)) | ||
459 | sendlog(name(), __FUNCTION__, pathname); | ||
460 | return rv; | ||
461 | } | ||
462 | #endif /* __GLIBC__ */ | ||
463 | |||
464 | // access | ||
465 | typedef int (*orig_access_t)(const char *pathname, int mode); | ||
466 | static orig_access_t orig_access = NULL; | ||
467 | int access(const char *pathname, int mode) { | ||
468 | if (!orig_access) | ||
469 | orig_access = (orig_access_t)dlsym(RTLD_NEXT, "access"); | ||
470 | if (!storage) | ||
471 | load_blacklist(); | ||
472 | |||
473 | int rv = orig_access(pathname, mode); | ||
474 | if (storage_find(pathname)) | ||
475 | sendlog(name(), __FUNCTION__, pathname); | ||
476 | return rv; | ||
477 | } | ||
478 | |||
479 | // opendir | ||
480 | typedef DIR *(*orig_opendir_t)(const char *pathname); | ||
481 | static orig_opendir_t orig_opendir = NULL; | ||
482 | DIR *opendir(const char *pathname) { | ||
483 | if (!orig_opendir) | ||
484 | orig_opendir = (orig_opendir_t)dlsym(RTLD_NEXT, "opendir"); | ||
485 | if (!storage) | ||
486 | load_blacklist(); | ||
487 | |||
488 | DIR *rv = orig_opendir(pathname); | ||
489 | if (storage_find(pathname)) | ||
490 | sendlog(name(), __FUNCTION__, pathname); | ||
491 | return rv; | ||
492 | } | ||
493 | |||
494 | |||