Lines 1-5
Link Here
|
1 |
/* |
1 |
/* |
2 |
S * Path sandbox for the gentoo linux portage package system, initially |
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 |
3 |
* based on the ROCK Linux Wrapper for getting a list of created files |
4 |
* |
4 |
* |
5 |
* to integrate with bash, bash should have been built like this |
5 |
* to integrate with bash, bash should have been built like this |
Lines 33-42
Link Here
|
33 |
* This is broken currently. */ |
33 |
* This is broken currently. */ |
34 |
/* #define WRAP_MKNOD */ |
34 |
/* #define WRAP_MKNOD */ |
35 |
|
35 |
|
36 |
/* Uncomment below to enable the use of strtok_r(). */ |
|
|
37 |
#define REENTRANT_STRTOK |
38 |
|
36 |
|
39 |
|
|
|
40 |
#define open xxx_open |
37 |
#define open xxx_open |
41 |
#define open64 xxx_open64 |
38 |
#define open64 xxx_open64 |
42 |
|
39 |
|
Lines 96-112
Link Here
|
96 |
static char sandbox_lib[255]; |
93 |
static char sandbox_lib[255]; |
97 |
|
94 |
|
98 |
typedef struct { |
95 |
typedef struct { |
|
|
96 |
char *last_env; |
97 |
int count; |
98 |
char **strs; |
99 |
} sbprefix_t; |
100 |
|
101 |
typedef struct { |
99 |
int show_access_violation; |
102 |
int show_access_violation; |
100 |
char** deny_prefixes; |
103 |
sbprefix_t deny; |
101 |
int num_deny_prefixes; |
104 |
sbprefix_t read; |
102 |
char** read_prefixes; |
105 |
sbprefix_t write; |
103 |
int num_read_prefixes; |
106 |
sbprefix_t predict; |
104 |
char** write_prefixes; |
|
|
105 |
int num_write_prefixes; |
106 |
char** predict_prefixes; |
107 |
int num_predict_prefixes; |
108 |
char** write_denied_prefixes; |
109 |
int num_write_denied_prefixes; |
110 |
} sbcontext_t; |
107 |
} sbcontext_t; |
111 |
|
108 |
|
112 |
/* glibc modified realpath() functions */ |
109 |
/* glibc modified realpath() functions */ |
Lines 120-128
Link Here
|
120 |
static int before_syscall(const char *, const char *); |
117 |
static int before_syscall(const char *, const char *); |
121 |
static int before_syscall_open_int(const char *, const char *, int); |
118 |
static int before_syscall_open_int(const char *, const char *, int); |
122 |
static int before_syscall_open_char(const char *, const char *, const char *); |
119 |
static int before_syscall_open_char(const char *, const char *, const char *); |
123 |
static void clean_env_entries(char ***, int *); |
120 |
static void clean_env_entries(sbprefix_t *); |
124 |
static void init_context(sbcontext_t *); |
121 |
static void init_context(sbcontext_t *); |
125 |
static void init_env_entries(char ***, int *, char *, int); |
122 |
static void init_env_entries(sbprefix_t *, char *); |
126 |
static char* filter_path(const char*); |
123 |
static char* filter_path(const char*); |
127 |
static int is_sandbox_on(); |
124 |
static int is_sandbox_on(); |
128 |
static int is_sandbox_pid(); |
125 |
static int is_sandbox_pid(); |
Lines 245-251
Link Here
|
245 |
|
242 |
|
246 |
/* If path == NULL, return or we get a segfault */ |
243 |
/* If path == NULL, return or we get a segfault */ |
247 |
if (NULL == path) return; |
244 |
if (NULL == path) return; |
248 |
|
245 |
|
249 |
if(!erealpath(path, resolved_path) && (path[0] != '/')) { |
246 |
if(!erealpath(path, resolved_path) && (path[0] != '/')) { |
250 |
/* The path could not be canonicalized, append it |
247 |
/* The path could not be canonicalized, append it |
251 |
* to the current working directory if it was not |
248 |
* to the current working directory if it was not |
Lines 253-259
Link Here
|
253 |
*/ |
250 |
*/ |
254 |
getcwd(resolved_path, MAXPATHLEN - 2); |
251 |
getcwd(resolved_path, MAXPATHLEN - 2); |
255 |
strcat(resolved_path, "/"); |
252 |
strcat(resolved_path, "/"); |
256 |
strncat(resolved_path, path, MAXPATHLEN - 1); |
253 |
strncat(resolved_path, path, MAXPATHLEN - 1 - strlen(resolved_path)); |
257 |
erealpath(resolved_path, resolved_path); |
254 |
erealpath(resolved_path, resolved_path); |
258 |
} |
255 |
} |
259 |
|
256 |
|
Lines 705-721
Link Here
|
705 |
|
702 |
|
706 |
static void init_context(sbcontext_t* context) |
703 |
static void init_context(sbcontext_t* context) |
707 |
{ |
704 |
{ |
|
|
705 |
memset(context, 0, sizeof(sbcontext_t)); |
708 |
context->show_access_violation = 1; |
706 |
context->show_access_violation = 1; |
709 |
context->deny_prefixes = NULL; |
|
|
710 |
context->num_deny_prefixes = 0; |
711 |
context->read_prefixes = NULL; |
712 |
context->num_read_prefixes = 0; |
713 |
context->write_prefixes = NULL; |
714 |
context->num_write_prefixes = 0; |
715 |
context->predict_prefixes = NULL; |
716 |
context->num_predict_prefixes = 0; |
717 |
context->write_denied_prefixes = NULL; |
718 |
context->num_write_denied_prefixes = 0; |
719 |
} |
707 |
} |
720 |
|
708 |
|
721 |
static int is_sandbox_pid() |
709 |
static int is_sandbox_pid() |
Lines 762-788
Link Here
|
762 |
return result; |
750 |
return result; |
763 |
} |
751 |
} |
764 |
|
752 |
|
765 |
static void clean_env_entries(char*** prefixes_array, int* prefixes_num) |
753 |
static void clean_env_entries(sbprefix_t* prefix) |
766 |
{ |
754 |
{ |
767 |
int old_errno = errno; |
755 |
int old_errno = errno; |
768 |
int i = 0; |
756 |
int i = 0; |
769 |
|
757 |
|
770 |
if (NULL != *prefixes_array) { |
758 |
if (NULL != prefix->strs) { |
771 |
for (i = 0; i < *prefixes_num; i++) { |
759 |
for (i = 0; i < prefix->count; i++) { |
772 |
if (NULL != (*prefixes_array)[i]) { |
760 |
if (NULL != prefix->strs[i]) { |
773 |
free((*prefixes_array)[i]); |
761 |
free(prefix->strs[i]); |
774 |
(*prefixes_array)[i] = NULL; |
762 |
prefix->strs[i] = NULL; |
775 |
} |
763 |
} |
776 |
} |
764 |
} |
777 |
if (*prefixes_array) free(*prefixes_array); |
765 |
free(prefix->strs); |
778 |
*prefixes_array = NULL; |
766 |
prefix->strs = NULL; |
779 |
*prefixes_num = 0; |
767 |
prefix->count = 0; |
|
|
768 |
} |
769 |
if (prefix->last_env) { |
770 |
free(prefix->last_env); |
771 |
prefix->last_env = NULL; |
780 |
} |
772 |
} |
781 |
|
773 |
|
782 |
errno = old_errno; |
774 |
errno = old_errno; |
783 |
} |
775 |
} |
784 |
|
776 |
|
785 |
static void init_env_entries(char*** prefixes_array, int* prefixes_num, char* env, int warn) |
777 |
static void init_env_entries(sbprefix_t* prefix, char* env) |
786 |
{ |
778 |
{ |
787 |
int old_errno = errno; |
779 |
int old_errno = errno; |
788 |
char* prefixes_env = getenv(env); |
780 |
char* prefixes_env = getenv(env); |
Lines 792-842
Link Here
|
792 |
"Sandbox error : the %s environmental variable should be defined.\n", |
784 |
"Sandbox error : the %s environmental variable should be defined.\n", |
793 |
env); |
785 |
env); |
794 |
} else { |
786 |
} else { |
795 |
char* buffer = NULL; |
787 |
char *ptr; |
796 |
int prefixes_env_length = strlen(prefixes_env); |
788 |
int num_colons = 0; |
797 |
int i = 0; |
|
|
798 |
int num_delimiters = 0; |
799 |
char* token = NULL; |
800 |
char* prefix = NULL; |
801 |
|
802 |
for (i = 0; i < prefixes_env_length; i++) { |
803 |
if (':' == prefixes_env[i]) { |
804 |
num_delimiters++; |
805 |
} |
806 |
} |
807 |
|
789 |
|
808 |
if (num_delimiters > 0) { |
790 |
/* Check to see if the env value has changed since the |
809 |
*prefixes_array = (char **)malloc((num_delimiters + 1) * sizeof(char *)); |
791 |
last time this was initalized, don't do the work again |
810 |
buffer = strndupa(prefixes_env, prefixes_env_length); |
792 |
if it hasn't. |
811 |
|
793 |
*/ |
812 |
#ifdef REENTRANT_STRTOK |
794 |
|
813 |
token = strtok_r(buffer, ":", &buffer); |
795 |
if (prefix->last_env && !strcmp(prefix->last_env, prefixes_env)) { |
814 |
#else |
796 |
errno = old_errno; |
815 |
token = strtok(buffer, ":"); |
797 |
return; |
816 |
#endif |
798 |
} |
817 |
|
799 |
|
818 |
while ((NULL != token) && (strlen(token) > 0)) { |
800 |
/* Env value is different, update the cached copy */ |
819 |
prefix = strndup(token, strlen(token)); |
801 |
if (prefix->last_env) { |
820 |
(*prefixes_array)[(*prefixes_num)++] = filter_path(prefix); |
802 |
free(prefix->last_env); |
821 |
|
803 |
prefix->last_env = NULL; |
822 |
#ifdef REENTRANT_STRTOK |
804 |
} |
823 |
token = strtok_r(NULL, ":", &buffer); |
805 |
prefix->last_env = strdup(prefixes_env); |
824 |
#else |
|
|
825 |
token = strtok(NULL, ":"); |
826 |
#endif |
827 |
|
806 |
|
828 |
if (prefix) free(prefix); |
807 |
ptr = prefixes_env; |
829 |
prefix = NULL; |
808 |
while (*ptr) { |
830 |
} |
809 |
if (*ptr++ == ':') ++num_colons; |
831 |
} |
810 |
} |
832 |
else if (prefixes_env_length > 0) { |
811 |
|
833 |
(*prefixes_array) = (char **)malloc(sizeof(char *)); |
812 |
if (prefix->strs) { |
834 |
|
813 |
free(prefix->strs); |
835 |
prefix = strndupa(prefixes_env, prefixes_env_length); |
814 |
prefix->strs = 0; |
836 |
(*prefixes_array)[(*prefixes_num)++] = filter_path(prefix); |
815 |
} |
837 |
} |
816 |
prefix->strs = (char**)malloc((num_colons+1) * sizeof(char*)); |
838 |
} |
817 |
if (!prefix->strs) return; |
|
|
818 |
memset(prefix->strs, 0, (num_colons+1) * sizeof(char*)); |
819 |
prefix->count = 0; |
820 |
|
821 |
ptr = prefixes_env; |
822 |
while (*ptr) { |
823 |
char *next_colon = strchr(ptr, ':'); |
824 |
if (next_colon) { |
825 |
if (next_colon != ptr) { |
826 |
char *str = strndup(ptr, next_colon-ptr); |
827 |
if (!str) return; |
828 |
prefix->strs[prefix->count++] = filter_path(str); |
829 |
free(str); |
830 |
} |
831 |
} else { |
832 |
prefix->strs[prefix->count++] = filter_path(ptr); |
833 |
break; |
834 |
} |
839 |
|
835 |
|
|
|
836 |
ptr = next_colon+1; |
837 |
} |
838 |
} |
840 |
errno = old_errno; |
839 |
errno = old_errno; |
841 |
} |
840 |
} |
842 |
|
841 |
|
Lines 844-849
Link Here
|
844 |
{ |
843 |
{ |
845 |
int old_errno = errno; |
844 |
int old_errno = errno; |
846 |
char* filtered_path = (char *)malloc(MAXPATHLEN * sizeof(char)); |
845 |
char* filtered_path = (char *)malloc(MAXPATHLEN * sizeof(char)); |
|
|
846 |
filtered_path[0] = 0; |
847 |
|
847 |
|
848 |
canonicalize(path, filtered_path); |
848 |
canonicalize(path, filtered_path); |
849 |
|
849 |
|
Lines 859-865
Link Here
|
859 |
int i = 0; |
859 |
int i = 0; |
860 |
char* filtered_path = filter_path(path); |
860 |
char* filtered_path = filter_path(path); |
861 |
|
861 |
|
|
|
862 |
if (!filtered_path) { |
863 |
errno = old_errno; |
864 |
return 0; |
865 |
} |
866 |
|
862 |
if ('/' != filtered_path[0]) { |
867 |
if ('/' != filtered_path[0]) { |
|
|
868 |
free(filtered_path); |
863 |
errno = old_errno; |
869 |
errno = old_errno; |
864 |
return 0; |
870 |
return 0; |
865 |
} |
871 |
} |
Lines 869-880
Link Here
|
869 |
} |
875 |
} |
870 |
|
876 |
|
871 |
if (-1 == result) { |
877 |
if (-1 == result) { |
872 |
if (NULL != sbcontext->deny_prefixes) { |
878 |
if (NULL != sbcontext->deny.strs) { |
873 |
for (i = 0; i < sbcontext->num_deny_prefixes; i++) { |
879 |
for (i = 0; i < sbcontext->deny.count; i++) { |
874 |
if (NULL != sbcontext->deny_prefixes[i]) { |
880 |
if (NULL != sbcontext->deny.strs[i]) { |
875 |
if (0 == strncmp(filtered_path, |
881 |
if (0 == strncmp(filtered_path, |
876 |
sbcontext->deny_prefixes[i], |
882 |
sbcontext->deny.strs[i], |
877 |
strlen(sbcontext->deny_prefixes[i]))) { |
883 |
strlen(sbcontext->deny.strs[i]))) { |
878 |
result = 0; |
884 |
result = 0; |
879 |
break; |
885 |
break; |
880 |
} |
886 |
} |
Lines 883-889
Link Here
|
883 |
} |
889 |
} |
884 |
|
890 |
|
885 |
if (-1 == result) { |
891 |
if (-1 == result) { |
886 |
if ((NULL != sbcontext->read_prefixes) && |
892 |
if ((NULL != sbcontext->read.strs) && |
887 |
((0 == strncmp(func, "open_rd", 7)) || |
893 |
((0 == strncmp(func, "open_rd", 7)) || |
888 |
(0 == strncmp(func, "popen", 5)) || |
894 |
(0 == strncmp(func, "popen", 5)) || |
889 |
(0 == strncmp(func, "opendir", 7)) || |
895 |
(0 == strncmp(func, "opendir", 7)) || |
Lines 896-913
Link Here
|
896 |
(0 == strncmp(func, "execve", 6)) |
902 |
(0 == strncmp(func, "execve", 6)) |
897 |
) |
903 |
) |
898 |
) { |
904 |
) { |
899 |
for (i = 0; i < sbcontext->num_read_prefixes; i++) { |
905 |
for (i = 0; i < sbcontext->read.count; i++) { |
900 |
if (NULL != sbcontext->read_prefixes[i]) { |
906 |
if (NULL != sbcontext->read.strs[i]) { |
901 |
if (0 == strncmp(filtered_path, |
907 |
if (0 == strncmp(filtered_path, |
902 |
sbcontext->read_prefixes[i], |
908 |
sbcontext->read.strs[i], |
903 |
strlen(sbcontext->read_prefixes[i]))) { |
909 |
strlen(sbcontext->read.strs[i]))) { |
904 |
result = 1; |
910 |
result = 1; |
905 |
break; |
911 |
break; |
906 |
} |
912 |
} |
907 |
} |
913 |
} |
908 |
} |
914 |
} |
909 |
} |
915 |
} |
910 |
else if ((NULL != sbcontext->write_prefixes) && |
916 |
else if ((NULL != sbcontext->write.strs) && |
911 |
((0 == strncmp(func, "open_wr", 7)) || |
917 |
((0 == strncmp(func, "open_wr", 7)) || |
912 |
(0 == strncmp(func, "creat", 5)) || |
918 |
(0 == strncmp(func, "creat", 5)) || |
913 |
(0 == strncmp(func, "creat64", 7)) || |
919 |
(0 == strncmp(func, "creat64", 7)) || |
Lines 932-954
Link Here
|
932 |
) { |
938 |
) { |
933 |
struct stat tmp_stat; |
939 |
struct stat tmp_stat; |
934 |
|
940 |
|
935 |
for (i = 0; i < sbcontext->num_write_denied_prefixes; i++) { |
941 |
#if 0 // write_denied is never set |
936 |
if (NULL != sbcontext->write_denied_prefixes[i]) { |
942 |
|
|
|
943 |
for (i = 0; i < sbcontext->write_denied.count; i++) { |
944 |
if (NULL != sbcontext->write_denied.strs[i]) { |
937 |
if (0 == strncmp(filtered_path, |
945 |
if (0 == strncmp(filtered_path, |
938 |
sbcontext->write_denied_prefixes[i], |
946 |
sbcontext->write_denied.strs[i], |
939 |
strlen(sbcontext->write_denied_prefixes[i]))) { |
947 |
strlen(sbcontext->write_denied.strs[i]))) { |
940 |
result = 0; |
948 |
result = 0; |
941 |
break; |
949 |
break; |
942 |
} |
950 |
} |
943 |
} |
951 |
} |
944 |
} |
952 |
} |
|
|
953 |
#endif |
945 |
|
954 |
|
946 |
if (-1 == result) { |
955 |
if (-1 == result) { |
947 |
for (i = 0; i < sbcontext->num_write_prefixes; i++) { |
956 |
for (i = 0; i < sbcontext->write.count; i++) { |
948 |
if (NULL != sbcontext->write_prefixes[i]) { |
957 |
if (NULL != sbcontext->write.strs[i]) { |
949 |
if (0 == strncmp(filtered_path, |
958 |
if (0 == strncmp(filtered_path, |
950 |
sbcontext->write_prefixes[i], |
959 |
sbcontext->write.strs[i], |
951 |
strlen(sbcontext->write_prefixes[i]))) { |
960 |
strlen(sbcontext->write.strs[i]))) { |
952 |
result = 1; |
961 |
result = 1; |
953 |
break; |
962 |
break; |
954 |
} |
963 |
} |
Lines 965-975
Link Here
|
965 |
} |
974 |
} |
966 |
|
975 |
|
967 |
if (-1 == result) { |
976 |
if (-1 == result) { |
968 |
for (i = 0; i < sbcontext->num_predict_prefixes; i++) { |
977 |
for (i = 0; i < sbcontext->predict.count; i++) { |
969 |
if (NULL != sbcontext->predict_prefixes[i]) { |
978 |
if (NULL != sbcontext->predict.strs[i]) { |
970 |
if (0 == strncmp(filtered_path, |
979 |
if (0 == strncmp(filtered_path, |
971 |
sbcontext->predict_prefixes[i], |
980 |
sbcontext->predict.strs[i], |
972 |
strlen(sbcontext->predict_prefixes[i]))) { |
981 |
strlen(sbcontext->predict.strs[i]))) { |
973 |
sbcontext->show_access_violation = 0; |
982 |
sbcontext->show_access_violation = 0; |
974 |
result = 0; |
983 |
result = 0; |
975 |
break; |
984 |
break; |
Lines 1128-1160
Link Here
|
1128 |
{ |
1137 |
{ |
1129 |
int old_errno = errno; |
1138 |
int old_errno = errno; |
1130 |
int result = 1; |
1139 |
int result = 1; |
1131 |
sbcontext_t sbcontext; |
1140 |
static sbcontext_t* sbcontext = NULL; |
1132 |
|
1141 |
|
1133 |
init_context(&sbcontext); |
1142 |
if (!sbcontext) { |
|
|
1143 |
sbcontext = (sbcontext_t*)malloc(sizeof(sbcontext_t)); |
1144 |
init_context(sbcontext); |
1145 |
} else { |
1146 |
/* sometimes this value gets set to 0 */ |
1147 |
sbcontext->show_access_violation = 1; |
1148 |
} |
1134 |
|
1149 |
|
1135 |
init_env_entries(&(sbcontext.deny_prefixes), |
1150 |
init_env_entries(&sbcontext->deny, "SANDBOX_DENY"); |
1136 |
&(sbcontext.num_deny_prefixes), |
1151 |
init_env_entries(&sbcontext->read, "SANDBOX_READ"); |
1137 |
"SANDBOX_DENY", 1); |
1152 |
init_env_entries(&sbcontext->write, "SANDBOX_WRITE"); |
1138 |
init_env_entries(&(sbcontext.read_prefixes), |
1153 |
init_env_entries(&sbcontext->predict, "SANDBOX_PREDICT"); |
1139 |
&(sbcontext.num_read_prefixes), |
1154 |
|
1140 |
"SANDBOX_READ", 1); |
1155 |
result = check_syscall(sbcontext, func, file); |
1141 |
init_env_entries(&(sbcontext.write_prefixes), |
1156 |
|
1142 |
&(sbcontext.num_write_prefixes), |
1157 |
/* don't clean now, the sbcontext is cached |
1143 |
"SANDBOX_WRITE", 1); |
1158 |
clean_env_entries(&sbcontext.deny); |
1144 |
init_env_entries(&(sbcontext.predict_prefixes), |
1159 |
clean_env_entries(&sbcontext.read); |
1145 |
&(sbcontext.num_predict_prefixes), |
1160 |
clean_env_entries(&sbcontext.write); |
1146 |
"SANDBOX_PREDICT", 1); |
1161 |
clean_env_entries(&sbcontext.predict); |
1147 |
|
1162 |
*/ |
1148 |
result = check_syscall(&sbcontext, func, file); |
|
|
1149 |
|
1150 |
clean_env_entries(&(sbcontext.deny_prefixes), |
1151 |
&(sbcontext.num_deny_prefixes)); |
1152 |
clean_env_entries(&(sbcontext.read_prefixes), |
1153 |
&(sbcontext.num_read_prefixes)); |
1154 |
clean_env_entries(&(sbcontext.write_prefixes), |
1155 |
&(sbcontext.num_write_prefixes)); |
1156 |
clean_env_entries(&(sbcontext.predict_prefixes), |
1157 |
&(sbcontext.num_predict_prefixes)); |
1158 |
|
1163 |
|
1159 |
errno = old_errno; |
1164 |
errno = old_errno; |
1160 |
|
1165 |
|