aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/firejail/fs_home.c1
-rw-r--r--src/firejail/fs_whitelist.c40
-rw-r--r--src/firejail/usage.c1
-rw-r--r--src/firejail/x11.c19
-rw-r--r--src/man/firejail.txt8
-rw-r--r--src/profstats/main.c24
6 files changed, 79 insertions, 14 deletions
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index bec22e5a6..dbc74bfff 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -20,7 +20,6 @@
20#include "firejail.h" 20#include "firejail.h"
21#include <sys/mount.h> 21#include <sys/mount.h>
22#include <linux/limits.h> 22#include <linux/limits.h>
23#include <glob.h>
24#include <dirent.h> 23#include <dirent.h>
25#include <errno.h> 24#include <errno.h>
26#include <sys/stat.h> 25#include <sys/stat.h>
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c
index c5b066b12..3f3075570 100644
--- a/src/firejail/fs_whitelist.c
+++ b/src/firejail/fs_whitelist.c
@@ -346,6 +346,39 @@ static void whitelist_home(int topdir) {
346} 346}
347 347
348 348
349static void globbing(const char *pattern) {
350 assert(pattern);
351
352 // globbing
353 glob_t globbuf;
354 int globerr = glob(pattern, GLOB_NOCHECK | GLOB_NOSORT | GLOB_PERIOD, NULL, &globbuf);
355 if (globerr) {
356 fprintf(stderr, "Error: failed to glob private-bin pattern %s\n", pattern);
357 exit(1);
358 }
359
360 size_t i;
361 for (i = 0; i < globbuf.gl_pathc; i++) {
362 assert(globbuf.gl_pathv[i]);
363 // testing for GLOB_NOCHECK - no pattern matched returns the original pattern
364 if (strcmp(globbuf.gl_pathv[i], pattern) == 0)
365 continue;
366
367 // build the new profile command
368 char *newcmd;
369 if (asprintf(&newcmd, "whitelist %s", globbuf.gl_pathv[i]) == -1)
370 errExit("asprintf");
371
372 // add the new profile command at the end of the list
373 if (arg_debug || arg_debug_whitelists)
374 printf("Adding new profile command: %s\n", newcmd);
375 profile_add(newcmd);
376 }
377
378 globfree(&globbuf);
379}
380
381
349void fs_whitelist(void) { 382void fs_whitelist(void) {
350 ProfileEntry *entry = cfg.profile; 383 ProfileEntry *entry = cfg.profile;
351 if (!entry) 384 if (!entry)
@@ -444,6 +477,13 @@ void fs_whitelist(void) {
444 else 477 else
445 fname = realpath(new_name, NULL); 478 fname = realpath(new_name, NULL);
446 479
480 // if this is not a real path, let's try globbing
481 // mark this entry as EMPTY_STRING and push the new paths at the end of profile entry list
482 // the new profile entries will be processed in this loop
483 // currently there is no globbing support for nowhitelist
484 if (!fname && !nowhitelist_flag)
485 globbing(new_name);
486
447 if (!fname) { 487 if (!fname) {
448 // file not found, blank the entry in the list and continue 488 // file not found, blank the entry in the list and continue
449 if (arg_debug || arg_debug_whitelists) { 489 if (arg_debug || arg_debug_whitelists) {
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index c98ad3620..77bfea8c6 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -208,6 +208,7 @@ static char *usage_str =
208 "\twhitelist the syscalls specified by the command.\n" 208 "\twhitelist the syscalls specified by the command.\n"
209 " --seccomp.print=name|pid - print the seccomp filter for the sandbox\n" 209 " --seccomp.print=name|pid - print the seccomp filter for the sandbox\n"
210 "\tidentified by name or PID.\n" 210 "\tidentified by name or PID.\n"
211 " --seccomp.32[.drop,.keep][=syscall] - like above but for 32 bit architecture.\n"
211#endif 212#endif
212 " --shell=none - run the program directly without a user shell.\n" 213 " --shell=none - run the program directly without a user shell.\n"
213 " --shell=program - set default user shell.\n" 214 " --shell=program - set default user shell.\n"
diff --git a/src/firejail/x11.c b/src/firejail/x11.c
index 74de24b47..98ac184d9 100644
--- a/src/firejail/x11.c
+++ b/src/firejail/x11.c
@@ -1235,16 +1235,15 @@ void x11_xorg(void) {
1235 1235
1236 // move the temporary file in RUN_XAUTHORITY_SEC_FILE in order to have it deleted 1236 // move the temporary file in RUN_XAUTHORITY_SEC_FILE in order to have it deleted
1237 // automatically when the sandbox is closed (rename doesn't work) 1237 // automatically when the sandbox is closed (rename doesn't work)
1238 // root needed 1238 if (arg_debug)
1239 if (copy_file(tmpfname, RUN_XAUTHORITY_SEC_FILE, getuid(), getgid(), 0600)) { 1239 printf("Copying the new .Xauthority file\n");
1240 fprintf(stderr, "Error: cannot create the new .Xauthority file\n"); 1240 copy_file_from_user_to_root(tmpfname, RUN_XAUTHORITY_SEC_FILE, getuid(), getgid(), 0600);
1241 exit(1); 1241
1242 }
1243 /* coverity[toctou] */ 1242 /* coverity[toctou] */
1244 unlink(tmpfname); 1243 unlink(tmpfname);
1245 umount("/tmp"); 1244 umount("/tmp");
1246 1245
1247 // remount RUN_XAUTHORITY_SEC_FILE noexec, nodev, nosuid 1246 // mount RUN_XAUTHORITY_SEC_FILE noexec, nodev, nosuid
1248 fs_remount(RUN_XAUTHORITY_SEC_FILE, MOUNT_NOEXEC, 0); 1247 fs_remount(RUN_XAUTHORITY_SEC_FILE, MOUNT_NOEXEC, 0);
1249 1248
1250 // Ensure there is already a file in the usual location, so that bind-mount below will work. 1249 // Ensure there is already a file in the usual location, so that bind-mount below will work.
@@ -1354,19 +1353,17 @@ void fs_x11(void) {
1354 if (mount("/tmp/.X11-unix", RUN_WHITELIST_X11_DIR, 0, MS_BIND|MS_REC, 0) < 0) 1353 if (mount("/tmp/.X11-unix", RUN_WHITELIST_X11_DIR, 0, MS_BIND|MS_REC, 0) < 0)
1355 errExit("mount bind"); 1354 errExit("mount bind");
1356 1355
1357 // This directory must be mode 1777, or Xlib will barf. 1356 // This directory must be mode 1777
1358 if (mount("tmpfs", "/tmp/.X11-unix", "tmpfs", 1357 if (mount("tmpfs", "/tmp/.X11-unix", "tmpfs",
1359 MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, 1358 MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME,
1360 "mode=1777,uid=0,gid=0") < 0) 1359 "mode=1777,uid=0,gid=0") < 0)
1361 errExit("mounting tmpfs on /tmp/.X11-unix"); 1360 errExit("mounting tmpfs on /tmp/.X11-unix");
1362 fs_logger("tmpfs /tmp/.X11-unix"); 1361 fs_logger("tmpfs /tmp/.X11-unix");
1363 1362
1364 // create an empty file which will have the desired socket bind-mounted over it 1363 // create an empty root-owned file which will have the desired socket bind-mounted over it
1365 int fd = open(x11file, O_RDWR|O_CREAT|O_EXCL, x11stat.st_mode & ~S_IFMT); 1364 int fd = open(x11file, O_RDONLY|O_CREAT|O_EXCL, S_IRUSR | S_IWUSR);
1366 if (fd < 0) 1365 if (fd < 0)
1367 errExit(x11file); 1366 errExit(x11file);
1368 if (fchown(fd, x11stat.st_uid, x11stat.st_gid))
1369 errExit("fchown");
1370 close(fd); 1367 close(fd);
1371 1368
1372 // the mount source is under control of the user, so be careful and 1369 // the mount source is under control of the user, so be careful and
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 13dcf09ee..1bed40015 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -2346,6 +2346,10 @@ the same top directory. For user home, both the link and the real file should be
2346.br 2346.br
2347 2347
2348.br 2348.br
2349File globbing is supported, see \fBFILE GLOBBING\fR section for more details.
2350.br
2351
2352.br
2349Example: 2353Example:
2350.br 2354.br
2351$ firejail \-\-noprofile \-\-whitelist=~/.mozilla 2355$ firejail \-\-noprofile \-\-whitelist=~/.mozilla
@@ -2353,6 +2357,8 @@ $ firejail \-\-noprofile \-\-whitelist=~/.mozilla
2353$ firejail \-\-whitelist=/tmp/.X11-unix --whitelist=/dev/null 2357$ firejail \-\-whitelist=/tmp/.X11-unix --whitelist=/dev/null
2354.br 2358.br
2355$ firejail "\-\-whitelist=/home/username/My Virtual Machines" 2359$ firejail "\-\-whitelist=/home/username/My Virtual Machines"
2360.br
2361$ firejail \-\-whitelist=~/work* \-\-whitelist=/var/backups*
2356 2362
2357.TP 2363.TP
2358\fB\-\-writable-etc 2364\fB\-\-writable-etc
@@ -2722,7 +2728,7 @@ The globbing feature is implemented using glibc glob command. For more informati
2722 2728
2723.br 2729.br
2724.TP 2730.TP
2725The following command line options are supported: \-\-blacklist, \-\-private-bin, \-\-noexec, \-\-read-only, \-\-read-write, and \-\-tmpfs. 2731The following command line options are supported: \-\-blacklist, \-\-private-bin, \-\-noexec, \-\-read-only, \-\-read-write, \-\-tmpfs, and \-\-whitelist.
2726.br 2732.br
2727 2733
2728.br 2734.br
diff --git a/src/profstats/main.c b/src/profstats/main.c
index 76b90f01b..f8818982f 100644
--- a/src/profstats/main.c
+++ b/src/profstats/main.c
@@ -35,6 +35,8 @@ static int cnt_noexec = 0; // include disable-exec.inc
35static int cnt_privatedev = 0; 35static int cnt_privatedev = 0;
36static int cnt_privatetmp = 0; 36static int cnt_privatetmp = 0;
37static int cnt_whitelistvar = 0; // include whitelist-var-common.inc 37static int cnt_whitelistvar = 0; // include whitelist-var-common.inc
38static int cnt_whitelistrunuser = 0; // include whitelist-runuser-common.inc
39static int cnt_whitelistusrshare = 0; // include whitelist-usr-share-common.inc
38static int cnt_ssh = 0; 40static int cnt_ssh = 0;
39 41
40static int level = 0; 42static int level = 0;
@@ -46,6 +48,8 @@ static int arg_noexec = 0;
46static int arg_privatedev = 0; 48static int arg_privatedev = 0;
47static int arg_privatetmp = 0; 49static int arg_privatetmp = 0;
48static int arg_whitelistvar = 0; 50static int arg_whitelistvar = 0;
51static int arg_whitelistrunuser = 0;
52static int arg_whitelistusrshare = 0;
49static int arg_ssh = 0; 53static int arg_ssh = 0;
50 54
51static char *profile = NULL; 55static char *profile = NULL;
@@ -63,6 +67,8 @@ static void usage(void) {
63 printf(" --private-tmp - print profiles without private-tmp\n"); 67 printf(" --private-tmp - print profiles without private-tmp\n");
64 printf(" --seccomp - print profiles without seccomp\n"); 68 printf(" --seccomp - print profiles without seccomp\n");
65 printf(" --whitelist-var - print profiles without \"include whitelist-var-common.inc\"\n"); 69 printf(" --whitelist-var - print profiles without \"include whitelist-var-common.inc\"\n");
70 printf(" --whitelist-runuser - print profiles without \"include whitelist-runuser-common.inc\"\n");
71 printf(" --whitelist-usrshare - print profiles without \"include whitelist-usr-share-common.inc\"\n");
66 printf(" --debug\n"); 72 printf(" --debug\n");
67 printf("\n"); 73 printf("\n");
68} 74}
@@ -102,6 +108,10 @@ void process_file(const char *fname) {
102 cnt_noexec++; 108 cnt_noexec++;
103 else if (strncmp(ptr, "include whitelist-var-common.inc", 32) == 0) 109 else if (strncmp(ptr, "include whitelist-var-common.inc", 32) == 0)
104 cnt_whitelistvar++; 110 cnt_whitelistvar++;
111 else if (strncmp(ptr, "include whitelist-runuser-common.inc", 32) == 0)
112 cnt_whitelistrunuser++;
113 else if (strncmp(ptr, "include whitelist-usr-share-common.inc", 32) == 0)
114 cnt_whitelistusrshare++;
105 else if (strncmp(ptr, "include disable-common.inc", 26) == 0) 115 else if (strncmp(ptr, "include disable-common.inc", 26) == 0)
106 cnt_ssh++; 116 cnt_ssh++;
107 else if (strncmp(ptr, "net none", 8) == 0) 117 else if (strncmp(ptr, "net none", 8) == 0)
@@ -159,6 +169,10 @@ int main(int argc, char **argv) {
159 arg_privatetmp = 1; 169 arg_privatetmp = 1;
160 else if (strcmp(argv[i], "--whitelist-var") == 0) 170 else if (strcmp(argv[i], "--whitelist-var") == 0)
161 arg_whitelistvar = 1; 171 arg_whitelistvar = 1;
172 else if (strcmp(argv[i], "--whitelist-runuser") == 0)
173 arg_whitelistrunuser = 1;
174 else if (strcmp(argv[i], "--whitelist-usrshare") == 0)
175 arg_whitelistusrshare = 1;
162 else if (strcmp(argv[i], "--ssh") == 0) 176 else if (strcmp(argv[i], "--ssh") == 0)
163 arg_ssh = 1; 177 arg_ssh = 1;
164 else if (*argv[i] == '-') { 178 else if (*argv[i] == '-') {
@@ -188,6 +202,8 @@ int main(int argc, char **argv) {
188 int dotlocal = cnt_dotlocal; 202 int dotlocal = cnt_dotlocal;
189 int globalsdotlocal = cnt_globalsdotlocal; 203 int globalsdotlocal = cnt_globalsdotlocal;
190 int whitelistvar = cnt_whitelistvar; 204 int whitelistvar = cnt_whitelistvar;
205 int whitelistrunuser = cnt_whitelistrunuser;
206 int whitelistusrshare = cnt_whitelistusrshare;
191 int ssh = cnt_ssh; 207 int ssh = cnt_ssh;
192 208
193 // process file 209 // process file
@@ -220,6 +236,10 @@ int main(int argc, char **argv) {
220 printf("No private-tmp found in %s\n", argv[i]); 236 printf("No private-tmp found in %s\n", argv[i]);
221 if (arg_whitelistvar && whitelistvar == cnt_whitelistvar) 237 if (arg_whitelistvar && whitelistvar == cnt_whitelistvar)
222 printf("No include whitelist-var-common.inc found in %s\n", argv[i]); 238 printf("No include whitelist-var-common.inc found in %s\n", argv[i]);
239 if (arg_whitelistrunuser && whitelistrunuser == cnt_whitelistrunuser)
240 printf("No include whitelist-runuser-common.inc found in %s\n", argv[i]);
241 if (arg_whitelistusrshare && whitelistusrshare == cnt_whitelistusrshare)
242 printf("No include whitelist-usr-share-common.inc found in %s\n", argv[i]);
223 if (arg_ssh && ssh == cnt_ssh) 243 if (arg_ssh && ssh == cnt_ssh)
224 printf("No include disable-common.inc found in %s\n", argv[i]); 244 printf("No include disable-common.inc found in %s\n", argv[i]);
225 245
@@ -238,7 +258,9 @@ int main(int argc, char **argv) {
238 printf(" apparmor\t\t\t%d\n", cnt_apparmor); 258 printf(" apparmor\t\t\t%d\n", cnt_apparmor);
239 printf(" private-dev\t\t\t%d\n", cnt_privatedev); 259 printf(" private-dev\t\t\t%d\n", cnt_privatedev);
240 printf(" private-tmp\t\t\t%d\n", cnt_privatetmp); 260 printf(" private-tmp\t\t\t%d\n", cnt_privatetmp);
241 printf(" whitelist var directory\t%d (include whitelist-var-common.inc)\n", cnt_whitelistvar); 261 printf(" whitelist var\t\t%d (include whitelist-var-common.inc)\n", cnt_whitelistvar);
262 printf(" whitelist run/user\t\t%d (include whitelist-runuser-common.inc)\n", cnt_whitelistrunuser);
263 printf(" whitelist usr/share\t\t%d (include whitelist-usr-share-common.inc)\n", cnt_whitelistusrshare);
242 printf(" net none\t\t\t%d\n", cnt_netnone); 264 printf(" net none\t\t\t%d\n", cnt_netnone);
243 printf("\n"); 265 printf("\n");
244 return 0; 266 return 0;