/[path-sandbox]/trunk/libsandbox.c
Gentoo

Contents of /trunk/libsandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 122 - (show annotations) (download) (as text)
Tue Jun 14 21:59:07 2005 UTC (9 years, 4 months ago) by azarah
File MIME type: text/x-csrc
File size: 39958 byte(s)
Label rename for clarity.
1 /*
2 * Path sandbox for the gentoo linux portage package system, initially
3 * based on the ROCK Linux Wrapper for getting a list of created files
4 *
5 * to integrate with bash, bash should have been built like this
6 *
7 * ./configure --prefix=<prefix> --host=<host> --without-gnu-malloc
8 *
9 * it's very important that the --enable-static-link option is NOT specified
10 *
11 * Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
12 * Distributed under the terms of the GNU General Public License, v2 or later
13 * Author : Geert Bevin <gbevin@uwyn.com>
14 *
15 * Post Bevin leaving Gentoo ranks:
16 * --------------------------------
17 * Ripped out all the wrappers, and implemented those of InstallWatch.
18 * Losts of cleanups and bugfixes. Implement a execve that forces $LIBSANDBOX
19 * in $LD_PRELOAD. Reformat the whole thing to look somewhat like the reworked
20 * sandbox.c from Brad House <brad@mainstreetsoftworks.com>.
21 *
22 * Martin Schlemmer <azarah@gentoo.org> (18 Aug 2002)
23 *
24 * Partly Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro <p@demauro.net>,
25 * as some of the InstallWatch code was used.
26 *
27 *
28 * $Header$
29 *
30 */
31
32 /* Uncomment below to enable wrapping of mknod().
33 * This is broken currently. */
34 /* #define WRAP_MKNOD 1 */
35
36 /* Uncomment below to enable the use of strtok_r(). */
37 #define REENTRANT_STRTOK 1
38
39 /* Uncomment below to enable memory debugging. */
40 /* #define SB_MEM_DEBUG 1 */
41
42 #define open xxx_open
43 #define open64 xxx_open64
44
45 /* Wrapping mknod, do not have any effect, and
46 * wrapping __xmknod causes calls to it to segfault
47 */
48 #ifdef WRAP_MKNOD
49 # define __xmknod xxx___xmknod
50 #endif
51
52 #include <dirent.h>
53 #include <dlfcn.h>
54 #include <errno.h>
55 #include <fcntl.h>
56 #include <libgen.h>
57 #include <stdarg.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <sys/file.h>
62 #include <sys/stat.h>
63 #include <sys/types.h>
64 #include <sys/param.h>
65 #include <unistd.h>
66 #include <utime.h>
67 #include "config.h"
68 #include "localdecls.h"
69 #include "symbols.h"
70
71 #ifdef SB_MEM_DEBUG
72 # include <mcheck.h>
73 #endif
74
75 #ifdef WRAP_MKNOD
76 # undef __xmknod
77 #endif
78
79 #undef open
80 #undef open64
81
82 //#include "localdecls.h"
83 #include "sandbox.h"
84
85 /* Macros to check if a function should be executed */
86 #define FUNCTION_SANDBOX_SAFE(func, path) \
87 ((0 == is_sandbox_on()) || (1 == before_syscall(func, path)))
88
89 #define FUNCTION_SANDBOX_SAFE_ACCESS(func, path, flags) \
90 ((0 == is_sandbox_on()) || (1 == before_syscall_access(func, path, flags)))
91
92 #define FUNCTION_SANDBOX_SAFE_OPEN_INT(func, path, flags) \
93 ((0 == is_sandbox_on()) || (1 == before_syscall_open_int(func, path, flags)))
94
95 #define FUNCTION_SANDBOX_SAFE_OPEN_CHAR(func, path, mode) \
96 ((0 == is_sandbox_on()) || (1 == before_syscall_open_char(func, path, mode)))
97
98 /* Macro to check if a wrapper is defined, if not
99 * then try to resolve it again. */
100 #define check_dlsym(name) \
101 { \
102 int old_errno=errno; \
103 if (!true_ ## name) \
104 true_ ## name = get_dlsym(symname_ ## name, symver_ ## name); \
105 errno=old_errno; \
106 }
107
108 static char sandbox_lib[SB_PATH_MAX];
109 //static char sandbox_pids_file[255];
110 static char *sandbox_pids_file;
111
112 typedef struct {
113 int show_access_violation;
114 char **deny_prefixes;
115 int num_deny_prefixes;
116 char **read_prefixes;
117 int num_read_prefixes;
118 char **write_prefixes;
119 int num_write_prefixes;
120 char **predict_prefixes;
121 int num_predict_prefixes;
122 char **write_denied_prefixes;
123 int num_write_denied_prefixes;
124 } sbcontext_t;
125
126 static sbcontext_t sbcontext;
127 static char **cached_env_vars;
128 static int sb_init = 0;
129 static int sb_path_size_warning = 0;
130
131 void __attribute__ ((constructor)) libsb_init(void);
132 void __attribute__ ((destructor)) libsb_fini(void);
133
134 /* glibc modified realpath() functions */
135 static char *erealpath(const char *, char *);
136 /* glibc modified getcwd() functions */
137 static char *egetcwd(char *, size_t);
138
139 static void init_wrappers(void);
140 static void *get_dlsym(const char *, const char *);
141 static int canonicalize(const char *, char *);
142 static char *filter_path(const char *, int);
143 static int check_access(sbcontext_t *, const char *, const char *, const char *);
144 static int check_syscall(sbcontext_t *, const char *, const char *);
145 static int before_syscall(const char *, const char *);
146 static int before_syscall_access(const char *, const char *, int);
147 static int before_syscall_open_int(const char *, const char *, int);
148 static int before_syscall_open_char(const char *, const char *, const char *);
149 static void clean_env_entries(char ***, int *);
150 static void init_context(sbcontext_t *);
151 static void init_env_entries(char ***, int *, const char *, const char *, int);
152 static int is_sandbox_on();
153 static int is_sandbox_pid();
154
155 /* Wrapped functions */
156
157 extern int chmod(const char *, mode_t);
158 static int (*true_chmod) (const char *, mode_t) = NULL;
159 extern int chown(const char *, uid_t, gid_t);
160 static int (*true_chown) (const char *, uid_t, gid_t) = NULL;
161 extern int creat(const char *, mode_t);
162 static int (*true_creat) (const char *, mode_t) = NULL;
163 extern FILE *fopen(const char *, const char *);
164 static FILE *(*true_fopen) (const char *, const char *) = NULL;
165 extern int lchown(const char *, uid_t, gid_t);
166 static int (*true_lchown) (const char *, uid_t, gid_t) = NULL;
167 extern int link(const char *, const char *);
168 static int (*true_link) (const char *, const char *) = NULL;
169 extern int mkdir(const char *, mode_t);
170 static int (*true_mkdir) (const char *, mode_t) = NULL;
171 extern DIR *opendir(const char *);
172 static DIR *(*true_opendir) (const char *) = NULL;
173 #ifdef WRAP_MKNOD
174 extern int __xmknod(const char *, mode_t, dev_t);
175 static int (*true___xmknod) (const char *, mode_t, dev_t) = NULL;
176 #endif
177 extern int access(const char *, int);
178 static int (*true_access) (const char *, int) = NULL;
179 extern int open(const char *, int, ...);
180 static int (*true_open) (const char *, int, ...) = NULL;
181 extern int rename(const char *, const char *);
182 static int (*true_rename) (const char *, const char *) = NULL;
183 extern int rmdir(const char *);
184 static int (*true_rmdir) (const char *) = NULL;
185 extern int symlink(const char *, const char *);
186 static int (*true_symlink) (const char *, const char *) = NULL;
187 extern int truncate(const char *, TRUNCATE_T);
188 static int (*true_truncate) (const char *, TRUNCATE_T) = NULL;
189 extern int unlink(const char *);
190 static int (*true_unlink) (const char *) = NULL;
191
192 #if (GLIBC_MINOR >= 1)
193
194 extern int creat64(const char *, __mode_t);
195 static int (*true_creat64) (const char *, __mode_t) = NULL;
196 extern FILE *fopen64(const char *, const char *);
197 static FILE *(*true_fopen64) (const char *, const char *) = NULL;
198 extern int open64(const char *, int, ...);
199 static int (*true_open64) (const char *, int, ...) = NULL;
200 extern int truncate64(const char *, __off64_t);
201 static int (*true_truncate64) (const char *, __off64_t) = NULL;
202
203 #endif
204
205 extern int execve(const char *filename, char *const argv[], char *const envp[]);
206 static int (*true_execve) (const char *, char *const[], char *const[]);
207
208 /*
209 * Initialize the shabang
210 */
211
212 static void init_wrappers(void)
213 {
214 check_dlsym(chmod);
215 check_dlsym(chown);
216 check_dlsym(creat);
217 check_dlsym(fopen);
218 check_dlsym(lchown);
219 check_dlsym(link);
220 check_dlsym(mkdir);
221 check_dlsym(opendir);
222 #ifdef WRAP_MKNOD
223 check_dlsym(__xmknod);
224 #endif
225 check_dlsym(access);
226 check_dlsym(open);
227 check_dlsym(rename);
228 check_dlsym(rmdir);
229 check_dlsym(symlink);
230 check_dlsym(truncate);
231 check_dlsym(unlink);
232
233 #if (GLIBC_MINOR >= 1)
234 check_dlsym(creat64);
235 check_dlsym(fopen64);
236 check_dlsym(open64);
237 check_dlsym(truncate64);
238 #endif
239
240 check_dlsym(execve);
241 }
242
243 static void *libc_handle = NULL;
244
245 static void *get_dlsym(const char *symname, const char *symver)
246 {
247 void *symaddr = NULL;
248
249 if (NULL == libc_handle) {
250 #ifdef BROKEN_RTLD_NEXT
251 libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY);
252 if (!libc_handle) {
253 printf("libsandbox.so: Can't dlopen libc: %s\n", dlerror());
254 abort();
255 }
256 #else
257 libc_handle = RTLD_NEXT;
258 #endif
259 }
260
261 if (NULL == symver)
262 symaddr = dlsym(libc_handle, symname);
263 else
264 symaddr = dlvsym(libc_handle, symname, symver);
265 if (!symaddr) {
266 printf("libsandbox.so: Can't resolve %s: %s\n", symname, dlerror());
267 abort();
268 }
269
270 return symaddr;
271 }
272
273
274 void __attribute__ ((destructor)) libsb_fini(void)
275 {
276 int x;
277 if(NULL != cached_env_vars) {
278 for(x=0; x < 4; x++) {
279 if(NULL != cached_env_vars[x])
280 free(cached_env_vars[x]);
281 }
282 free(cached_env_vars);
283 }
284 clean_env_entries(&(sbcontext.deny_prefixes),
285 &(sbcontext.num_deny_prefixes));
286 clean_env_entries(&(sbcontext.read_prefixes),
287 &(sbcontext.num_read_prefixes));
288 clean_env_entries(&(sbcontext.write_prefixes),
289 &(sbcontext.num_write_prefixes));
290 clean_env_entries(&(sbcontext.predict_prefixes),
291 &(sbcontext.num_predict_prefixes));
292
293 free(sandbox_pids_file);
294 }
295
296 void __attribute__ ((constructor)) libsb_init(void)
297 {
298 int old_errno = errno;
299 char tmp_dir[SB_PATH_MAX];
300
301 #ifdef SB_MEM_DEBUG
302 mtrace();
303 #endif
304
305 init_wrappers();
306
307 /* Get the path and name to this library */
308 snprintf(sandbox_lib, SB_PATH_MAX, "%s", get_sandbox_lib("/"));
309
310 if (-1 == get_tmp_dir(tmp_dir))
311 snprintf(tmp_dir, SB_PATH_MAX, "%s", TMPDIR);
312
313 /* Generate sandbox pids-file path */
314 sandbox_pids_file = get_sandbox_pids_file(tmp_dir);
315
316 // sb_init = 1;
317
318 errno = old_errno;
319 }
320
321 static int canonicalize(const char *path, char *resolved_path)
322 {
323 int old_errno = errno;
324 char *retval;
325
326 *resolved_path = '\0';
327
328 /* If path == NULL, return or we get a segfault */
329 if (NULL == path) {
330 errno = EINVAL;
331 return -1;
332 }
333
334 /* Do not try to resolve an empty path */
335 if ('\0' == path[0]) {
336 errno = old_errno;
337 return 0;
338 }
339
340 retval = erealpath(path, resolved_path);
341
342 if ((NULL == retval) && (path[0] != '/')) {
343 /* The path could not be canonicalized, append it
344 * to the current working directory if it was not
345 * an absolute path
346 */
347
348 if (ENAMETOOLONG == errno)
349 return -1;
350
351 if (NULL == egetcwd(resolved_path, SB_PATH_MAX - 2))
352 return -1;
353 snprintf((char *)(resolved_path + strlen(resolved_path)),
354 SB_PATH_MAX - strlen(resolved_path), "/%s", path);
355
356 if (NULL == erealpath(resolved_path, resolved_path)) {
357 if (errno == ENAMETOOLONG) {
358 /* The resolved path is too long for the buffer to hold */
359 return -1;
360 } else {
361 /* Whatever it resolved, is not a valid path */
362 errno = ENOENT;
363 return -1;
364 }
365 }
366
367 } else if ((NULL == retval) && (path[0] == '/')) {
368 /* Whatever it resolved, is not a valid path */
369 errno = ENOENT;
370 return -1;
371 }
372
373 errno = old_errno;
374 return 0;
375 }
376
377 static char *filter_path(const char *path, int follow_link)
378 {
379 struct stat st;
380 int old_errno = errno;
381 char tmp_str1[SB_PATH_MAX], tmp_str2[SB_PATH_MAX];
382 char *dname, *bname;
383 char *filtered_path;
384
385 if (NULL == path)
386 return NULL;
387
388 filtered_path = malloc(SB_PATH_MAX * sizeof(char));
389 if (NULL == filtered_path)
390 return NULL;
391
392 if (0 == follow_link) {
393 if (-1 == canonicalize(path, filtered_path))
394 return NULL;
395 } else {
396 /* Basically we get the realpath which should resolve symlinks,
397 * etc. If that fails (might not exist), we try to get the
398 * realpath of the parent directory, as that should hopefully
399 * exist. If all else fails, just go with canonicalize */
400 if (NULL == realpath(path, filtered_path)) {
401 snprintf(tmp_str1, SB_PATH_MAX, "%s", path);
402
403 dname = dirname(tmp_str1);
404
405 /* If not, then check if we can resolve the
406 * parent directory */
407 if (NULL == realpath(dname, filtered_path)) {
408 /* Fall back to canonicalize */
409 if (-1 == canonicalize(path, filtered_path))
410 return NULL;
411 } else {
412 /* OK, now add the basename to keep our access
413 * checking happy (don't want '/usr/lib' if we
414 * tried to do something with non-existing
415 * file '/usr/lib/cf*' ...) */
416 snprintf(tmp_str2, SB_PATH_MAX, "%s", path);
417
418 bname = basename(tmp_str2);
419 snprintf((char *)(filtered_path + strlen(filtered_path)),
420 SB_PATH_MAX - strlen(filtered_path), "%s%s",
421 (filtered_path[strlen(filtered_path) - 1] != '/') ? "/" : "",
422 bname);
423 }
424 }
425 }
426
427 errno = old_errno;
428
429 return filtered_path;
430 }
431
432 /*
433 * Wrapper Functions
434 */
435
436 int chmod(const char *path, mode_t mode)
437 {
438 int result = -1;
439
440 if FUNCTION_SANDBOX_SAFE("chmod", path) {
441 check_dlsym(chmod);
442 result = true_chmod(path, mode);
443 }
444
445 return result;
446 }
447
448 int chown(const char *path, uid_t owner, gid_t group)
449 {
450 int result = -1;
451
452 if FUNCTION_SANDBOX_SAFE("chown", path) {
453 check_dlsym(chown);
454 result = true_chown(path, owner, group);
455 }
456
457 return result;
458 }
459
460 int creat(const char *pathname, mode_t mode)
461 {
462 /* Is it a system call? */
463 int result = -1;
464
465 if FUNCTION_SANDBOX_SAFE("creat", pathname) {
466 check_dlsym(open);
467 result = true_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
468 }
469
470 return result;
471 }
472
473 FILE *fopen(const char *pathname, const char *mode)
474 {
475 FILE *result = NULL;
476
477 if FUNCTION_SANDBOX_SAFE_OPEN_CHAR("fopen", pathname, mode) {
478 check_dlsym(fopen);
479 result = true_fopen(pathname, mode);
480 }
481
482 return result;
483 }
484
485 int lchown(const char *path, uid_t owner, gid_t group)
486 {
487 int result = -1;
488
489 if FUNCTION_SANDBOX_SAFE("lchown", path) {
490 check_dlsym(lchown);
491 result = true_lchown(path, owner, group);
492 }
493
494 return result;
495 }
496
497 int link(const char *oldpath, const char *newpath)
498 {
499 int result = -1;
500
501 if FUNCTION_SANDBOX_SAFE("link", newpath) {
502 check_dlsym(link);
503 result = true_link(oldpath, newpath);
504 }
505
506 return result;
507 }
508
509 int mkdir(const char *pathname, mode_t mode)
510 {
511 struct stat st;
512 int result = -1, my_errno = errno;
513 char canonic[SB_PATH_MAX];
514
515 if (-1 == canonicalize(pathname, canonic))
516 /* Path is too long to canonicalize, do not fail, but just let
517 * the real function handle it (see bug #94630 and #21766). */
518 if (ENAMETOOLONG != errno)
519 return -1;
520
521 /* XXX: Hack to prevent errors if the directory exist,
522 * and are not writable - we rather return EEXIST rather
523 * than failing */
524 if (0 == lstat(canonic, &st)) {
525 errno = EEXIST;
526 return -1;
527 }
528 errno = my_errno;
529
530 if FUNCTION_SANDBOX_SAFE("mkdir", pathname) {
531 check_dlsym(mkdir);
532 result = true_mkdir(pathname, mode);
533 }
534
535 return result;
536 }
537
538 DIR *opendir(const char *name)
539 {
540 DIR *result = NULL;
541
542 if FUNCTION_SANDBOX_SAFE("opendir", name) {
543 check_dlsym(opendir);
544 result = true_opendir(name);
545 }
546
547 return result;
548 }
549
550 #ifdef WRAP_MKNOD
551
552 int __xmknod(const char *pathname, mode_t mode, dev_t dev)
553 {
554 int result = -1;
555
556 if FUNCTION_SANDBOX_SAFE("__xmknod", pathname) {
557 check_dlsym(__xmknod);
558 result = true___xmknod(pathname, mode, dev);
559 }
560
561 return result;
562 }
563
564 #endif
565
566 int access(const char *pathname, int mode)
567 {
568 int result = -1;
569
570 if FUNCTION_SANDBOX_SAFE_ACCESS("access", pathname, mode) {
571 check_dlsym(access);
572 result = true_access(pathname, mode);
573 }
574
575 return result;
576 }
577
578 /* Eventually, there is a third parameter: it's mode_t mode */
579 int open(const char *pathname, int flags, ...)
580 {
581 va_list ap;
582 mode_t mode = 0;
583 int result = -1;
584
585 if (flags & O_CREAT) {
586 va_start(ap, flags);
587 mode = va_arg(ap, mode_t);
588 va_end(ap);
589 }
590
591 if FUNCTION_SANDBOX_SAFE_OPEN_INT("open", pathname, flags) {
592 check_dlsym(open);
593 result = true_open(pathname, flags, mode);
594 }
595
596 return result;
597 }
598
599 int rename(const char *oldpath, const char *newpath)
600 {
601 int result = -1;
602
603 if (FUNCTION_SANDBOX_SAFE("rename", oldpath) &&
604 FUNCTION_SANDBOX_SAFE("rename", newpath)) {
605 check_dlsym(rename);
606 result = true_rename(oldpath, newpath);
607 }
608
609 return result;
610 }
611
612 int rmdir(const char *pathname)
613 {
614 int result = -1;
615
616 if FUNCTION_SANDBOX_SAFE("rmdir", pathname) {
617 check_dlsym(rmdir);
618 result = true_rmdir(pathname);
619 }
620
621 return result;
622 }
623
624 int symlink(const char *oldpath, const char *newpath)
625 {
626 int result = -1;
627
628 if FUNCTION_SANDBOX_SAFE("symlink", newpath) {
629 check_dlsym(symlink);
630 result = true_symlink(oldpath, newpath);
631 }
632
633 return result;
634 }
635
636 int truncate(const char *path, TRUNCATE_T length)
637 {
638 int result = -1;
639
640 if FUNCTION_SANDBOX_SAFE("truncate", path) {
641 check_dlsym(truncate);
642 result = true_truncate(path, length);
643 }
644
645 return result;
646 }
647
648 int unlink(const char *pathname)
649 {
650 int result = -1;
651 char canonic[SB_PATH_MAX];
652
653 if (-1 == canonicalize(pathname, canonic))
654 /* Path is too long to canonicalize, do not fail, but just let
655 * the real function handle it (see bug #94630 and #21766). */
656 if (ENAMETOOLONG != errno)
657 return -1;
658
659 /* XXX: Hack to make sure sandboxed process cannot remove
660 * a device node, bug #79836. */
661 if ((0 == strncmp(canonic, "/dev/null", 9)) ||
662 (0 == strncmp(canonic, "/dev/zero", 9))) {
663 errno = EACCES;
664 return result;
665 }
666
667 if FUNCTION_SANDBOX_SAFE("unlink", pathname) {
668 check_dlsym(unlink);
669 result = true_unlink(pathname);
670 }
671
672 return result;
673 }
674
675 #if (GLIBC_MINOR >= 1)
676
677 int creat64(const char *pathname, __mode_t mode)
678 {
679 /* Is it a system call? */
680 int result = -1;
681
682 if FUNCTION_SANDBOX_SAFE("creat64", pathname) {
683 check_dlsym(open64);
684 result = true_open64(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
685 }
686
687 return result;
688 }
689
690 FILE *fopen64(const char *pathname, const char *mode)
691 {
692 FILE *result = NULL;
693
694 if FUNCTION_SANDBOX_SAFE_OPEN_CHAR("fopen64", pathname, mode) {
695 check_dlsym(fopen64);
696 result = true_fopen64(pathname, mode);
697 }
698
699 return result;
700 }
701
702 /* Eventually, there is a third parameter: it's mode_t mode */
703 int open64(const char *pathname, int flags, ...)
704 {
705 va_list ap;
706 mode_t mode = 0;
707 int result = -1;
708
709 if (flags & O_CREAT) {
710 va_start(ap, flags);
711 mode = va_arg(ap, mode_t);
712 va_end(ap);
713 }
714
715 if FUNCTION_SANDBOX_SAFE_OPEN_INT("open64", pathname, flags) {
716 check_dlsym(open64);
717 result = true_open64(pathname, flags, mode);
718 }
719
720 return result;
721 }
722
723 int truncate64(const char *path, __off64_t length)
724 {
725 int result = -1;
726
727 if FUNCTION_SANDBOX_SAFE("truncate64", path) {
728 check_dlsym(truncate64);
729 result = true_truncate64(path, length);
730 }
731
732 return result;
733 }
734
735 #endif /* GLIBC_MINOR >= 1 */
736
737 /*
738 * Exec Wrappers
739 */
740
741 int execve(const char *filename, char *const argv[], char *const envp[])
742 {
743 int old_errno = errno;
744 int result = -1;
745 int count = 0;
746 int env_len = 0;
747 char **my_env = NULL;
748 int kill_env = 1;
749 /* We limit the size LD_PRELOAD can be here, but it should be enough */
750 char tmp_str[SB_BUF_LEN];
751
752 if FUNCTION_SANDBOX_SAFE("execve", filename) {
753 while (envp[count] != NULL) {
754 /* Check if we do not have to do anything */
755 if (strstr(envp[count], LD_PRELOAD_EQ) == envp[count]) {
756 if (NULL != strstr(envp[count], sandbox_lib)) {
757 my_env = (char **)envp;
758 kill_env = 0;
759 goto end_loop;
760 }
761 }
762
763 /* If LD_PRELOAD is set and sandbox_lib not in it */
764 if (((strstr(envp[count], LD_PRELOAD_EQ) == envp[count]) &&
765 (NULL == strstr(envp[count], sandbox_lib))) ||
766 /* Or LD_PRELOAD is not set, and this is the last loop */
767 ((strstr(envp[count], LD_PRELOAD_EQ) != envp[count]) &&
768 (NULL == envp[count + 1]))) {
769 int i = 0;
770 int add_ldpreload = 0;
771 const int max_envp_len = strlen(envp[count]) + strlen(sandbox_lib) + 1;
772
773 /* Fail safe ... */
774 if (max_envp_len > SB_BUF_LEN) {
775 fprintf(stderr, "sandbox: max_envp_len too big!\n");
776 errno = ENOMEM;
777 return result;
778 }
779
780 /* Calculate envp size */
781 my_env = (char **)envp;
782 do
783 env_len++;
784 while (NULL != *my_env++);
785
786 /* Should we add LD_PRELOAD ? */
787 if (strstr(envp[count], LD_PRELOAD_EQ) != envp[count])
788 add_ldpreload = 1;
789
790 my_env = (char **)calloc(env_len + add_ldpreload, sizeof(char *));
791 if (NULL == my_env) {
792 errno = ENOMEM;
793 return result;
794 }
795 /* Copy envp to my_env */
796 do
797 /* Leave a space for LD_PRELOAD if needed */
798 my_env[i + add_ldpreload] = envp[i];
799 while (NULL != envp[i++]);
800
801 /* Add 'LD_PRELOAD=' to the beginning of our new string */
802 snprintf(tmp_str, max_envp_len, "%s%s", LD_PRELOAD_EQ, sandbox_lib);
803
804 /* LD_PRELOAD already have variables other than sandbox_lib,
805 * thus we have to add sandbox_lib seperated via a whitespace. */
806 if (0 == add_ldpreload) {
807 snprintf((char *)(tmp_str + strlen(tmp_str)),
808 max_envp_len - strlen(tmp_str) + 1, " %s",
809 (char *)(envp[count] + strlen(LD_PRELOAD_EQ)));
810 }
811
812 /* Valid string? */
813 tmp_str[max_envp_len] = '\0';
814
815 /* Ok, replace my_env[count] with our version that contains
816 * sandbox_lib ... */
817 if (1 == add_ldpreload)
818 /* We reserved a space for LD_PRELOAD above */
819 my_env[0] = tmp_str;
820 else
821 my_env[count] = tmp_str;
822
823 goto end_loop;
824 }
825 count++;
826 }
827
828 end_loop:
829 errno = old_errno;
830 check_dlsym(execve);
831 result = true_execve(filename, argv, my_env);
832 old_errno = errno;
833
834 if (my_env && kill_env)
835 free(my_env);
836 }
837
838 errno = old_errno;
839
840 return result;
841 }
842
843 /*
844 * Internal Functions
845 */
846
847 #if (GLIBC_MINOR == 1)
848
849 /* This hack is needed for glibc 2.1.1 (and others?)
850 * (not really needed, but good example) */
851 extern int fclose(FILE *);
852 static int (*true_fclose) (FILE *) = NULL;
853 int fclose(FILE * file)
854 {
855 int result = -1;
856
857 check_dlsym(fclose);
858 result = true_fclose(file);
859
860 return result;
861 }
862
863 #endif /* GLIBC_MINOR == 1 */
864
865 static void init_context(sbcontext_t * context)
866 {
867 context->show_access_violation = 1;
868 context->deny_prefixes = NULL;
869 context->num_deny_prefixes = 0;
870 context->read_prefixes = NULL;
871 context->num_read_prefixes = 0;
872 context->write_prefixes = NULL;
873 context->num_write_prefixes = 0;
874 context->predict_prefixes = NULL;
875 context->num_predict_prefixes = 0;
876 context->write_denied_prefixes = NULL;
877 context->num_write_denied_prefixes = 0;
878 }
879
880 static int is_sandbox_pid()
881 {
882 int old_errno = errno;
883 int result = 0;
884 FILE *pids_stream = NULL;
885 int pids_file = -1;
886 int current_pid = 0;
887 int tmp_pid = 0;
888
889 init_wrappers();
890
891 check_dlsym(fopen);
892 pids_stream = true_fopen(sandbox_pids_file, "r");
893
894 if (NULL == pids_stream) {
895 perror(">>> pids file fopen");
896 } else {
897 pids_file = fileno(pids_stream);
898
899 if (pids_file < 0) {
900 perror(">>> pids file fileno");
901 } else {
902 current_pid = getpid();
903
904 while (EOF != fscanf(pids_stream, "%d\n", &tmp_pid)) {
905 if (tmp_pid == current_pid) {
906 result = 1;
907 break;
908 }
909 }
910 }
911 if (EOF == fclose(pids_stream)) {
912 perror(">>> pids file fclose");
913 }
914 pids_stream = NULL;
915 pids_file = -1;
916 }
917
918 errno = old_errno;
919
920 return result;
921 }
922
923 static void clean_env_entries(char ***prefixes_array, int *prefixes_num)
924 {
925 int old_errno = errno;
926 int i = 0;
927
928 if (NULL != *prefixes_array) {
929 for (i = 0; i < *prefixes_num; i++) {
930 if (NULL != (*prefixes_array)[i]) {
931 free((*prefixes_array)[i]);
932 (*prefixes_array)[i] = NULL;
933 }
934 }
935 if (NULL != *prefixes_array)
936 free(*prefixes_array);
937 *prefixes_array = NULL;
938 *prefixes_num = 0;
939 }
940
941 errno = old_errno;
942 }
943
944 #define pfx_num (*prefixes_num)
945 #define pfx_array (*prefixes_array)
946 #define pfx_item ((*prefixes_array)[(*prefixes_num)])
947
948 static void init_env_entries(char ***prefixes_array, int *prefixes_num, const char *env, const char *prefixes_env, int warn)
949 {
950 int old_errno = errno;
951 // char *prefixes_env = getenv(env);
952
953 if (NULL == prefixes_env) {
954 /* Do not warn if this is in init stage, as we might get
955 * issues due to LD_PRELOAD already set (bug #91431). */
956 if (1 == sb_init)
957 fprintf(stderr, "Sandbox error : the %s environmental variable should be defined.\n", env);
958 if(pfx_array) {
959 int x;
960 for(x=0; x < pfx_num; x++)
961 free(pfx_item);
962 free(pfx_array);
963 }
964 pfx_num = 0;
965 } else {
966 char *buffer = NULL;
967 char *buffer_ptr = NULL;
968 int prefixes_env_length = strlen(prefixes_env);
969 int i = 0;
970 int num_delimiters = 0;
971 char *token = NULL;
972 char *rpath = NULL;
973
974 for (i = 0; i < prefixes_env_length; i++) {
975 if (':' == prefixes_env[i]) {
976 num_delimiters++;
977 }
978 }
979
980 if (num_delimiters > 0) {
981 pfx_array = malloc(((num_delimiters * 2) + 1) * sizeof(char *));
982 if (NULL == pfx_array)
983 return;
984 buffer = strndup(prefixes_env, prefixes_env_length);
985 if (NULL == buffer)
986 return;
987 buffer_ptr = buffer;
988
989 #ifdef REENTRANT_STRTOK
990 token = strtok_r(buffer_ptr, ":", &buffer_ptr);
991 #else
992 token = strtok(buffer_ptr, ":");
993 #endif
994
995 while ((NULL != token) && (strlen(token) > 0)) {
996 pfx_item = filter_path(token, 0);
997 if (NULL != pfx_item) {
998 pfx_num++;
999
1000 /* Now add the realpath if it exists and
1001 * are not a duplicate */
1002 rpath = malloc(SB_PATH_MAX * sizeof(char));
1003 if (NULL != rpath) {
1004 pfx_item = realpath(*(&(pfx_item) - 1), rpath);
1005 if ((NULL != pfx_item) &&
1006 (0 != strcmp(*(&(pfx_item) - 1), pfx_item))) {
1007 pfx_num++;
1008 } else {
1009 free(rpath);
1010 pfx_item = NULL;
1011 }
1012 }
1013 }
1014
1015 #ifdef REENTRANT_STRTOK
1016 token = strtok_r(NULL, ":", &buffer_ptr);
1017 #else
1018 token = strtok(NULL, ":");
1019 #endif
1020 }
1021
1022 free(buffer);
1023 } else if (prefixes_env_length > 0) {
1024 pfx_array = malloc(2 * sizeof(char *));
1025 if (NULL == pfx_array)
1026 return;
1027
1028 pfx_item = filter_path(prefixes_env, 0);
1029 if (NULL != pfx_item) {
1030 pfx_num++;
1031
1032 /* Now add the realpath if it exists and
1033 * are not a duplicate */
1034 rpath = malloc(SB_PATH_MAX * sizeof(char));
1035 if (NULL != rpath) {
1036 pfx_item = realpath(*(&(pfx_item) - 1), rpath);
1037 if ((NULL != pfx_item) &&
1038 (0 != strcmp(*(&(pfx_item) - 1), pfx_item))) {
1039 pfx_num++;
1040 } else {
1041 free(rpath);
1042 pfx_item = NULL;
1043 }
1044 }
1045 }
1046 }
1047 }
1048
1049 errno = old_errno;
1050 }
1051
1052 static int check_access(sbcontext_t * sbcontext, const char *func, const char *path, const char *fpath)
1053 {
1054 int old_errno = errno;
1055 int result = -1;
1056 int i = 0;
1057
1058 if ((-1 == result) && (NULL != sbcontext->deny_prefixes)) {
1059 for (i = 0; i < sbcontext->num_deny_prefixes; i++) {
1060 if (NULL != sbcontext->deny_prefixes[i]) {
1061 if (0 == strncmp(fpath,
1062 sbcontext->deny_prefixes[i],
1063 strlen(sbcontext->deny_prefixes[i]))) {
1064 result = 0;
1065 break;
1066 }
1067 }
1068 }
1069 }
1070
1071 if (-1 == result) {
1072 if ((NULL != sbcontext->read_prefixes) &&
1073 ((0 == strncmp(func, "access_rd", 9)) ||
1074 (0 == strncmp(func, "open_rd", 7)) ||
1075 (0 == strncmp(func, "popen", 5)) ||
1076 (0 == strncmp(func, "opendir", 7)) ||
1077 (0 == strncmp(func, "system", 6)) ||
1078 (0 == strncmp(func, "execl", 5)) ||
1079 (0 == strncmp(func, "execlp", 6)) ||
1080 (0 == strncmp(func, "execle", 6)) ||
1081 (0 == strncmp(func, "execv", 5)) ||
1082 (0 == strncmp(func, "execvp", 6)) ||
1083 (0 == strncmp(func, "execve", 6)))) {
1084 for (i = 0; i < sbcontext->num_read_prefixes; i++) {
1085 if (NULL != sbcontext->read_prefixes[i]) {
1086 if (0 == strncmp(fpath,
1087 sbcontext->read_prefixes[i],
1088 strlen(sbcontext->read_prefixes[i]))) {
1089 result = 1;
1090 break;
1091 }
1092 }
1093 }
1094 }
1095 if ((NULL != sbcontext->write_prefixes) &&
1096 ((0 == strncmp(func, "access_wr", 7)) ||
1097 (0 == strncmp(func, "open_wr", 7)) ||
1098 (0 == strncmp(func, "creat", 5)) ||
1099 (0 == strncmp(func, "creat64", 7)) ||
1100 (0 == strncmp(func, "mkdir", 5)) ||
1101 (0 == strncmp(func, "mknod", 5)) ||
1102 (0 == strncmp(func, "mkfifo", 6)) ||
1103 (0 == strncmp(func, "link", 4)) ||
1104 (0 == strncmp(func, "symlink", 7)) ||
1105 (0 == strncmp(func, "rename", 6)) ||
1106 (0 == strncmp(func, "utime", 5)) ||
1107 (0 == strncmp(func, "utimes", 6)) ||
1108 (0 == strncmp(func, "unlink", 6)) ||
1109 (0 == strncmp(func, "rmdir", 5)) ||
1110 (0 == strncmp(func, "chown", 5)) ||
1111 (0 == strncmp(func, "lchown", 6)) ||
1112 (0 == strncmp(func, "chmod", 5)) ||
1113 (0 == strncmp(func, "truncate", 8)) ||
1114 (0 == strncmp(func, "ftruncate", 9)) ||
1115 (0 == strncmp(func, "truncate64", 10)) ||
1116 (0 == strncmp(func, "ftruncate64", 11)))) {
1117 struct stat st;
1118
1119 /* No need to check here, as we do it above
1120 if (NULL != sbcontext->write_prefixes) { */
1121
1122 if (NULL != sbcontext->write_denied_prefixes) {
1123 for (i = 0; i < sbcontext->num_write_denied_prefixes; i++) {
1124 if (NULL != sbcontext->write_denied_prefixes[i]) {
1125 if (0 == strncmp(fpath,
1126 sbcontext->write_denied_prefixes[i],
1127 strlen(sbcontext->write_denied_prefixes[i]))) {
1128 /* Special paths in writable context that should
1129 * be denied - not implemented yet */
1130 result = 0;
1131 break;
1132 }
1133 }
1134 }
1135 }
1136
1137 if ((-1 == result) && (NULL != sbcontext->write_prefixes)) {
1138 for (i = 0; i < sbcontext->num_write_prefixes; i++) {
1139 if (NULL != sbcontext->write_prefixes[i]) {
1140 if (0 == strncmp(fpath,
1141 sbcontext->write_prefixes[i],
1142 strlen(sbcontext->write_prefixes[i]))) {
1143 /* Falls in a writable path */
1144 result = 1;
1145 break;
1146 }
1147 }
1148 }
1149 }
1150
1151 /* XXX: Hack to enable us to remove symlinks pointing
1152 * to protected stuff. First we make sure that the
1153 * passed path is writable, and if so, check if its a
1154 * symlink, and give access only if the resolved path
1155 * of the symlink's parent also have write access. */
1156 if ((-1 == result) &&
1157 ((0 == strncmp(func, "unlink", 6)) ||
1158 (0 == strncmp(func, "lchown", 6)) ||
1159 (0 == strncmp(func, "rename", 6))) &&
1160 ((-1 != lstat(path, &st)) && (S_ISLNK(st.st_mode)))) {
1161 int hresult = -1;
1162
1163 /* Check if the symlink unresolved path have access */
1164 for (i = 0; i < sbcontext->num_write_prefixes; i++) {
1165 if (NULL != sbcontext->write_prefixes[i]) {
1166 if (0 == strncmp(path,
1167 sbcontext->write_prefixes[i],
1168 strlen(sbcontext->write_prefixes[i]))) {
1169 /* Does have write access on path */
1170 hresult = 1;
1171 break;
1172 }
1173 }
1174 }
1175 if (1 == hresult) {
1176 char tmp_buf[SB_PATH_MAX];
1177 char *dname, *rpath;
1178
1179 snprintf(tmp_buf, SB_PATH_MAX, "%s", path);
1180
1181 dname = dirname(tmp_buf);
1182 /* Get symlink resolved path */
1183 rpath = filter_path(dname, 1);
1184 if (NULL == rpath)
1185 /* Don't really worry here about
1186 * memory issues */
1187 goto unlink_hack_end;
1188
1189 /* Now check if the symlink resolved path have access */
1190 for (i = 0; i < sbcontext->num_write_prefixes; i++) {
1191 if (NULL != sbcontext->write_prefixes[i]) {
1192 if (0 == strncmp(rpath,
1193 sbcontext->write_prefixes[i],
1194 strlen(sbcontext->write_prefixes[i]))) {
1195 /* Does have write access on path */
1196 hresult = 2;
1197 break;
1198 }
1199 }
1200 }
1201 free(rpath);
1202
1203 if (2 == hresult) {
1204 /* Ok, enable the hack as it is a symlink */
1205 result = 1;
1206 }
1207 }
1208 }
1209 unlink_hack_end:
1210
1211 /* XXX: Hack to allow writing to '/proc/self/fd' (bug #91516)
1212 * It needs to be here, as for each process '/proc/self'
1213 * will differ ... */
1214 if (-1 == result) {
1215 char proc_self_fd[SB_PATH_MAX];
1216
1217 if (NULL != realpath("/proc/self/fd", proc_self_fd)) {
1218 if (0 == strncmp(fpath, proc_self_fd, strlen(proc_self_fd)))
1219 result = 1;
1220 }
1221 }
1222
1223 if ((-1 == result) && (NULL != sbcontext->predict_prefixes)) {
1224 for (i = 0; i < sbcontext->num_predict_prefixes; i++) {
1225 if (NULL != sbcontext->predict_prefixes[i]) {
1226 if (0 == strncmp(fpath,
1227 sbcontext->predict_prefixes[i],
1228 strlen(sbcontext->predict_prefixes[i]))) {
1229 /* Is a known access violation, so deny access,
1230 * and do not log it */
1231 sbcontext->show_access_violation = 0;
1232 result = 0;
1233 break;
1234 }
1235 }
1236 }
1237 }
1238 }
1239 }
1240
1241 if (-1 == result) {
1242 result = 0;
1243 }
1244
1245 errno = old_errno;
1246
1247 return result;
1248 }
1249
1250 static int check_syscall(sbcontext_t * sbcontext, const char *func, const char *file)
1251 {
1252 int old_errno = errno;
1253 int result = 1;
1254 struct stat log_stat;
1255 char *log_path = NULL;
1256 char *absolute_path = NULL;
1257 char *resolved_path = NULL;
1258 char *tmp_buffer = NULL;
1259 int log_file = 0;
1260 struct stat debug_log_stat;
1261 char *debug_log_env = NULL;
1262 char *debug_log_path = NULL;
1263 int debug_log_file = 0;
1264 char buffer[512];
1265 char *dpath = NULL;
1266
1267 init_wrappers();
1268
1269 absolute_path = filter_path(file, 0);
1270 if (NULL == absolute_path)
1271 goto fp_error;
1272 resolved_path = filter_path(file, 1);
1273 if (NULL == resolved_path)
1274 goto fp_error;
1275
1276 log_path = getenv("SANDBOX_LOG");
1277 debug_log_env = getenv("SANDBOX_DEBUG");
1278 debug_log_path = getenv("SANDBOX_DEBUG_LOG");
1279
1280 if (((NULL == log_path) ||
1281 (0 != strncmp(absolute_path, log_path, strlen(log_path)))) &&
1282 ((NULL == debug_log_env) ||
1283 (NULL == debug_log_path) ||
1284 (0 != strncmp(absolute_path, debug_log_path, strlen(debug_log_path)))) &&
1285 (0 == check_access(sbcontext, func, absolute_path, resolved_path))) {
1286 if (1 == sbcontext->show_access_violation) {
1287 fprintf(stderr, "\e[31;01mACCESS DENIED\033[0m %s:%*s%s\n",
1288 func, (int)(10 - strlen(func)), "", absolute_path);
1289
1290 if (NULL != log_path) {
1291 if (0 != strncmp(absolute_path, resolved_path, strlen(absolute_path))) {
1292 sprintf(buffer, "%s:%*s%s (symlink to %s)\n", func, (int)(10-strlen(func)), "",
1293 absolute_path, resolved_path);
1294 } else {
1295 sprintf(buffer, "%s:%*s%s\n", func, (int)(10 - strlen(func)), "", absolute_path);
1296 }
1297 // log_path somehow gets corrupted. figuring out why would be good.
1298 dpath = strdup(log_path);
1299 if ((0 == lstat(log_path, &log_stat)) &&
1300 (0 == S_ISREG(log_stat.st_mode))) {
1301 fprintf(stderr, "\e[31;01mSECURITY BREACH\033[0m %s already exists and is not a regular file.\n", dpath);
1302 } else if (0 == check_access(sbcontext, "open_wr", dpath, filter_path(dpath, 1))) {
1303 unsetenv("SANDBOX_LOG");
1304 fprintf(stderr, "\e[31;01mSECURITY BREACH\033[0m SANDBOX_LOG %s isn't allowed via SANDBOX_WRITE\n", dpath);
1305 } else {
1306 check_dlsym(open);
1307 log_file = true_open(dpath, O_APPEND | O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1308 if (log_file >= 0) {
1309 write(log_file, buffer, strlen(buffer));
1310 close(log_file);
1311 }
1312 }
1313 free(dpath);
1314 }
1315 }
1316
1317 result = 0;
1318 } else if (NULL != debug_log_env) {
1319 if (NULL != debug_log_path) {
1320 if (0 != strncmp(absolute_path, debug_log_path, strlen(debug_log_path))) {
1321 sprintf(buffer, "%s:%*s%s\n", func, (int)(10 - strlen(func)), "", absolute_path);
1322 //debug_log_path somehow gets corupted, same thing as log_path above.
1323 dpath = strdup(debug_log_path);
1324 if ((0 == lstat(debug_log_path, &debug_log_stat))
1325 && (0 == S_ISREG(debug_log_stat.st_mode))) {
1326 fprintf(stderr, "\e[31;01mSECURITY BREACH\033[0m %s already exists and is not a regular file.\n",
1327 debug_log_path);
1328 } else if (0 == check_access(sbcontext, "open_wr", dpath, filter_path(dpath, 1))) {
1329 unsetenv("SANDBOX_DEBUG");
1330 unsetenv("SANDBOX_DEBUG_LOG");
1331 fprintf(stderr, "\e[31;01mSECURITY BREACH\033[0m SANDBOX_DEBUG_LOG %s isn't allowed by SANDBOX_WRITE.\n",
1332 dpath);
1333 } else {
1334 check_dlsym(open);
1335 debug_log_file = true_open(dpath, O_APPEND | O_WRONLY | O_CREAT,
1336 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1337 if (debug_log_file >= 0) {
1338 write(debug_log_file, buffer, strlen(buffer));
1339 close(debug_log_file);
1340 }
1341 }
1342 free(dpath);
1343 }
1344 } else {
1345 fprintf(stderr, "\e[32;01mACCESS ALLOWED\033[0m %s:%*s%s\n",
1346 func, (int)(10 - strlen(func)), "", absolute_path);
1347 }
1348 }
1349
1350 if (NULL != absolute_path)
1351 free(absolute_path);
1352 if (NULL != resolved_path)
1353 free(resolved_path);
1354
1355 errno = old_errno;
1356
1357 return result;
1358
1359 fp_error:
1360 if (NULL != absolute_path)
1361 free(absolute_path);
1362 if (NULL != resolved_path)
1363 free(resolved_path);
1364
1365 /* The path is too long to be canonicalized, so just warn and let the
1366 * function handle it (see bug #94630 and #21766 for more info) */
1367 if (ENAMETOOLONG == errno) {
1368 if (0 == sb_path_size_warning) {
1369 fprintf(stderr, "\e[31;01mPATH LENGTH\033[0m %s:%*s%s\n",
1370 func, (int)(10 - strlen(func)), "", file);
1371 sb_path_size_warning = 1;
1372 }
1373
1374 return 1;
1375 }
1376
1377 return 0;
1378 }
1379
1380 static int is_sandbox_on()
1381 {
1382 int old_errno = errno;
1383
1384 /* $SANDBOX_ACTIVE is an env variable that should ONLY
1385 * be used internal by sandbox.c and libsanbox.c. External
1386 * sources should NEVER set it, else the sandbox is enabled
1387 * in some cases when run in parallel with another sandbox,
1388 * but not even in the sandbox shell.
1389 *
1390 * Azarah (3 Aug 2002)
1391 */
1392 if ((NULL != getenv("SANDBOX_ON")) &&
1393 (0 == strncmp(getenv("SANDBOX_ON"), "1", 1)) &&
1394 (NULL != getenv("SANDBOX_ACTIVE")) &&
1395 (0 == strncmp(getenv("SANDBOX_ACTIVE"), "armedandready", 13))) {
1396 errno = old_errno;
1397 return 1;
1398 } else {
1399 errno = old_errno;
1400 return 0;
1401 }
1402 }
1403
1404 static int before_syscall(const char *func, const char *file)
1405 {
1406 int old_errno = errno;
1407 int result = 1;
1408 // static sbcontext_t sbcontext;
1409 char *deny = getenv("SANDBOX_DENY");
1410 char *read = getenv("SANDBOX_READ");
1411 char *write = getenv("SANDBOX_WRITE");
1412 char *predict = getenv("SANDBOX_PREDICT");
1413
1414 if (NULL == file || 0 == strlen(file)) {
1415 /* The file/directory does not exist */
1416 errno = ENOENT;
1417 return 0;
1418 }
1419
1420 if(sb_init == 0) {
1421 init_context(&sbcontext);
1422 cached_env_vars = malloc(sizeof(char *)*4);
1423 cached_env_vars[0] = cached_env_vars[1] = cached_env_vars[2] = cached_env_vars[3] = NULL;
1424 sb_init=1;
1425 }
1426
1427 if((deny == NULL && cached_env_vars[0] != deny) || cached_env_vars[0] == NULL ||
1428 strcmp(cached_env_vars[0], deny) != 0) {
1429
1430 clean_env_entries(&(sbcontext.deny_prefixes),
1431 &(sbcontext.num_deny_prefixes));
1432
1433 if(NULL != cached_env_vars[0])
1434 free(cached_env_vars[0]);
1435
1436 if(NULL != deny) {
1437 init_env_entries(&(sbcontext.deny_prefixes),
1438 &(sbcontext.num_deny_prefixes), "SANDBOX_DENY", deny, 1);
1439 cached_env_vars[0] = strdup(deny);
1440 } else {
1441 cached_env_vars[0] = NULL;
1442 }
1443 }
1444
1445 if((read == NULL && cached_env_vars[1] != read) || cached_env_vars[1] == NULL ||
1446 strcmp(cached_env_vars[1], read) != 0) {
1447
1448 clean_env_entries(&(sbcontext.read_prefixes),
1449 &(sbcontext.num_read_prefixes));
1450
1451 if(NULL != cached_env_vars[1])
1452 free(cached_env_vars[1]);
1453
1454 if(NULL != read) {
1455 init_env_entries(&(sbcontext.read_prefixes),
1456 &(sbcontext.num_read_prefixes), "SANDBOX_READ", read, 1);
1457 cached_env_vars[1] = strdup(read);
1458 } else {
1459 cached_env_vars[1] = NULL;
1460 }
1461 }
1462
1463 if((write == NULL && cached_env_vars[2] != write) || cached_env_vars[2] == NULL ||
1464 strcmp(cached_env_vars[2], write) != 0) {
1465
1466 clean_env_entries(&(sbcontext.write_prefixes),
1467 &(sbcontext.num_write_prefixes));
1468
1469 if(NULL != cached_env_vars[2])
1470 free(cached_env_vars[2]);
1471
1472 if(NULL != write) {
1473 init_env_entries(&(sbcontext.write_prefixes),
1474 &(sbcontext.num_write_prefixes), "SANDBOX_WRITE", write, 1);
1475 cached_env_vars[2] = strdup(write);
1476 } else {
1477 cached_env_vars[2] = NULL;
1478 }
1479 }
1480
1481 if((predict == NULL && cached_env_vars[3] != predict) || cached_env_vars[3] == NULL ||
1482 strcmp(cached_env_vars[3], predict) != 0) {
1483
1484 clean_env_entries(&(sbcontext.predict_prefixes),
1485 &(sbcontext.num_predict_prefixes));
1486
1487 if(NULL != cached_env_vars[3])
1488 free(cached_env_vars[3]);
1489
1490 if(NULL != predict) {
1491 init_env_entries(&(sbcontext.predict_prefixes),
1492 &(sbcontext.num_predict_prefixes), "SANDBOX_PREDICT", predict, 1);
1493 cached_env_vars[3] = strdup(predict);
1494 } else {
1495 cached_env_vars[3] = NULL;
1496 }
1497
1498 }
1499
1500 result = check_syscall(&sbcontext, func, file);
1501
1502 errno = old_errno;
1503
1504 if (0 == result) {
1505 errno = EACCES;
1506 }
1507
1508 return result;
1509 }
1510
1511 static int before_syscall_access(const char *func, const char *file, int flags)
1512 {
1513 if (flags & W_OK) {
1514 return before_syscall("access_wr", file);
1515 } else {
1516 return before_syscall("access_rd", file);
1517 }
1518 }
1519
1520 static int before_syscall_open_int(const char *func, const char *file, int flags)
1521 {
1522 if ((flags & O_WRONLY) || (flags & O_RDWR)) {
1523 return before_syscall("open_wr", file);
1524 } else {
1525 return before_syscall("open_rd", file);
1526 }
1527 }
1528
1529 static int before_syscall_open_char(const char *func, const char *file, const char *mode)
1530 {
1531 if (*mode == 'r' && ((strcmp(mode, "r") == 0) ||
1532 /* The strspn accept args are known non-writable modifiers */
1533 (strlen(++mode) == strspn(mode, "xbtmc")))) {
1534 return before_syscall("open_rd", file);
1535 } else {
1536 return before_syscall("open_wr", file);
1537 }
1538 }
1539
1540 #include "getcwd.c"
1541 #include "canonicalize.c"
1542 #include "sandbox_futils.c"
1543
1544 // vim:noexpandtab noai:cindent ai

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20