diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/fbuilder/build_fs.c | 12 | ||||
-rw-r--r-- | src/fbuilder/build_home.c | 8 | ||||
-rw-r--r-- | src/fbuilder/build_profile.c | 34 | ||||
-rw-r--r-- | src/firecfg/firecfg.config | 2 | ||||
-rw-r--r-- | src/firejail/fs_home.c | 67 | ||||
-rw-r--r-- | src/firejail/pulseaudio.c | 126 | ||||
-rw-r--r-- | src/firejail/restrict_users.c | 23 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 35 | ||||
-rw-r--r-- | src/firejail/sbox.c | 5 | ||||
-rw-r--r-- | src/profstats/main.c | 2 |
10 files changed, 168 insertions, 146 deletions
diff --git a/src/fbuilder/build_fs.c b/src/fbuilder/build_fs.c index b08afb939..1b8231033 100644 --- a/src/fbuilder/build_fs.c +++ b/src/fbuilder/build_fs.c | |||
@@ -165,10 +165,12 @@ void build_var(const char *fname, FILE *fp) { | |||
165 | 165 | ||
166 | process_files(fname, "/var", var_callback); | 166 | process_files(fname, "/var", var_callback); |
167 | 167 | ||
168 | if (var_out == NULL) | 168 | if (var_out == NULL) { |
169 | fprintf(fp, "blacklist /var\n"); | 169 | fprintf(fp, "blacklist /var\n"); |
170 | else | 170 | } else { |
171 | filedb_print(var_out, "whitelist ", fp); | 171 | filedb_print(var_out, "whitelist ", fp); |
172 | fprintf(fp, "include whitelist-var-common.inc\n"); | ||
173 | } | ||
172 | } | 174 | } |
173 | 175 | ||
174 | 176 | ||
@@ -202,10 +204,12 @@ void build_share(const char *fname, FILE *fp) { | |||
202 | 204 | ||
203 | process_files(fname, "/usr/share", share_callback); | 205 | process_files(fname, "/usr/share", share_callback); |
204 | 206 | ||
205 | if (share_out == NULL) | 207 | if (share_out == NULL) { |
206 | fprintf(fp, "blacklist /usr/share\n"); | 208 | fprintf(fp, "blacklist /usr/share\n"); |
207 | else | 209 | } else { |
208 | filedb_print(share_out, "whitelist ", fp); | 210 | filedb_print(share_out, "whitelist ", fp); |
211 | fprintf(fp, "include whitelist-usr-share-common.inc\n"); | ||
212 | } | ||
209 | } | 213 | } |
210 | 214 | ||
211 | //******************************************* | 215 | //******************************************* |
diff --git a/src/fbuilder/build_home.c b/src/fbuilder/build_home.c index 8db17a942..fca3396c4 100644 --- a/src/fbuilder/build_home.c +++ b/src/fbuilder/build_home.c | |||
@@ -32,9 +32,9 @@ static void load_whitelist_common(void) { | |||
32 | 32 | ||
33 | char buf[MAX_BUF]; | 33 | char buf[MAX_BUF]; |
34 | while (fgets(buf, MAX_BUF, fp)) { | 34 | while (fgets(buf, MAX_BUF, fp)) { |
35 | if (strncmp(buf, "whitelist ~/", 12) != 0) | 35 | if (strncmp(buf, "whitelist ${HOME}/", 18) != 0) |
36 | continue; | 36 | continue; |
37 | char *fn = buf + 12; | 37 | char *fn = buf + 18; |
38 | char *ptr = strchr(buf, '\n'); | 38 | char *ptr = strchr(buf, '\n'); |
39 | if (!ptr) | 39 | if (!ptr) |
40 | continue; | 40 | continue; |
@@ -190,8 +190,8 @@ void build_home(const char *fname, FILE *fp) { | |||
190 | 190 | ||
191 | // print the out list if any | 191 | // print the out list if any |
192 | if (db_out) { | 192 | if (db_out) { |
193 | filedb_print(db_out, "whitelist ~/", fp); | 193 | filedb_print(db_out, "whitelist ${HOME}/", fp); |
194 | fprintf(fp, "include /etc/firejail/whitelist-common.inc\n"); | 194 | fprintf(fp, "include whitelist-common.inc\n"); |
195 | } | 195 | } |
196 | else | 196 | else |
197 | fprintf(fp, "private\n"); | 197 | fprintf(fp, "private\n"); |
diff --git a/src/fbuilder/build_profile.c b/src/fbuilder/build_profile.c index ea9e9a4a0..adc00e67b 100644 --- a/src/fbuilder/build_profile.c +++ b/src/fbuilder/build_profile.c | |||
@@ -131,18 +131,21 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { | |||
131 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { | 131 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { |
132 | if (fp == stdout) | 132 | if (fp == stdout) |
133 | printf("--- Built profile beings after this line ---\n"); | 133 | printf("--- Built profile beings after this line ---\n"); |
134 | fprintf(fp, "############################################\n"); | 134 | fprintf(fp, "# Firejail profile for %s\n", argv[index]); |
135 | fprintf(fp, "# %s profile\n", argv[index]); | 135 | fprintf(fp, "# Persistent local customizations\n"); |
136 | fprintf(fp, "############################################\n"); | 136 | fprintf(fp, "#include %s.local\n", argv[index]); |
137 | fprintf(fp, "# Persistent global definitions\n"); | 137 | fprintf(fp, "# Persistent global definitions\n"); |
138 | fprintf(fp, "# include /etc/firejail/globals.local\n"); | 138 | fprintf(fp, "#include globals.local\n"); |
139 | fprintf(fp, "\n"); | 139 | fprintf(fp, "\n"); |
140 | 140 | ||
141 | fprintf(fp, "### basic blacklisting\n"); | 141 | fprintf(fp, "### basic blacklisting\n"); |
142 | fprintf(fp, "include /etc/firejail/disable-common.inc\n"); | 142 | fprintf(fp, "include disable-common.inc\n"); |
143 | fprintf(fp, "# include /etc/firejail/disable-devel.inc\n"); | 143 | fprintf(fp, "# include disable-devel.inc\n"); |
144 | fprintf(fp, "include /etc/firejail/disable-passwdmgr.inc\n"); | 144 | fprintf(fp, "# include disable-exec.inc\n"); |
145 | fprintf(fp, "# include /etc/firejail/disable-programs.inc\n"); | 145 | fprintf(fp, "# include disable-interpreters.inc\n"); |
146 | fprintf(fp, "include disable-passwdmgr.inc\n"); | ||
147 | fprintf(fp, "# include disable-programs.inc\n"); | ||
148 | fprintf(fp, "# include disable-xdg.inc\n"); | ||
146 | fprintf(fp, "\n"); | 149 | fprintf(fp, "\n"); |
147 | 150 | ||
148 | fprintf(fp, "### home directory whitelisting\n"); | 151 | fprintf(fp, "### home directory whitelisting\n"); |
@@ -150,12 +153,19 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { | |||
150 | fprintf(fp, "\n"); | 153 | fprintf(fp, "\n"); |
151 | 154 | ||
152 | fprintf(fp, "### filesystem\n"); | 155 | fprintf(fp, "### filesystem\n"); |
153 | build_tmp(trace_output, fp); | 156 | fprintf(fp, "# /usr/share:\n"); |
154 | build_dev(trace_output, fp); | 157 | build_share(trace_output, fp); |
155 | build_etc(trace_output, fp); | 158 | fprintf(fp, "# /var:\n"); |
156 | build_var(trace_output, fp); | 159 | build_var(trace_output, fp); |
160 | fprintf(fp, "\n"); | ||
161 | fprintf(fp, "# $PATH:\n"); | ||
157 | build_bin(trace_output, fp); | 162 | build_bin(trace_output, fp); |
158 | build_share(trace_output, fp); | 163 | fprintf(fp, "# /dev:\n"); |
164 | build_dev(trace_output, fp); | ||
165 | fprintf(fp, "# /etc:\n"); | ||
166 | build_etc(trace_output, fp); | ||
167 | fprintf(fp, "# /tmp:\n"); | ||
168 | build_tmp(trace_output, fp); | ||
159 | fprintf(fp, "\n"); | 169 | fprintf(fp, "\n"); |
160 | 170 | ||
161 | fprintf(fp, "### security filters\n"); | 171 | fprintf(fp, "### security filters\n"); |
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config index a19819552..313f796b9 100644 --- a/src/firecfg/firecfg.config +++ b/src/firecfg/firecfg.config | |||
@@ -346,6 +346,7 @@ jd-gui | |||
346 | jdownloader | 346 | jdownloader |
347 | jerry | 347 | jerry |
348 | jitsi | 348 | jitsi |
349 | jitsi-meet-desktop | ||
349 | jumpnbump | 350 | jumpnbump |
350 | jumpnbump-menu | 351 | jumpnbump-menu |
351 | k3b | 352 | k3b |
@@ -492,6 +493,7 @@ neverputt | |||
492 | newsbeuter | 493 | newsbeuter |
493 | newsboat | 494 | newsboat |
494 | nheko | 495 | nheko |
496 | nicotine | ||
495 | nitroshare | 497 | nitroshare |
496 | nitroshare-cli | 498 | nitroshare-cli |
497 | nitroshare-nmh | 499 | nitroshare-nmh |
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index dbc74bfff..ff6d78bf2 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c | |||
@@ -352,20 +352,6 @@ void fs_private(void) { | |||
352 | int xflag = store_xauthority(); | 352 | int xflag = store_xauthority(); |
353 | int aflag = store_asoundrc(); | 353 | int aflag = store_asoundrc(); |
354 | 354 | ||
355 | // mask /home | ||
356 | if (u == 0 && arg_allusers) // allow --allusers when starting the sandbox as root | ||
357 | ; | ||
358 | else { | ||
359 | if (arg_debug) | ||
360 | printf("Mounting a new /home directory\n"); | ||
361 | if (arg_allusers) | ||
362 | fwarning("allusers option disabled by private or whitelist option\n"); | ||
363 | if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=755,gid=0") < 0) | ||
364 | errExit("mounting /home directory"); | ||
365 | selinux_relabel_path("/home", "/home"); | ||
366 | fs_logger("tmpfs /home"); | ||
367 | } | ||
368 | |||
369 | // mask /root | 355 | // mask /root |
370 | if (arg_debug) | 356 | if (arg_debug) |
371 | printf("Mounting a new /root directory\n"); | 357 | printf("Mounting a new /root directory\n"); |
@@ -373,28 +359,39 @@ void fs_private(void) { | |||
373 | errExit("mounting /root directory"); | 359 | errExit("mounting /root directory"); |
374 | fs_logger("tmpfs /root"); | 360 | fs_logger("tmpfs /root"); |
375 | 361 | ||
376 | if (u != 0) { | 362 | if (arg_allusers) { |
377 | if (strncmp(homedir, "/home/", 6) == 0) { | 363 | if (u != 0) |
378 | // create /home/user | 364 | fs_tmpfs(homedir, 1); // check if directory is owned by the current user |
379 | if (arg_debug) | 365 | } |
380 | printf("Create a new user directory\n"); | 366 | else { // mask /home |
381 | if (mkdir(homedir, S_IRWXU) == -1) { | 367 | if (arg_debug) |
382 | if (mkpath_as_root(homedir) == -1) | 368 | printf("Mounting a new /home directory\n"); |
383 | errExit("mkpath"); | 369 | if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=755,gid=0") < 0) |
384 | if (mkdir(homedir, S_IRWXU) == -1 && errno != EEXIST) | 370 | errExit("mounting /home directory"); |
385 | errExit("mkdir"); | 371 | selinux_relabel_path("/home", "/home"); |
386 | } | 372 | fs_logger("tmpfs /home"); |
387 | if (chown(homedir, u, g) < 0) | ||
388 | errExit("chown"); | ||
389 | selinux_relabel_path(homedir, homedir); | ||
390 | 373 | ||
391 | fs_logger2("mkdir", homedir); | 374 | if (u != 0) { |
392 | fs_logger2("tmpfs", homedir); | 375 | if (strncmp(homedir, "/home/", 6) == 0) { |
376 | // create /home/user | ||
377 | if (arg_debug) | ||
378 | printf("Create a new user directory\n"); | ||
379 | if (mkdir(homedir, S_IRWXU) == -1) { | ||
380 | if (mkpath_as_root(homedir) == -1) | ||
381 | errExit("mkpath"); | ||
382 | if (mkdir(homedir, S_IRWXU) == -1 && errno != EEXIST) | ||
383 | errExit("mkdir"); | ||
384 | } | ||
385 | if (chown(homedir, u, g) < 0) | ||
386 | errExit("chown"); | ||
387 | |||
388 | selinux_relabel_path(homedir, homedir); | ||
389 | fs_logger2("mkdir", homedir); | ||
390 | fs_logger2("tmpfs", homedir); | ||
391 | } | ||
392 | else | ||
393 | fs_tmpfs(homedir, 1); // check if directory is owned by the current user | ||
393 | } | 394 | } |
394 | else | ||
395 | // user directory is outside /home, mask it as well | ||
396 | // check if directory is owned by the current user | ||
397 | fs_tmpfs(homedir, 1); | ||
398 | } | 395 | } |
399 | 396 | ||
400 | skel(homedir, u, g); | 397 | skel(homedir, u, g); |
@@ -518,7 +515,7 @@ static void duplicate(char *name) { | |||
518 | ptr++; | 515 | ptr++; |
519 | if (asprintf(&path, "%s/%s", RUN_HOME_DIR, ptr) == -1) | 516 | if (asprintf(&path, "%s/%s", RUN_HOME_DIR, ptr) == -1) |
520 | errExit("asprintf"); | 517 | errExit("asprintf"); |
521 | mkdir_attr(path, 0755, getuid(), getgid()); | 518 | create_empty_dir_as_user(path, 0755); |
522 | sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, path); | 519 | sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, path); |
523 | free(path); | 520 | free(path); |
524 | } | 521 | } |
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c index a8fb838ab..b4df78dda 100644 --- a/src/firejail/pulseaudio.c +++ b/src/firejail/pulseaudio.c | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | #include <fcntl.h> | 28 | #include <fcntl.h> |
29 | #ifndef O_PATH | 29 | #ifndef O_PATH |
30 | # define O_PATH 010000000 | 30 | #define O_PATH 010000000 |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | // disable pulseaudio socket | 33 | // disable pulseaudio socket |
@@ -72,8 +72,13 @@ void pulseaudio_disable(void) { | |||
72 | closedir(dir); | 72 | closedir(dir); |
73 | } | 73 | } |
74 | 74 | ||
75 | static void pulseaudio_set_environment(const char *path) { | ||
76 | assert(path); | ||
77 | if (setenv("PULSE_CLIENTCONFIG", path, 1) < 0) | ||
78 | errExit("setenv"); | ||
79 | } | ||
75 | 80 | ||
76 | // disable shm in pulseaudio | 81 | // disable shm in pulseaudio (issue #69) |
77 | void pulseaudio_init(void) { | 82 | void pulseaudio_init(void) { |
78 | struct stat s; | 83 | struct stat s; |
79 | 84 | ||
@@ -108,84 +113,63 @@ void pulseaudio_init(void) { | |||
108 | errExit("set_perms"); | 113 | errExit("set_perms"); |
109 | 114 | ||
110 | // create ~/.config/pulse directory if not present | 115 | // create ~/.config/pulse directory if not present |
111 | char *homeusercfg; | 116 | char *homeusercfg = NULL; |
112 | if (asprintf(&homeusercfg, "%s/.config", cfg.homedir) == -1) | 117 | if (asprintf(&homeusercfg, "%s/.config", cfg.homedir) == -1) |
113 | errExit("asprintf"); | 118 | errExit("asprintf"); |
114 | if (lstat(homeusercfg, &s) == -1) { | 119 | if (create_empty_dir_as_user(homeusercfg, 0700)) |
115 | if (create_empty_dir_as_user(homeusercfg, 0700)) | 120 | fs_logger2("create", homeusercfg); |
116 | fs_logger2("create", homeusercfg); | ||
117 | } | ||
118 | else if (!S_ISDIR(s.st_mode)) { | ||
119 | if (S_ISLNK(s.st_mode)) | ||
120 | fprintf(stderr, "Error: %s is a symbolic link\n", homeusercfg); | ||
121 | else | ||
122 | fprintf(stderr, "Error: %s is not a directory\n", homeusercfg); | ||
123 | exit(1); | ||
124 | } | ||
125 | free(homeusercfg); | ||
126 | 121 | ||
122 | free(homeusercfg); | ||
127 | if (asprintf(&homeusercfg, "%s/.config/pulse", cfg.homedir) == -1) | 123 | if (asprintf(&homeusercfg, "%s/.config/pulse", cfg.homedir) == -1) |
128 | errExit("asprintf"); | 124 | errExit("asprintf"); |
129 | if (lstat(homeusercfg, &s) == -1) { | 125 | if (create_empty_dir_as_user(homeusercfg, 0700)) |
130 | if (create_empty_dir_as_user(homeusercfg, 0700)) | 126 | fs_logger2("create", homeusercfg); |
131 | fs_logger2("create", homeusercfg); | 127 | |
132 | } | 128 | // if ~/.config/pulse now exists and there are no symbolic links, mount the new directory |
133 | else if (!S_ISDIR(s.st_mode)) { | 129 | // else set environment variable |
134 | if (S_ISLNK(s.st_mode)) | 130 | int fd = safe_fd(homeusercfg, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
135 | fprintf(stderr, "Error: %s is a symbolic link\n", homeusercfg); | 131 | if (fd == -1) { |
136 | else | 132 | pulseaudio_set_environment(pulsecfg); |
137 | fprintf(stderr, "Error: %s is not a directory\n", homeusercfg); | 133 | goto out; |
138 | exit(1); | ||
139 | } | 134 | } |
140 | 135 | // confirm the actual mount destination is owned by the user | |
141 | // if we have ~/.config/pulse mount the new directory, else set environment variable. | 136 | if (fstat(fd, &s) == -1) |
142 | if (stat(homeusercfg, &s) == 0) { | 137 | errExit("fstat"); |
143 | // get a file descriptor for ~/.config/pulse, fails if there is any symlink | 138 | if (s.st_uid != getuid()) { |
144 | int fd = safe_fd(homeusercfg, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | ||
145 | if (fd == -1) | ||
146 | errExit("safe_fd"); | ||
147 | // confirm the actual mount destination is owned by the user | ||
148 | if (fstat(fd, &s) == -1) | ||
149 | errExit("fstat"); | ||
150 | if (s.st_uid != getuid()) { | ||
151 | fprintf(stderr, "Error: %s is not owned by the current user\n", homeusercfg); | ||
152 | exit(1); | ||
153 | } | ||
154 | // preserve a read-only mount | ||
155 | struct statvfs vfs; | ||
156 | if (fstatvfs(fd, &vfs) == -1) | ||
157 | errExit("fstatvfs"); | ||
158 | if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY) | ||
159 | fs_remount(RUN_PULSE_DIR, MOUNT_READONLY, 0); | ||
160 | // mount via the link in /proc/self/fd | ||
161 | if (arg_debug) | ||
162 | printf("Mounting %s on %s\n", RUN_PULSE_DIR, homeusercfg); | ||
163 | char *proc; | ||
164 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | ||
165 | errExit("asprintf"); | ||
166 | if (mount(RUN_PULSE_DIR, proc, "none", MS_BIND, NULL) < 0) | ||
167 | errExit("mount pulseaudio"); | ||
168 | fs_logger2("tmpfs", homeusercfg); | ||
169 | free(proc); | ||
170 | close(fd); | 139 | close(fd); |
171 | // check /proc/self/mountinfo to confirm the mount is ok | 140 | pulseaudio_set_environment(pulsecfg); |
172 | MountData *mptr = get_last_mount(); | 141 | goto out; |
173 | if (strcmp(mptr->dir, homeusercfg) != 0 || strcmp(mptr->fstype, "tmpfs") != 0) | ||
174 | errLogExit("invalid pulseaudio mount"); | ||
175 | |||
176 | char *p; | ||
177 | if (asprintf(&p, "%s/client.conf", homeusercfg) == -1) | ||
178 | errExit("asprintf"); | ||
179 | fs_logger2("create", p); | ||
180 | free(p); | ||
181 | } | ||
182 | |||
183 | else { | ||
184 | // set environment | ||
185 | if (setenv("PULSE_CLIENTCONFIG", pulsecfg, 1) < 0) | ||
186 | errExit("setenv"); | ||
187 | } | 142 | } |
143 | // preserve a read-only mount | ||
144 | struct statvfs vfs; | ||
145 | if (fstatvfs(fd, &vfs) == -1) | ||
146 | errExit("fstatvfs"); | ||
147 | if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY) | ||
148 | fs_remount(RUN_PULSE_DIR, MOUNT_READONLY, 0); | ||
149 | // mount via the link in /proc/self/fd | ||
150 | if (arg_debug) | ||
151 | printf("Mounting %s on %s\n", RUN_PULSE_DIR, homeusercfg); | ||
152 | char *proc; | ||
153 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | ||
154 | errExit("asprintf"); | ||
155 | if (mount(RUN_PULSE_DIR, proc, "none", MS_BIND, NULL) < 0) | ||
156 | errExit("mount pulseaudio"); | ||
157 | // check /proc/self/mountinfo to confirm the mount is ok | ||
158 | MountData *mptr = get_last_mount(); | ||
159 | if (strcmp(mptr->dir, homeusercfg) != 0 || strcmp(mptr->fstype, "tmpfs") != 0) | ||
160 | errLogExit("invalid pulseaudio mount"); | ||
161 | fs_logger2("tmpfs", homeusercfg); | ||
162 | free(proc); | ||
163 | close(fd); | ||
164 | |||
165 | char *p; | ||
166 | if (asprintf(&p, "%s/client.conf", homeusercfg) == -1) | ||
167 | errExit("asprintf"); | ||
168 | fs_logger2("create", p); | ||
169 | pulseaudio_set_environment(p); | ||
170 | free(p); | ||
188 | 171 | ||
172 | out: | ||
189 | free(pulsecfg); | 173 | free(pulsecfg); |
190 | free(homeusercfg); | 174 | free(homeusercfg); |
191 | } | 175 | } |
diff --git a/src/firejail/restrict_users.c b/src/firejail/restrict_users.c index 5ebb0e9ec..804b45339 100644 --- a/src/firejail/restrict_users.c +++ b/src/firejail/restrict_users.c | |||
@@ -29,7 +29,7 @@ | |||
29 | 29 | ||
30 | #include <fcntl.h> | 30 | #include <fcntl.h> |
31 | #ifndef O_PATH | 31 | #ifndef O_PATH |
32 | # define O_PATH 010000000 | 32 | #define O_PATH 010000000 |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #define MAXBUF 1024 | 35 | #define MAXBUF 1024 |
@@ -68,24 +68,25 @@ static USER_LIST *ulist_find(const char *user) { | |||
68 | 68 | ||
69 | static void sanitize_home(void) { | 69 | static void sanitize_home(void) { |
70 | assert(getuid() != 0); // this code works only for regular users | 70 | assert(getuid() != 0); // this code works only for regular users |
71 | struct stat s; | ||
71 | 72 | ||
72 | if (arg_debug) | 73 | if (arg_debug) |
73 | printf("Cleaning /home directory\n"); | 74 | printf("Cleaning /home directory\n"); |
74 | 75 | ||
75 | struct stat s; | ||
76 | if (stat(cfg.homedir, &s) == -1) { | ||
77 | // cannot find home directory, just return | ||
78 | fwarning("cannot find home directory\n"); | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | if (mkdir(RUN_WHITELIST_HOME_DIR, 0755) == -1) | 76 | if (mkdir(RUN_WHITELIST_HOME_DIR, 0755) == -1) |
83 | errExit("mkdir"); | 77 | errExit("mkdir"); |
84 | 78 | ||
85 | // keep a copy of the user home directory | 79 | // keep a copy of the user home directory |
86 | int fd = safe_fd(cfg.homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | 80 | int fd = safe_fd(cfg.homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
87 | if (fd == -1) | 81 | if (fd == -1) { |
88 | errExit("safe_fd"); | 82 | if (errno == ENOENT) |
83 | fwarning("cannot find user home directory\n"); | ||
84 | else | ||
85 | fwarning("cannot clean /home directory\n"); | ||
86 | return; | ||
87 | } | ||
88 | if (fstat(fd, &s) == -1) | ||
89 | errExit("fstat"); | ||
89 | char *proc; | 90 | char *proc; |
90 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | 91 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) |
91 | errExit("asprintf"); | 92 | errExit("asprintf"); |
@@ -167,7 +168,7 @@ static void sanitize_run(void) { | |||
167 | if (set_perms(runuser, getuid(), getgid(), 0700)) | 168 | if (set_perms(runuser, getuid(), getgid(), 0700)) |
168 | errExit("set_perms"); | 169 | errExit("set_perms"); |
169 | 170 | ||
170 | // mount user home directory | 171 | // mount /run/user/$UID directory |
171 | if (mount(RUN_WHITELIST_RUN_DIR, runuser, NULL, MS_BIND|MS_REC, NULL) < 0) | 172 | if (mount(RUN_WHITELIST_RUN_DIR, runuser, NULL, MS_BIND|MS_REC, NULL) < 0) |
172 | errExit("mount bind"); | 173 | errExit("mount bind"); |
173 | 174 | ||
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 37d108750..631f721ad 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -198,6 +198,32 @@ static FILE *create_ready_for_join_file(void) { | |||
198 | } | 198 | } |
199 | } | 199 | } |
200 | 200 | ||
201 | #ifdef HAVE_SECCOMP | ||
202 | static void seccomp_debug(void) { | ||
203 | if (arg_debug == 0) | ||
204 | return; | ||
205 | |||
206 | pid_t child = fork(); | ||
207 | if (child < 0) | ||
208 | errExit("fork"); | ||
209 | if (child == 0) { | ||
210 | // dropping privs before calling system(3) | ||
211 | drop_privs(1); | ||
212 | printf("Seccomp directory:\n"); | ||
213 | int rv = system("ls -l " RUN_SECCOMP_DIR); | ||
214 | (void) rv; | ||
215 | printf("Active seccomp files:\n"); | ||
216 | rv = system("cat " RUN_SECCOMP_LIST); | ||
217 | (void) rv; | ||
218 | #ifdef HAVE_GCOV | ||
219 | __gcov_flush(); | ||
220 | #endif | ||
221 | _exit(0); | ||
222 | } | ||
223 | waitpid(child, NULL, 0); | ||
224 | } | ||
225 | #endif | ||
226 | |||
201 | static void sandbox_if_up(Bridge *br) { | 227 | static void sandbox_if_up(Bridge *br) { |
202 | assert(br); | 228 | assert(br); |
203 | if (!br->configured) | 229 | if (!br->configured) |
@@ -1136,14 +1162,7 @@ int sandbox(void* sandbox_arg) { | |||
1136 | 1162 | ||
1137 | // make seccomp filters read-only | 1163 | // make seccomp filters read-only |
1138 | fs_remount(RUN_SECCOMP_DIR, MOUNT_READONLY, 0); | 1164 | fs_remount(RUN_SECCOMP_DIR, MOUNT_READONLY, 0); |
1139 | if (arg_debug) { | 1165 | seccomp_debug(); |
1140 | printf("Seccomp directory:\n"); | ||
1141 | int rv = system("ls -l " RUN_SECCOMP_DIR); | ||
1142 | (void) rv; | ||
1143 | printf("Active seccomp files:\n"); | ||
1144 | rv = system("cat " RUN_SECCOMP_LIST); | ||
1145 | (void) rv; | ||
1146 | } | ||
1147 | #endif | 1166 | #endif |
1148 | 1167 | ||
1149 | // set capabilities | 1168 | // set capabilities |
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c index e7fa267d8..91c658f96 100644 --- a/src/firejail/sbox.c +++ b/src/firejail/sbox.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | static int sbox_do_exec_v(unsigned filtermask, char * const arg[]) { | 34 | static int sbox_do_exec_v(unsigned filtermask, char * const arg[]) { |
35 | // build a new, clean environment | ||
35 | int env_index = 0; | 36 | int env_index = 0; |
36 | char *new_environment[256] = { NULL }; | 37 | char *new_environment[256] = { NULL }; |
37 | // preserve firejail-specific env vars | 38 | // preserve firejail-specific env vars |
@@ -40,7 +41,6 @@ static int sbox_do_exec_v(unsigned filtermask, char * const arg[]) { | |||
40 | if (asprintf(&new_environment[env_index++], "FIREJAIL_FILE_COPY_LIMIT=%s", cl) == -1) | 41 | if (asprintf(&new_environment[env_index++], "FIREJAIL_FILE_COPY_LIMIT=%s", cl) == -1) |
41 | errExit("asprintf"); | 42 | errExit("asprintf"); |
42 | } | 43 | } |
43 | clearenv(); | ||
44 | if (arg_quiet) // --quiet is passed as an environment variable | 44 | if (arg_quiet) // --quiet is passed as an environment variable |
45 | new_environment[env_index++] = "FIREJAIL_QUIET=yes"; | 45 | new_environment[env_index++] = "FIREJAIL_QUIET=yes"; |
46 | if (arg_debug) // --debug is passed as an environment variable | 46 | if (arg_debug) // --debug is passed as an environment variable |
@@ -123,6 +123,9 @@ static int sbox_do_exec_v(unsigned filtermask, char * const arg[]) { | |||
123 | #ifdef SYS_mount | 123 | #ifdef SYS_mount |
124 | BLACKLIST(SYS_mount), // mount/unmount filesystems | 124 | BLACKLIST(SYS_mount), // mount/unmount filesystems |
125 | #endif | 125 | #endif |
126 | #ifdef SYS_umount | ||
127 | BLACKLIST(SYS_umount), | ||
128 | #endif | ||
126 | #ifdef SYS_umount2 | 129 | #ifdef SYS_umount2 |
127 | BLACKLIST(SYS_umount2), | 130 | BLACKLIST(SYS_umount2), |
128 | #endif | 131 | #endif |
diff --git a/src/profstats/main.c b/src/profstats/main.c index b94fdd213..a75ad8e29 100644 --- a/src/profstats/main.c +++ b/src/profstats/main.c | |||
@@ -246,6 +246,8 @@ int main(int argc, char **argv) { | |||
246 | cnt_dotlocal = dotlocal + 1; | 246 | cnt_dotlocal = dotlocal + 1; |
247 | if (cnt_globalsdotlocal > (globalsdotlocal + 1)) | 247 | if (cnt_globalsdotlocal > (globalsdotlocal + 1)) |
248 | cnt_globalsdotlocal = globalsdotlocal + 1; | 248 | cnt_globalsdotlocal = globalsdotlocal + 1; |
249 | if (cnt_whitelistrunuser > (whitelistrunuser + 1)) | ||
250 | cnt_whitelistrunuser = whitelistrunuser + 1; | ||
249 | 251 | ||
250 | if (arg_apparmor && apparmor == cnt_apparmor) | 252 | if (arg_apparmor && apparmor == cnt_apparmor) |
251 | printf("No apparmor found in %s\n", argv[i]); | 253 | printf("No apparmor found in %s\n", argv[i]); |