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

Contents of /trunk/libsandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


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