Lines 8-13
Link Here
|
8 |
* |
8 |
* |
9 |
* it's very important that the --enable-static-link option is NOT specified |
9 |
* it's very important that the --enable-static-link option is NOT specified |
10 |
* |
10 |
* |
|
|
11 |
* To use, you need to set environment variables: |
12 |
* SANDBOX_ON If this is set, it turns on sandboxing |
13 |
* SANDBOX_LOG The log file used for reporting violations. |
14 |
* Sandbox writes to stderr if not set. |
15 |
* SANDBOX_DEBUG Turn on sandbox debugging, so you know what it did |
16 |
* SANDBOX_DEBUG_LOG Logfile for debugging, stderr if not set |
17 |
* SANDBOX_TRACE Turn on tracing, listing all interesting files read |
18 |
* SANDBOX_TRACE_LOG Logfile for the above, needs to be set to work |
19 |
* |
20 |
* These take path prefixes separated by ':' : |
21 |
* SANDBOX_DENY Deny access to the listed prefixes |
22 |
* SANDBOX_READ Allow reads from these prefixes. Normally set to "/" |
23 |
* SANDBOX_WRITE Allow write access to these prefixes |
24 |
* SANDBOX_PREDICT Dunno really. Something with error logging. |
25 |
* |
26 |
* Notes: |
27 |
* - the above just do sandboxing, the regular access permissions still apply. |
28 |
* |
29 |
* - sandbox works by messing with libc. If you have applications that call |
30 |
* the kernel directly (like dietlibc?), it won't work. This means that |
31 |
* malicious code could still be executed. Which is why the portage user is |
32 |
* a good idea. |
33 |
* |
34 |
* - using sandbox is faster than something based on ptrace(), which would |
35 |
* not have the above problem. Easily checked by comparing the difference |
36 |
* between |
37 |
* # time FEATURES=-sandbox strace -f -e\!all emerge blabla |
38 |
* and |
39 |
* # time emerge blabla |
40 |
* |
41 |
* - If we want total security, maybe something like the systrace patch |
42 |
* (http://www.systrace.org) would be better, although that only exists |
43 |
* for the Linux kernel. |
44 |
* |
11 |
* Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com |
45 |
* Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com |
12 |
* Distributed under the terms of the GNU General Public License, v2 or later |
46 |
* Distributed under the terms of the GNU General Public License, v2 or later |
13 |
* Author : Geert Bevin <gbevin@uwyn.com> |
47 |
* Author : Geert Bevin <gbevin@uwyn.com> |
Lines 21-26
Link Here
|
21 |
* |
55 |
* |
22 |
* Martin Schlemmer <azarah@gentoo.org> (18 Aug 2002) |
56 |
* Martin Schlemmer <azarah@gentoo.org> (18 Aug 2002) |
23 |
* |
57 |
* |
|
|
58 |
* Added logging for opened files in the forbidden zone, thus knowing |
59 |
* what packages were used, see bug #3141 |
60 |
* |
61 |
* Removed unused write_denied structures |
62 |
* |
63 |
* Added docs for libsandbox |
64 |
* |
65 |
* Wout Mertens <wmertens@gentoo.org> (13 May 2003) |
66 |
* |
24 |
* Partly Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro <p@demauro.net>, |
67 |
* Partly Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro <p@demauro.net>, |
25 |
* as some of the InstallWatch code was used. |
68 |
* as some of the InstallWatch code was used. |
26 |
* |
69 |
* |
Lines 105-112
Link Here
|
105 |
int num_write_prefixes; |
148 |
int num_write_prefixes; |
106 |
char** predict_prefixes; |
149 |
char** predict_prefixes; |
107 |
int num_predict_prefixes; |
150 |
int num_predict_prefixes; |
108 |
char** write_denied_prefixes; |
|
|
109 |
int num_write_denied_prefixes; |
110 |
} sbcontext_t; |
151 |
} sbcontext_t; |
111 |
|
152 |
|
112 |
/* glibc modified realpath() functions */ |
153 |
/* glibc modified realpath() functions */ |
Lines 714-721
Link Here
|
714 |
context->num_write_prefixes = 0; |
755 |
context->num_write_prefixes = 0; |
715 |
context->predict_prefixes = NULL; |
756 |
context->predict_prefixes = NULL; |
716 |
context->num_predict_prefixes = 0; |
757 |
context->num_predict_prefixes = 0; |
717 |
context->write_denied_prefixes = NULL; |
|
|
718 |
context->num_write_denied_prefixes = 0; |
719 |
} |
758 |
} |
720 |
|
759 |
|
721 |
static int is_sandbox_pid() |
760 |
static int is_sandbox_pid() |
Lines 932-948
Link Here
|
932 |
) { |
971 |
) { |
933 |
struct stat tmp_stat; |
972 |
struct stat tmp_stat; |
934 |
|
973 |
|
935 |
for (i = 0; i < sbcontext->num_write_denied_prefixes; i++) { |
|
|
936 |
if (NULL != sbcontext->write_denied_prefixes[i]) { |
937 |
if (0 == strncmp(filtered_path, |
938 |
sbcontext->write_denied_prefixes[i], |
939 |
strlen(sbcontext->write_denied_prefixes[i]))) { |
940 |
result = 0; |
941 |
break; |
942 |
} |
943 |
} |
944 |
} |
945 |
|
946 |
if (-1 == result) { |
974 |
if (-1 == result) { |
947 |
for (i = 0; i < sbcontext->num_write_prefixes; i++) { |
975 |
for (i = 0; i < sbcontext->num_write_prefixes; i++) { |
948 |
if (NULL != sbcontext->write_prefixes[i]) { |
976 |
if (NULL != sbcontext->write_prefixes[i]) { |
Lines 995-1000
Link Here
|
995 |
return result; |
1023 |
return result; |
996 |
} |
1024 |
} |
997 |
|
1025 |
|
|
|
1026 |
/* We define as interesting: */ |
1027 |
/* All files that we don't have write access to and are reading from */ |
1028 |
static int is_interesting(sbcontext_t* sbcontext, const char* func, const char* path) |
1029 |
{ |
1030 |
int result = -1; |
1031 |
int i = 0; |
1032 |
char* filtered_path = filter_path(path); |
1033 |
|
1034 |
if ('/' != filtered_path[0]) { |
1035 |
return 0; |
1036 |
} |
1037 |
|
1038 |
if ((0 == strncmp(filtered_path, "/etc/ld.so.preload", 18)) && (is_sandbox_pid())) { |
1039 |
result = 0; |
1040 |
} |
1041 |
|
1042 |
if (-1 == result) { |
1043 |
/* These are the functions we care about */ |
1044 |
if ((NULL != sbcontext->write_prefixes) && |
1045 |
((0 == strncmp(func, "open_rd", 7)) || |
1046 |
(0 == strncmp(func, "popen", 5)) || |
1047 |
(0 == strncmp(func, "system", 6)) || |
1048 |
(0 == strncmp(func, "execl", 5)) || |
1049 |
(0 == strncmp(func, "execlp", 6)) || |
1050 |
(0 == strncmp(func, "execle", 6)) || |
1051 |
(0 == strncmp(func, "execv", 5)) || |
1052 |
(0 == strncmp(func, "execvp", 6)) || |
1053 |
(0 == strncmp(func, "execve", 6)) |
1054 |
) |
1055 |
) { |
1056 |
/* See if we are allowed to write to it */ |
1057 |
for (i = 0; i < sbcontext->num_write_prefixes; i++) { |
1058 |
if (NULL != sbcontext->write_prefixes[i]) { |
1059 |
if (0 == strncmp(filtered_path, |
1060 |
sbcontext->write_prefixes[i], |
1061 |
strlen(sbcontext->write_prefixes[i]))) { |
1062 |
result = 0; |
1063 |
break; |
1064 |
} |
1065 |
} |
1066 |
} |
1067 |
/* All the rest is interesting */ |
1068 |
if (-1 == result) { |
1069 |
result = 1; |
1070 |
} |
1071 |
} |
1072 |
} |
1073 |
|
1074 |
if (-1 == result) { |
1075 |
result = 0; |
1076 |
} |
1077 |
|
1078 |
if (filtered_path) free(filtered_path); |
1079 |
filtered_path = NULL; |
1080 |
|
1081 |
return result; |
1082 |
} |
1083 |
|
998 |
static int check_syscall(sbcontext_t* sbcontext, const char* func, const char* file) |
1084 |
static int check_syscall(sbcontext_t* sbcontext, const char* func, const char* file) |
999 |
{ |
1085 |
{ |
1000 |
int old_errno = errno; |
1086 |
int old_errno = errno; |
Lines 1008-1013
Link Here
|
1008 |
char* debug_log_env = NULL; |
1094 |
char* debug_log_env = NULL; |
1009 |
char* debug_log_path = NULL; |
1095 |
char* debug_log_path = NULL; |
1010 |
int debug_log_file = 0; |
1096 |
int debug_log_file = 0; |
|
|
1097 |
struct stat trace_log_stat; |
1098 |
char* trace_log_env = NULL; |
1099 |
char* trace_log_path = NULL; |
1100 |
int trace_log_file = 0; |
1011 |
char buffer[512]; |
1101 |
char buffer[512]; |
1012 |
|
1102 |
|
1013 |
init_wrappers(); |
1103 |
init_wrappers(); |
Lines 1027-1032
Link Here
|
1027 |
log_path = getenv("SANDBOX_LOG"); |
1117 |
log_path = getenv("SANDBOX_LOG"); |
1028 |
debug_log_env = getenv("SANDBOX_DEBUG"); |
1118 |
debug_log_env = getenv("SANDBOX_DEBUG"); |
1029 |
debug_log_path = getenv("SANDBOX_DEBUG_LOG"); |
1119 |
debug_log_path = getenv("SANDBOX_DEBUG_LOG"); |
|
|
1120 |
trace_log_env = getenv("SANDBOX_TRACE"); |
1121 |
trace_log_path = getenv("SANDBOX_TRACE_LOG"); |
1030 |
|
1122 |
|
1031 |
if (((NULL == log_path) || |
1123 |
if (((NULL == log_path) || |
1032 |
(0 != strncmp(absolute_path, log_path, strlen(log_path)))) && |
1124 |
(0 != strncmp(absolute_path, log_path, strlen(log_path)))) && |
Lines 1089-1094
Link Here
|
1089 |
} |
1181 |
} |
1090 |
} |
1182 |
} |
1091 |
|
1183 |
|
|
|
1184 |
/* Save the path if tracing and it's interesting enough */ |
1185 |
if ( (NULL != trace_log_env) && |
1186 |
(NULL != trace_log_path) && |
1187 |
(0 != strncmp(absolute_path, trace_log_path, strlen(trace_log_path))) && |
1188 |
is_interesting(sbcontext, func, absolute_path) |
1189 |
) { |
1190 |
sprintf(buffer, "%s\n", absolute_path); |
1191 |
|
1192 |
if ((0 == lstat(trace_log_path, &trace_log_stat)) && |
1193 |
(0 == S_ISREG(trace_log_stat.st_mode)) |
1194 |
) { |
1195 |
fprintf(stderr, |
1196 |
"\e[31;01mSECURITY BREACH\033[0m %s already exists and is not a regular file.\n", |
1197 |
log_path); |
1198 |
} else { |
1199 |
trace_log_file = true_open(trace_log_path, |
1200 |
O_APPEND | O_WRONLY | O_CREAT, |
1201 |
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); |
1202 |
if(trace_log_file >= 0) { |
1203 |
write(trace_log_file, buffer, strlen(buffer)); |
1204 |
close(trace_log_file); |
1205 |
} |
1206 |
} |
1207 |
} |
1208 |
|
1092 |
if (absolute_path) free(absolute_path); |
1209 |
if (absolute_path) free(absolute_path); |
1093 |
absolute_path = NULL; |
1210 |
absolute_path = NULL; |
1094 |
|
1211 |
|