diff options
author | netblue30 <netblue30@yahoo.com> | 2017-10-21 10:30:24 -0400 |
---|---|---|
committer | netblue30 <netblue30@yahoo.com> | 2017-10-21 10:30:24 -0400 |
commit | 955bb591345a688d124b297154d9c1bc2fd05430 (patch) | |
tree | 4fc0882fe98547707b239d94c53d71eb20c21fff /src | |
parent | added whitelist support for /etc (diff) | |
download | firejail-955bb591345a688d124b297154d9c1bc2fd05430.tar.gz firejail-955bb591345a688d124b297154d9c1bc2fd05430.tar.zst firejail-955bb591345a688d124b297154d9c1bc2fd05430.zip |
added whitelisting support for /usr/share
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/firejail.h | 2 | ||||
-rw-r--r-- | src/firejail/fs_whitelist.c | 68 |
2 files changed, 59 insertions, 11 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 387fc441c..008f4ad08 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -82,6 +82,7 @@ | |||
82 | #define RUN_WHITELIST_OPT_DIR "/run/firejail/mnt/orig-opt" | 82 | #define RUN_WHITELIST_OPT_DIR "/run/firejail/mnt/orig-opt" |
83 | #define RUN_WHITELIST_SRV_DIR "/run/firejail/mnt/orig-srv" | 83 | #define RUN_WHITELIST_SRV_DIR "/run/firejail/mnt/orig-srv" |
84 | #define RUN_WHITELIST_ETC_DIR "/run/firejail/mnt/orig-etc" | 84 | #define RUN_WHITELIST_ETC_DIR "/run/firejail/mnt/orig-etc" |
85 | #define RUN_WHITELIST_SHARE_DIR "/run/firejail/mnt/orig-share" | ||
85 | 86 | ||
86 | #define RUN_XAUTHORITY_FILE "/run/firejail/mnt/.Xauthority" | 87 | #define RUN_XAUTHORITY_FILE "/run/firejail/mnt/.Xauthority" |
87 | #define RUN_XAUTHORITY_SEC_FILE "/run/firejail/mnt/sec.Xauthority" | 88 | #define RUN_XAUTHORITY_SEC_FILE "/run/firejail/mnt/sec.Xauthority" |
@@ -200,6 +201,7 @@ typedef struct profile_entry_t { | |||
200 | unsigned opt_dir:1; // whitelist in /opt directory | 201 | unsigned opt_dir:1; // whitelist in /opt directory |
201 | unsigned srv_dir:1; // whitelist in /srv directory | 202 | unsigned srv_dir:1; // whitelist in /srv directory |
202 | unsigned etc_dir:1; // whitelist in /etc directory | 203 | unsigned etc_dir:1; // whitelist in /etc directory |
204 | unsigned share_dir:1; // whitelist in /usr/share directory | ||
203 | }ProfileEntry; | 205 | }ProfileEntry; |
204 | 206 | ||
205 | typedef struct config_t { | 207 | typedef struct config_t { |
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 | ||