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

Contents of /trunk/libsandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 76 - (show annotations) (download) (as text)
Sun May 8 11:27:37 2005 UTC (9 years, 7 months ago) by ferringb
File MIME type: text/x-csrc
File size: 39826 byte(s)
rewrote sbcontext caching so it accounts for env changes since lib initialization.

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