diff options
-rw-r--r-- | src/firejail/fs_lib.c | 73 | ||||
-rw-r--r-- | src/fldd/main.c | 7 |
2 files changed, 55 insertions, 25 deletions
diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c index 94d87a151..890f8daf9 100644 --- a/src/firejail/fs_lib.c +++ b/src/firejail/fs_lib.c | |||
@@ -34,29 +34,26 @@ static const char * const lib_paths[] = { | |||
34 | NULL | 34 | NULL |
35 | }; // Note: this array is duplicated in src/fldd/main.c | 35 | }; // Note: this array is duplicated in src/fldd/main.c |
36 | 36 | ||
37 | static void copy_libs(const char *exe, const char *dir, const char *file); | ||
38 | |||
39 | static void duplicate(const char *fname, const char *private_run_dir) { | 37 | static void duplicate(const char *fname, const char *private_run_dir) { |
40 | if (arg_debug) | 38 | if (arg_debug) |
41 | printf("copying %s to private %s\n", fname, private_run_dir); | 39 | printf("copying %s to private %s\n", fname, private_run_dir); |
42 | sbox_run(SBOX_ROOT| SBOX_SECCOMP, 4, PATH_FCOPY, "--follow-link", fname, private_run_dir); | 40 | |
41 | // copy only root-owned files | ||
42 | struct stat s; | ||
43 | if (stat(fname, &s) == 0 && s.st_uid == 0) | ||
44 | sbox_run(SBOX_ROOT| SBOX_SECCOMP, 4, PATH_FCOPY, "--follow-link", fname, private_run_dir); | ||
43 | } | 45 | } |
44 | 46 | ||
45 | 47 | ||
46 | // requires full path for exe | 48 | // requires full path for lib |
47 | static void copy_exe(const char *exe, const char *dir, const char *file) { | 49 | static void copy_libs(const char *lib, const char *private_run_dir, const char *output_file) { |
48 | // if exe does not exist or the user does not have read access to it | 50 | // if library/executable does not exist or the user does not have read access to it |
49 | // print a warning and exit the function. | 51 | // print a warning and exit the function. |
50 | if (access(exe, R_OK)) { | 52 | if (access(lib, R_OK)) { |
51 | fwarning("cannot find %s executable for private-lib, skipping...\n", exe); | 53 | fwarning("cannot find %s for private-lib, skipping...\n", lib); |
52 | return; | 54 | return; |
53 | } | 55 | } |
54 | 56 | ||
55 | copy_libs(exe, dir, file); | ||
56 | } | ||
57 | |||
58 | // requires full path for lib | ||
59 | static void copy_libs(const char *lib, const char *dir, const char *output_file) { | ||
60 | // create an empty RUN_LIB_FILE and allow the user to write to it | 57 | // create an empty RUN_LIB_FILE and allow the user to write to it |
61 | unlink(output_file); // in case is there | 58 | unlink(output_file); // in case is there |
62 | create_empty_file_as_root(output_file, 0644); | 59 | create_empty_file_as_root(output_file, 0644); |
@@ -78,13 +75,35 @@ static void copy_libs(const char *lib, const char *dir, const char *output_file) | |||
78 | char *ptr = strchr(buf, '\n'); | 75 | char *ptr = strchr(buf, '\n'); |
79 | if (ptr) | 76 | if (ptr) |
80 | *ptr = '\0'; | 77 | *ptr = '\0'; |
81 | duplicate(buf, dir); | 78 | duplicate(buf, private_run_dir); |
82 | } | 79 | } |
83 | fclose(fp); | 80 | fclose(fp); |
84 | } | 81 | } |
85 | 82 | ||
83 | static void copy_directory(const char *full_path, const char *dir_name, const char *private_run_dir) { | ||
84 | char *dest; | ||
85 | if (asprintf(&dest, "%s/%s", private_run_dir, dir_name) == -1) | ||
86 | errExit("asprintf"); | ||
87 | |||
88 | // do nothing if the directory is already there | ||
89 | struct stat s; | ||
90 | if (stat(dest, &s) == 0) { | ||
91 | free(dest); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | // create new directory and mount the original on top of it | ||
96 | mkdir_attr(dest, 0755, 0, 0); | ||
97 | |||
98 | if (mount(full_path, dest, NULL, MS_BIND|MS_REC, NULL) < 0 || | ||
99 | mount(NULL, dest, NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0) | ||
100 | errExit("mount bind"); | ||
101 | fs_logger2("mount", full_path); | ||
102 | free(dest); | ||
103 | } | ||
104 | |||
86 | // return 1 if the file is valid | 105 | // return 1 if the file is valid |
87 | static char *valid_library(const char *lib) { | 106 | static char *valid_file(const char *lib) { |
88 | // filename check | 107 | // filename check |
89 | int len = strlen(lib); | 108 | int len = strlen(lib); |
90 | if (strcspn(lib, "\\&!?\"'<>%^(){}[];,*") != (size_t)len || | 109 | if (strcspn(lib, "\\&!?\"'<>%^(){}[];,*") != (size_t)len || |
@@ -135,11 +154,11 @@ void fs_private_lib(void) { | |||
135 | 154 | ||
136 | // copy the libs in the new lib directory for the main exe | 155 | // copy the libs in the new lib directory for the main exe |
137 | if (cfg.original_program_index > 0) | 156 | if (cfg.original_program_index > 0) |
138 | copy_exe(cfg.original_argv[cfg.original_program_index], RUN_LIB_DIR, RUN_LIB_FILE); | 157 | copy_libs(cfg.original_argv[cfg.original_program_index], RUN_LIB_DIR, RUN_LIB_FILE); |
139 | 158 | ||
140 | // for the shell | 159 | // for the shell |
141 | if (!arg_shell_none) { | 160 | if (!arg_shell_none) { |
142 | copy_exe(cfg.shell, RUN_LIB_DIR, RUN_LIB_FILE); | 161 | copy_libs(cfg.shell, RUN_LIB_DIR, RUN_LIB_FILE); |
143 | // a shell is useless without ls command | 162 | // a shell is useless without ls command |
144 | copy_libs("/bin/ls", RUN_LIB_DIR, RUN_LIB_FILE); | 163 | copy_libs("/bin/ls", RUN_LIB_DIR, RUN_LIB_FILE); |
145 | } | 164 | } |
@@ -154,18 +173,26 @@ void fs_private_lib(void) { | |||
154 | errExit("strdup"); | 173 | errExit("strdup"); |
155 | 174 | ||
156 | char *ptr = strtok(dlist, ","); | 175 | char *ptr = strtok(dlist, ","); |
157 | char *lib = valid_library(ptr); | 176 | char *lib = valid_file(ptr); |
158 | if (lib) { | 177 | if (lib) { |
159 | duplicate(lib, RUN_LIB_DIR); | 178 | if (is_dir(lib)) |
160 | copy_libs(lib, RUN_LIB_DIR, RUN_LIB_FILE); | 179 | copy_directory(lib, ptr, RUN_LIB_DIR); |
180 | else { | ||
181 | duplicate(lib, RUN_LIB_DIR); | ||
182 | copy_libs(lib, RUN_LIB_DIR, RUN_LIB_FILE); | ||
183 | } | ||
161 | free(lib); | 184 | free(lib); |
162 | } | 185 | } |
163 | 186 | ||
164 | while ((ptr = strtok(NULL, ",")) != NULL) { | 187 | while ((ptr = strtok(NULL, ",")) != NULL) { |
165 | lib = valid_library(ptr); | 188 | lib = valid_file(ptr); |
166 | if (lib) { | 189 | if (lib) { |
167 | duplicate(lib, RUN_LIB_DIR); | 190 | if (is_dir(lib)) |
168 | copy_libs(lib, RUN_LIB_DIR, RUN_LIB_FILE); | 191 | copy_directory(lib, ptr, RUN_LIB_DIR); |
192 | else { | ||
193 | duplicate(lib, RUN_LIB_DIR); | ||
194 | copy_libs(lib, RUN_LIB_DIR, RUN_LIB_FILE); | ||
195 | } | ||
169 | free(lib); | 196 | free(lib); |
170 | } | 197 | } |
171 | } | 198 | } |
diff --git a/src/fldd/main.c b/src/fldd/main.c index 8b54242a4..1c6b3dd25 100644 --- a/src/fldd/main.c +++ b/src/fldd/main.c | |||
@@ -105,7 +105,7 @@ static void copy_libs_for_exe(const char *exe) { | |||
105 | f = open(exe, O_RDONLY); | 105 | f = open(exe, O_RDONLY); |
106 | if (f < 0) { | 106 | if (f < 0) { |
107 | if (!arg_quiet) | 107 | if (!arg_quiet) |
108 | fprintf(stderr, "Warning fldd: cannot open %s\n", exe); | 108 | fprintf(stderr, "Warning fldd: cannot open %s, skipping...\n", exe); |
109 | return; | 109 | return; |
110 | } | 110 | } |
111 | 111 | ||
@@ -202,7 +202,10 @@ static void copy_libs_for_lib(const char *lib) { | |||
202 | } | 202 | } |
203 | free(fname); | 203 | free(fname); |
204 | } | 204 | } |
205 | errExit("library not found"); | 205 | |
206 | // log a warning and continue | ||
207 | if (!arg_quiet) | ||
208 | fprintf(stderr, "Warning fldd: cannot find %s, skipping...\n", lib); | ||
206 | } | 209 | } |
207 | 210 | ||
208 | static void usage(void) { | 211 | static void usage(void) { |