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

Contents of /trunk/libsandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


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