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

Contents of /trunk/src/libsandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


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