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

Contents of /trunk/libsandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 54 - (show annotations) (download) (as text)
Thu Apr 28 22:41:57 2005 UTC (13 years, 5 months ago) by azarah
File MIME type: text/x-csrc
File size: 37707 byte(s)
Do not append '/' to pathname in filter_path() if it already ends with it.

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