diff options
Diffstat (limited to 'src/firejail/fs_whitelist.c')
-rw-r--r-- | src/firejail/fs_whitelist.c | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 0ae5a7155..7928aaf3d 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c | |||
@@ -202,7 +202,7 @@ static void whitelist_path(ProfileEntry *entry) { | |||
202 | errExit("asprintf"); | 202 | errExit("asprintf"); |
203 | } | 203 | } |
204 | else if (entry->tmp_dir) { | 204 | else if (entry->tmp_dir) { |
205 | fname = path + 4; // strlen("/tmp") | 205 | fname = path + 5; // strlen("/tmp/") |
206 | if (*fname == '\0') | 206 | if (*fname == '\0') |
207 | goto errexit; | 207 | goto errexit; |
208 | 208 | ||
@@ -210,7 +210,7 @@ static void whitelist_path(ProfileEntry *entry) { | |||
210 | errExit("asprintf"); | 210 | errExit("asprintf"); |
211 | } | 211 | } |
212 | else if (entry->media_dir) { | 212 | else if (entry->media_dir) { |
213 | fname = path + 6; // strlen("/media") | 213 | fname = path + 7; // strlen("/media/") |
214 | if (*fname == '\0') | 214 | if (*fname == '\0') |
215 | goto errexit; | 215 | goto errexit; |
216 | 216 | ||
@@ -218,7 +218,7 @@ static void whitelist_path(ProfileEntry *entry) { | |||
218 | errExit("asprintf"); | 218 | errExit("asprintf"); |
219 | } | 219 | } |
220 | else if (entry->mnt_dir) { | 220 | else if (entry->mnt_dir) { |
221 | fname = path + 4; // strlen("/mnt") | 221 | fname = path + 5; // strlen("/mnt/") |
222 | if (*fname == '\0') | 222 | if (*fname == '\0') |
223 | goto errexit; | 223 | goto errexit; |
224 | 224 | ||
@@ -226,7 +226,7 @@ static void whitelist_path(ProfileEntry *entry) { | |||
226 | errExit("asprintf"); | 226 | errExit("asprintf"); |
227 | } | 227 | } |
228 | else if (entry->var_dir) { | 228 | else if (entry->var_dir) { |
229 | fname = path + 4; // strlen("/var") | 229 | fname = path + 5; // strlen("/var/") |
230 | if (*fname == '\0') | 230 | if (*fname == '\0') |
231 | goto errexit; | 231 | goto errexit; |
232 | 232 | ||
@@ -234,7 +234,7 @@ static void whitelist_path(ProfileEntry *entry) { | |||
234 | errExit("asprintf"); | 234 | errExit("asprintf"); |
235 | } | 235 | } |
236 | else if (entry->dev_dir) { | 236 | else if (entry->dev_dir) { |
237 | fname = path + 4; // strlen("/dev") | 237 | fname = path + 5; // strlen("/dev/") |
238 | if (*fname == '\0') | 238 | if (*fname == '\0') |
239 | goto errexit; | 239 | goto errexit; |
240 | 240 | ||
@@ -242,7 +242,7 @@ static void whitelist_path(ProfileEntry *entry) { | |||
242 | errExit("asprintf"); | 242 | errExit("asprintf"); |
243 | } | 243 | } |
244 | else if (entry->opt_dir) { | 244 | else if (entry->opt_dir) { |
245 | fname = path + 4; // strlen("/opt") | 245 | fname = path + 5; // strlen("/opt/") |
246 | if (*fname == '\0') | 246 | if (*fname == '\0') |
247 | goto errexit; | 247 | goto errexit; |
248 | 248 | ||
@@ -250,7 +250,7 @@ static void whitelist_path(ProfileEntry *entry) { | |||
250 | errExit("asprintf"); | 250 | errExit("asprintf"); |
251 | } | 251 | } |
252 | else if (entry->srv_dir) { | 252 | else if (entry->srv_dir) { |
253 | fname = path + 4; // strlen("/srv") | 253 | fname = path + 5; // strlen("/srv/") |
254 | if (*fname == '\0') | 254 | if (*fname == '\0') |
255 | goto errexit; | 255 | goto errexit; |
256 | 256 | ||
@@ -258,23 +258,31 @@ static void whitelist_path(ProfileEntry *entry) { | |||
258 | errExit("asprintf"); | 258 | errExit("asprintf"); |
259 | } | 259 | } |
260 | else if (entry->etc_dir) { | 260 | else if (entry->etc_dir) { |
261 | fname = path + 4; // strlen("/etc") | 261 | fname = path + 5; // strlen("/etc/") |
262 | if (*fname == '\0') | 262 | if (*fname == '\0') |
263 | goto errexit; | 263 | goto errexit; |
264 | 264 | ||
265 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_ETC_DIR, fname) == -1) | 265 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_ETC_DIR, fname) == -1) |
266 | errExit("asprintf"); | 266 | errExit("asprintf"); |
267 | } | 267 | } |
268 | else if (entry->share_dir) { | ||
269 | fname = path + 11; // strlen("/usr/share/") | ||
270 | if (*fname == '\0') | ||
271 | goto errexit; | ||
272 | |||
273 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_SHARE_DIR, fname) == -1) | ||
274 | errExit("asprintf"); | ||
275 | } | ||
268 | 276 | ||
269 | // check if the file exists | 277 | // check if the file exists |
278 | assert(wfile); | ||
270 | struct stat s; | 279 | struct stat s; |
271 | if (wfile && stat(wfile, &s) == 0) { | 280 | if (stat(wfile, &s) == 0) { |
272 | if (arg_debug || arg_debug_whitelists) | 281 | if (arg_debug || arg_debug_whitelists) |
273 | printf("Whitelisting %s\n", path); | 282 | printf("Whitelisting %s\n", path); |
274 | } | 283 | } |
275 | else { | 284 | else |
276 | return; | 285 | return; |
277 | } | ||
278 | 286 | ||
279 | // create the path if necessary | 287 | // create the path if necessary |
280 | mkpath(path, s.st_mode); | 288 | mkpath(path, s.st_mode); |
@@ -335,6 +343,7 @@ void fs_whitelist(void) { | |||
335 | int opt_dir = 0; // /opt directory flag | 343 | int opt_dir = 0; // /opt directory flag |
336 | int srv_dir = 0; // /srv directory flag | 344 | int srv_dir = 0; // /srv directory flag |
337 | int etc_dir = 0; // /etc directory flag | 345 | int etc_dir = 0; // /etc directory flag |
346 | int share_dir = 0; // /usr/share directory flag | ||
338 | 347 | ||
339 | size_t nowhitelist_c = 0; | 348 | size_t nowhitelist_c = 0; |
340 | size_t nowhitelist_m = 32; | 349 | size_t nowhitelist_m = 32; |
@@ -426,6 +435,8 @@ void fs_whitelist(void) { | |||
426 | srv_dir = 1; | 435 | srv_dir = 1; |
427 | else if (strncmp(new_name, "/etc/", 5) == 0) | 436 | else if (strncmp(new_name, "/etc/", 5) == 0) |
428 | etc_dir = 1; | 437 | etc_dir = 1; |
438 | else if (strncmp(new_name, "/usr/share/", 11) == 0) | ||
439 | share_dir = 1; | ||
429 | } | 440 | } |
430 | 441 | ||
431 | entry->data = EMPTY_STRING; | 442 | entry->data = EMPTY_STRING; |
@@ -558,6 +569,13 @@ void fs_whitelist(void) { | |||
558 | goto errexit; | 569 | goto errexit; |
559 | } | 570 | } |
560 | } | 571 | } |
572 | else if (strncmp(new_name, "/usr/share/", 11) == 0) { | ||
573 | entry->share_dir = 1; | ||
574 | share_dir = 1; | ||
575 | // both path and absolute path are under /etc | ||
576 | if (strncmp(fname, "/usr/share/", 11) != 0) | ||
577 | goto errexit; | ||
578 | } | ||
561 | else { | 579 | else { |
562 | goto errexit; | 580 | goto errexit; |
563 | } | 581 | } |
@@ -764,6 +782,27 @@ void fs_whitelist(void) { | |||
764 | etc_dir = 0; | 782 | etc_dir = 0; |
765 | } | 783 | } |
766 | 784 | ||
785 | // /usr/share mountpoint | ||
786 | if (share_dir) { | ||
787 | // check if /usr/share directory exists | ||
788 | struct stat s; | ||
789 | if (stat("/usr/share", &s) == 0) { | ||
790 | // keep a copy of real /usr/share directory in RUN_WHITELIST_ETC_DIR | ||
791 | mkdir_attr(RUN_WHITELIST_SHARE_DIR, 0755, 0, 0); | ||
792 | if (mount("/usr/share", RUN_WHITELIST_SHARE_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
793 | errExit("mount bind"); | ||
794 | |||
795 | // mount tmpfs on /srv | ||
796 | if (arg_debug || arg_debug_whitelists) | ||
797 | printf("Mounting tmpfs on /usr/share directory\n"); | ||
798 | if (mount("tmpfs", "/usr/share", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) | ||
799 | errExit("mounting tmpfs on /usr/share"); | ||
800 | fs_logger("tmpfs /usr/share"); | ||
801 | } | ||
802 | else | ||
803 | share_dir = 0; | ||
804 | } | ||
805 | |||
767 | 806 | ||
768 | // go through profile rules again, and interpret whitelist commands | 807 | // go through profile rules again, and interpret whitelist commands |
769 | entry = cfg.profile; | 808 | entry = cfg.profile; |
@@ -870,6 +909,13 @@ void fs_whitelist(void) { | |||
870 | fs_logger2("tmpfs", RUN_WHITELIST_ETC_DIR); | 909 | fs_logger2("tmpfs", RUN_WHITELIST_ETC_DIR); |
871 | } | 910 | } |
872 | 911 | ||
912 | // mask the real /usr/share directory, currently mounted on RUN_WHITELIST_SHARE_DIR | ||
913 | if (share_dir) { | ||
914 | if (mount("tmpfs", RUN_WHITELIST_SHARE_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) | ||
915 | errExit("mount tmpfs"); | ||
916 | fs_logger2("tmpfs", RUN_WHITELIST_SHARE_DIR); | ||
917 | } | ||
918 | |||
873 | if (new_name) | 919 | if (new_name) |
874 | free(new_name); | 920 | free(new_name); |
875 | 921 | ||