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

Contents of /trunk/libsandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 170 - (show annotations) (download) (as text)
Tue Nov 1 16:02:30 2005 UTC (8 years, 10 months ago) by azarah
File MIME type: text/x-csrc
File size: 37487 byte(s)
Do not pass mode to true_open and true_open64 if not needed.  Should fix a
segfault in some cases.

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