diff options
author | Fred Barclay <Fred-Barclay@users.noreply.github.com> | 2017-05-22 01:48:27 -0500 |
---|---|---|
committer | Fred Barclay <Fred-Barclay@users.noreply.github.com> | 2017-05-22 01:48:27 -0500 |
commit | cfbcbf2c95455373aa2570827c52b7b87d80cfef (patch) | |
tree | a29ac95c58a14c7f69c9b900b10fd1d63ba4ec19 /src | |
parent | Fix 1291 - remove nonexistent *.inc from qupzilla profile (diff) | |
download | firejail-cfbcbf2c95455373aa2570827c52b7b87d80cfef.tar.gz firejail-cfbcbf2c95455373aa2570827c52b7b87d80cfef.tar.zst firejail-cfbcbf2c95455373aa2570827c52b7b87d80cfef.zip |
--novideo option
Still a work in progress. Code needs cleanup and improvement, but
it does block /dev/video* in all of my tests so far.
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/firejail.h | 22 | ||||
-rw-r--r-- | src/firejail/fs_dev.c | 36 | ||||
-rw-r--r-- | src/firejail/main.c | 286 | ||||
-rw-r--r-- | src/firejail/profile.c | 130 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 144 | ||||
-rw-r--r-- | src/firejail/usage.c | 41 | ||||
-rw-r--r-- | src/man/firejail-profile.txt | 13 | ||||
-rw-r--r-- | src/man/firejail.txt | 78 |
8 files changed, 389 insertions, 361 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index fba4c4fe2..91b9c7be7 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -147,9 +147,9 @@ typedef struct bridge_t { | |||
147 | uint32_t mask; // interface device mask | 147 | uint32_t mask; // interface device mask |
148 | uint8_t mac[6]; // interface mac address | 148 | uint8_t mac[6]; // interface mac address |
149 | int mtu; // interface mtu | 149 | int mtu; // interface mtu |
150 | 150 | ||
151 | char *veth_name; // veth name for the device connected to the bridge | 151 | char *veth_name; // veth name for the device connected to the bridge |
152 | 152 | ||
153 | // inside the sandbox | 153 | // inside the sandbox |
154 | char *devsandbox; // name of the device inside the sandbox | 154 | char *devsandbox; // name of the device inside the sandbox |
155 | uint32_t ipsandbox; // ip address inside the sandbox | 155 | uint32_t ipsandbox; // ip address inside the sandbox |
@@ -157,7 +157,7 @@ typedef struct bridge_t { | |||
157 | uint8_t macsandbox[6]; // mac address inside the sandbox | 157 | uint8_t macsandbox[6]; // mac address inside the sandbox |
158 | uint32_t iprange_start;// iprange arp scan start range | 158 | uint32_t iprange_start;// iprange arp scan start range |
159 | uint32_t iprange_end; // iprange arp scan end range | 159 | uint32_t iprange_end; // iprange arp scan end range |
160 | 160 | ||
161 | // flags | 161 | // flags |
162 | uint8_t arg_ip_none; // --ip=none | 162 | uint8_t arg_ip_none; // --ip=none |
163 | uint8_t macvlan; // set by --net=eth0 (or eth1, ...); reset by --net=br0 (or br1, ...) | 163 | uint8_t macvlan; // set by --net=eth0 (or eth1, ...); reset by --net=br0 (or br1, ...) |
@@ -171,14 +171,14 @@ typedef struct interface_t { | |||
171 | uint32_t mask; | 171 | uint32_t mask; |
172 | uint8_t mac[6]; | 172 | uint8_t mac[6]; |
173 | int mtu; | 173 | int mtu; |
174 | 174 | ||
175 | uint8_t configured; | 175 | uint8_t configured; |
176 | } Interface; | 176 | } Interface; |
177 | 177 | ||
178 | typedef struct profile_entry_t { | 178 | typedef struct profile_entry_t { |
179 | struct profile_entry_t *next; | 179 | struct profile_entry_t *next; |
180 | char *data; // command | 180 | char *data; // command |
181 | 181 | ||
182 | // whitelist command parameters | 182 | // whitelist command parameters |
183 | char *link; // link name - set if the file is a link | 183 | char *link; // link name - set if the file is a link |
184 | unsigned home_dir:1; // whitelist in /home/user directory | 184 | unsigned home_dir:1; // whitelist in /home/user directory |
@@ -195,10 +195,10 @@ typedef struct config_t { | |||
195 | // user data | 195 | // user data |
196 | char *username; | 196 | char *username; |
197 | char *homedir; | 197 | char *homedir; |
198 | 198 | ||
199 | // filesystem | 199 | // filesystem |
200 | ProfileEntry *profile; | 200 | ProfileEntry *profile; |
201 | #define MAX_PROFILE_IGNORE 32 | 201 | #define MAX_PROFILE_IGNORE 32 |
202 | char *profile_ignore[MAX_PROFILE_IGNORE]; | 202 | char *profile_ignore[MAX_PROFILE_IGNORE]; |
203 | char *chrootdir; // chroot directory | 203 | char *chrootdir; // chroot directory |
204 | char *home_private; // private home directory | 204 | char *home_private; // private home directory |
@@ -239,12 +239,12 @@ typedef struct config_t { | |||
239 | long long unsigned rlimit_nproc; | 239 | long long unsigned rlimit_nproc; |
240 | long long unsigned rlimit_fsize; | 240 | long long unsigned rlimit_fsize; |
241 | long long unsigned rlimit_sigpending; | 241 | long long unsigned rlimit_sigpending; |
242 | 242 | ||
243 | // cpu affinity, nice and control groups | 243 | // cpu affinity, nice and control groups |
244 | uint32_t cpus; | 244 | uint32_t cpus; |
245 | int nice; | 245 | int nice; |
246 | char *cgroup; | 246 | char *cgroup; |
247 | 247 | ||
248 | 248 | ||
249 | // command line | 249 | // command line |
250 | char *command_line; | 250 | char *command_line; |
@@ -331,6 +331,7 @@ extern int arg_private_tmp; // private tmp directory | |||
331 | extern int arg_scan; // arp-scan all interfaces | 331 | extern int arg_scan; // arp-scan all interfaces |
332 | extern int arg_whitelist; // whitelist commad | 332 | extern int arg_whitelist; // whitelist commad |
333 | extern int arg_nosound; // disable sound | 333 | extern int arg_nosound; // disable sound |
334 | extern int arg_novideo; //disable video devices in /dev | ||
334 | extern int arg_no3d; // disable 3d hardware acceleration | 335 | extern int arg_no3d; // disable 3d hardware acceleration |
335 | extern int arg_quiet; // no output for scripting | 336 | extern int arg_quiet; // no output for scripting |
336 | extern int arg_join_network; // join only the network namespace | 337 | extern int arg_join_network; // join only the network namespace |
@@ -724,7 +725,7 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc, | |||
724 | // bitmapped filters for sbox_run | 725 | // bitmapped filters for sbox_run |
725 | #define SBOX_ROOT (1 << 0) // run the sandbox as root | 726 | #define SBOX_ROOT (1 << 0) // run the sandbox as root |
726 | #define SBOX_USER (1 << 1) // run the sandbox as a regular user | 727 | #define SBOX_USER (1 << 1) // run the sandbox as a regular user |
727 | #define SBOX_SECCOMP (1 << 2) // install seccomp | 728 | #define SBOX_SECCOMP (1 << 2) // install seccomp |
728 | #define SBOX_CAPS_NONE (1 << 3) // drop all capabilities | 729 | #define SBOX_CAPS_NONE (1 << 3) // drop all capabilities |
729 | #define SBOX_CAPS_NETWORK (1 << 4) // caps filter for programs running network programs | 730 | #define SBOX_CAPS_NETWORK (1 << 4) // caps filter for programs running network programs |
730 | #define SBOX_ALLOW_STDIN (1 << 5) // don't close stdin | 731 | #define SBOX_ALLOW_STDIN (1 << 5) // don't close stdin |
@@ -739,4 +740,3 @@ void git_install(); | |||
739 | void git_uninstall(); | 740 | void git_uninstall(); |
740 | 741 | ||
741 | #endif | 742 | #endif |
742 | |||
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c index 9b73ac9fc..159c8e654 100644 --- a/src/firejail/fs_dev.c +++ b/src/firejail/fs_dev.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <fcntl.h> | 26 | #include <fcntl.h> |
27 | #include <pwd.h> | 27 | #include <pwd.h> |
28 | #ifndef _BSD_SOURCE | 28 | #ifndef _BSD_SOURCE |
29 | #define _BSD_SOURCE | 29 | #define _BSD_SOURCE |
30 | #endif | 30 | #endif |
31 | #include <sys/sysmacros.h> | 31 | #include <sys/sysmacros.h> |
32 | #include <sys/types.h> | 32 | #include <sys/types.h> |
@@ -35,6 +35,7 @@ typedef struct { | |||
35 | const char *dev_fname; | 35 | const char *dev_fname; |
36 | const char *run_fname; | 36 | const char *run_fname; |
37 | int sound; | 37 | int sound; |
38 | int video; | ||
38 | int hw3d; | 39 | int hw3d; |
39 | } DevEntry; | 40 | } DevEntry; |
40 | 41 | ||
@@ -93,16 +94,16 @@ static void deventry_mount(void) { | |||
93 | fclose(fp); | 94 | fclose(fp); |
94 | } | 95 | } |
95 | } | 96 | } |
96 | 97 | ||
97 | if (mount(dev[i].run_fname, dev[i].dev_fname, NULL, MS_BIND|MS_REC, NULL) < 0) | 98 | if (mount(dev[i].run_fname, dev[i].dev_fname, NULL, MS_BIND|MS_REC, NULL) < 0) |
98 | errExit("mounting dev file"); | 99 | errExit("mounting dev file"); |
99 | fs_logger2("whitelist", dev[i].dev_fname); | 100 | fs_logger2("whitelist", dev[i].dev_fname); |
100 | } | 101 | } |
101 | 102 | ||
102 | i++; | 103 | i++; |
103 | } | 104 | } |
104 | } | 105 | } |
105 | 106 | ||
106 | static void create_char_dev(const char *path, mode_t mode, int major, int minor) { | 107 | static void create_char_dev(const char *path, mode_t mode, int major, int minor) { |
107 | dev_t dev = makedev(major, minor); | 108 | dev_t dev = makedev(major, minor); |
108 | if (mknod(path, S_IFCHR | mode, dev) == -1) | 109 | if (mknod(path, S_IFCHR | mode, dev) == -1) |
@@ -112,7 +113,7 @@ static void create_char_dev(const char *path, mode_t mode, int major, int minor) | |||
112 | ASSERT_PERMS(path, 0, 0, mode); | 113 | ASSERT_PERMS(path, 0, 0, mode); |
113 | 114 | ||
114 | return; | 115 | return; |
115 | 116 | ||
116 | errexit: | 117 | errexit: |
117 | fprintf(stderr, "Error: cannot create %s device\n", path); | 118 | fprintf(stderr, "Error: cannot create %s device\n", path); |
118 | exit(1); | 119 | exit(1); |
@@ -161,7 +162,7 @@ void fs_private_dev(void){ | |||
161 | if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) | 162 | if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) |
162 | errExit("mounting /dev"); | 163 | errExit("mounting /dev"); |
163 | fs_logger("tmpfs /dev"); | 164 | fs_logger("tmpfs /dev"); |
164 | 165 | ||
165 | deventry_mount(); | 166 | deventry_mount(); |
166 | 167 | ||
167 | // bring back /dev/log | 168 | // bring back /dev/log |
@@ -174,11 +175,11 @@ void fs_private_dev(void){ | |||
174 | errExit("mounting /dev/log"); | 175 | errExit("mounting /dev/log"); |
175 | fs_logger("clone /dev/log"); | 176 | fs_logger("clone /dev/log"); |
176 | } | 177 | } |
177 | } | 178 | } |
178 | if (mount(RUN_RO_DIR, RUN_DEV_DIR, "none", MS_BIND, "mode=400,gid=0") < 0) | 179 | if (mount(RUN_RO_DIR, RUN_DEV_DIR, "none", MS_BIND, "mode=400,gid=0") < 0) |
179 | errExit("disable /dev/snd"); | 180 | errExit("disable /dev/snd"); |
180 | 181 | ||
181 | 182 | ||
182 | // create /dev/shm | 183 | // create /dev/shm |
183 | if (arg_debug) | 184 | if (arg_debug) |
184 | printf("Create /dev/shm directory\n"); | 185 | printf("Create /dev/shm directory\n"); |
@@ -267,24 +268,24 @@ void fs_dev_shm(void) { | |||
267 | fwarning("/dev/shm not mounted\n"); | 268 | fwarning("/dev/shm not mounted\n"); |
268 | dbg_test_dir("/dev/shm"); | 269 | dbg_test_dir("/dev/shm"); |
269 | } | 270 | } |
270 | 271 | ||
271 | } | 272 | } |
272 | } | 273 | } |
273 | #endif | 274 | #endif |
274 | 275 | ||
275 | static void disable_file_or_dir(const char *fname) { | 276 | static void disable_file_or_dir(const char *fname) { |
276 | if (arg_debug) | 277 | if (arg_debug) |
277 | printf("disable %s\n", fname); | 278 | printf("disable %s\n", fname); |
278 | struct stat s; | 279 | struct stat s; |
279 | if (stat(fname, &s) != -1) { | 280 | if (stat(fname, &s) != -1) { |
280 | if (is_dir(fname)) { | 281 | if (is_dir(fname)) { |
281 | if (mount(RUN_RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0) | 282 | if (mount(RUN_RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0) |
282 | errExit("disable directory"); | 283 | errExit("disable directory"); |
283 | } | 284 | } |
284 | else { | 285 | else { |
285 | if (mount(RUN_RO_FILE, fname, "none", MS_BIND, "mode=400,gid=0") < 0) | 286 | if (mount(RUN_RO_FILE, fname, "none", MS_BIND, "mode=400,gid=0") < 0) |
286 | errExit("disable file"); | 287 | errExit("disable file"); |
287 | } | 288 | } |
288 | } | 289 | } |
289 | fs_logger2("blacklist", fname); | 290 | fs_logger2("blacklist", fname); |
290 | 291 | ||
@@ -299,6 +300,15 @@ void fs_dev_disable_sound(void) { | |||
299 | } | 300 | } |
300 | } | 301 | } |
301 | 302 | ||
303 | void fs_dev_disable_video(void) { | ||
304 | int i = 0; | ||
305 | while (dev[i].dev_fname != NULL) { | ||
306 | if (dev[i].video) | ||
307 | disable_file_or_dir(dev[i].dev_fname); | ||
308 | i++; | ||
309 | } | ||
310 | } | ||
311 | |||
302 | void fs_dev_disable_3d(void) { | 312 | void fs_dev_disable_3d(void) { |
303 | int i = 0; | 313 | int i = 0; |
304 | while (dev[i].dev_fname != NULL) { | 314 | while (dev[i].dev_fname != NULL) { |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 86ca422ae..012b2f230 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -88,6 +88,7 @@ int arg_private_tmp = 0; // private tmp directory | |||
88 | int arg_scan = 0; // arp-scan all interfaces | 88 | int arg_scan = 0; // arp-scan all interfaces |
89 | int arg_whitelist = 0; // whitelist commad | 89 | int arg_whitelist = 0; // whitelist commad |
90 | int arg_nosound = 0; // disable sound | 90 | int arg_nosound = 0; // disable sound |
91 | int arg_novideo = 0; //disable video devices in /dev | ||
91 | int arg_no3d; // disable 3d hardware acceleration | 92 | int arg_no3d; // disable 3d hardware acceleration |
92 | int arg_quiet = 0; // no output for scripting | 93 | int arg_quiet = 0; // no output for scripting |
93 | int arg_join_network = 0; // join only the network namespace | 94 | int arg_join_network = 0; // join only the network namespace |
@@ -143,7 +144,7 @@ static void myexit(int rv) { | |||
143 | clear_run_files(sandbox_pid); | 144 | clear_run_files(sandbox_pid); |
144 | appimage_clear(); | 145 | appimage_clear(); |
145 | flush_stdin(); | 146 | flush_stdin(); |
146 | exit(rv); | 147 | exit(rv); |
147 | } | 148 | } |
148 | 149 | ||
149 | static void my_handler(int s){ | 150 | static void my_handler(int s){ |
@@ -163,7 +164,7 @@ static pid_t extract_pid(const char *name) { | |||
163 | fprintf(stderr, "Error: invalid sandbox name\n"); | 164 | fprintf(stderr, "Error: invalid sandbox name\n"); |
164 | exit(1); | 165 | exit(1); |
165 | } | 166 | } |
166 | 167 | ||
167 | pid_t pid; | 168 | pid_t pid; |
168 | EUID_ROOT(); | 169 | EUID_ROOT(); |
169 | if (name2pid(name, &pid)) { | 170 | if (name2pid(name, &pid)) { |
@@ -201,7 +202,7 @@ static void init_cfg(int argc, char **argv) { | |||
201 | cfg.bridge1.devsandbox = "eth1"; | 202 | cfg.bridge1.devsandbox = "eth1"; |
202 | cfg.bridge2.devsandbox = "eth2"; | 203 | cfg.bridge2.devsandbox = "eth2"; |
203 | cfg.bridge3.devsandbox = "eth3"; | 204 | cfg.bridge3.devsandbox = "eth3"; |
204 | 205 | ||
205 | // extract user data | 206 | // extract user data |
206 | EUID_ROOT(); // rise permissions for grsecurity | 207 | EUID_ROOT(); // rise permissions for grsecurity |
207 | struct passwd *pw = getpwuid(getuid()); | 208 | struct passwd *pw = getpwuid(getuid()); |
@@ -249,7 +250,7 @@ void check_user_namespace(void) { | |||
249 | EUID_ASSERT(); | 250 | EUID_ASSERT(); |
250 | if (getuid() == 0) | 251 | if (getuid() == 0) |
251 | goto errout; | 252 | goto errout; |
252 | 253 | ||
253 | // test user namespaces available in the kernel | 254 | // test user namespaces available in the kernel |
254 | struct stat s1; | 255 | struct stat s1; |
255 | struct stat s2; | 256 | struct stat s2; |
@@ -280,7 +281,7 @@ static void exit_err_feature(const char *feature) { | |||
280 | // this function handles command line options such as --version and --help | 281 | // this function handles command line options such as --version and --help |
281 | static void run_cmd_and_exit(int i, int argc, char **argv) { | 282 | static void run_cmd_and_exit(int i, int argc, char **argv) { |
282 | EUID_ASSERT(); | 283 | EUID_ASSERT(); |
283 | 284 | ||
284 | //************************************* | 285 | //************************************* |
285 | // basic arguments | 286 | // basic arguments |
286 | //************************************* | 287 | //************************************* |
@@ -303,7 +304,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
303 | if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1) | 304 | if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1) |
304 | errExit("asprintf"); | 305 | errExit("asprintf"); |
305 | EUID_ROOT(); | 306 | EUID_ROOT(); |
306 | if (setreuid(0, 0) < 0 || | 307 | if (setreuid(0, 0) < 0 || |
307 | setregid(0, 0) < 0) | 308 | setregid(0, 0) < 0) |
308 | errExit("setreuid/setregid"); | 309 | errExit("setreuid/setregid"); |
309 | errno = 0; | 310 | errno = 0; |
@@ -349,11 +350,11 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
349 | exit_err_feature("x11"); | 350 | exit_err_feature("x11"); |
350 | } | 351 | } |
351 | #endif | 352 | #endif |
352 | #ifdef HAVE_NETWORK | 353 | #ifdef HAVE_NETWORK |
353 | else if (strncmp(argv[i], "--bandwidth=", 12) == 0) { | 354 | else if (strncmp(argv[i], "--bandwidth=", 12) == 0) { |
354 | if (checkcfg(CFG_NETWORK)) { | 355 | if (checkcfg(CFG_NETWORK)) { |
355 | logargs(argc, argv); | 356 | logargs(argc, argv); |
356 | 357 | ||
357 | // extract the command | 358 | // extract the command |
358 | if ((i + 1) == argc) { | 359 | if ((i + 1) == argc) { |
359 | fprintf(stderr, "Error: command expected after --bandwidth option\n"); | 360 | fprintf(stderr, "Error: command expected after --bandwidth option\n"); |
@@ -364,7 +365,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
364 | fprintf(stderr, "Error: invalid --bandwidth command.\nValid commands: set, clear, status.\n"); | 365 | fprintf(stderr, "Error: invalid --bandwidth command.\nValid commands: set, clear, status.\n"); |
365 | exit(1); | 366 | exit(1); |
366 | } | 367 | } |
367 | 368 | ||
368 | // extract network name | 369 | // extract network name |
369 | char *dev = NULL; | 370 | char *dev = NULL; |
370 | int down = 0; | 371 | int down = 0; |
@@ -376,20 +377,20 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
376 | exit(1); | 377 | exit(1); |
377 | } | 378 | } |
378 | dev = argv[i + 2]; | 379 | dev = argv[i + 2]; |
379 | 380 | ||
380 | // check device name | 381 | // check device name |
381 | if (if_nametoindex(dev) == 0) { | 382 | if (if_nametoindex(dev) == 0) { |
382 | fprintf(stderr, "Error: network device %s not found\n", dev); | 383 | fprintf(stderr, "Error: network device %s not found\n", dev); |
383 | exit(1); | 384 | exit(1); |
384 | } | 385 | } |
385 | 386 | ||
386 | // extract bandwidth | 387 | // extract bandwidth |
387 | if (strcmp(cmd, "set") == 0) { | 388 | if (strcmp(cmd, "set") == 0) { |
388 | if ((i + 4) >= argc) { | 389 | if ((i + 4) >= argc) { |
389 | fprintf(stderr, "Error: invalid --bandwidth set command\n"); | 390 | fprintf(stderr, "Error: invalid --bandwidth set command\n"); |
390 | exit(1); | 391 | exit(1); |
391 | } | 392 | } |
392 | 393 | ||
393 | down = atoi(argv[i + 3]); | 394 | down = atoi(argv[i + 3]); |
394 | if (down < 0) { | 395 | if (down < 0) { |
395 | fprintf(stderr, "Error: invalid download speed\n"); | 396 | fprintf(stderr, "Error: invalid download speed\n"); |
@@ -401,8 +402,8 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
401 | exit(1); | 402 | exit(1); |
402 | } | 403 | } |
403 | } | 404 | } |
404 | } | 405 | } |
405 | 406 | ||
406 | // extract pid or sandbox name | 407 | // extract pid or sandbox name |
407 | pid_t pid = read_pid(argv[i] + 12); | 408 | pid_t pid = read_pid(argv[i] + 12); |
408 | bandwidth_pid(pid, cmd, dev, down, up); | 409 | bandwidth_pid(pid, cmd, dev, down, up); |
@@ -450,7 +451,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
450 | else if (strncmp(argv[i], "--protocol.print=", 17) == 0) { | 451 | else if (strncmp(argv[i], "--protocol.print=", 17) == 0) { |
451 | if (checkcfg(CFG_SECCOMP)) { | 452 | if (checkcfg(CFG_SECCOMP)) { |
452 | // print seccomp filter for a sandbox specified by pid or by name | 453 | // print seccomp filter for a sandbox specified by pid or by name |
453 | pid_t pid = read_pid(argv[i] + 17); | 454 | pid_t pid = read_pid(argv[i] + 17); |
454 | protocol_print_filter(pid); | 455 | protocol_print_filter(pid); |
455 | } | 456 | } |
456 | else | 457 | else |
@@ -509,7 +510,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
509 | 2, PATH_FIREMON, "--top"); | 510 | 2, PATH_FIREMON, "--top"); |
510 | exit(0); | 511 | exit(0); |
511 | } | 512 | } |
512 | #ifdef HAVE_NETWORK | 513 | #ifdef HAVE_NETWORK |
513 | else if (strcmp(argv[i], "--netstats") == 0) { | 514 | else if (strcmp(argv[i], "--netstats") == 0) { |
514 | if (checkcfg(CFG_NETWORK)) { | 515 | if (checkcfg(CFG_NETWORK)) { |
515 | struct stat s; | 516 | struct stat s; |
@@ -524,12 +525,12 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
524 | else | 525 | else |
525 | exit_err_feature("networking"); | 526 | exit_err_feature("networking"); |
526 | } | 527 | } |
527 | #endif | 528 | #endif |
528 | #ifdef HAVE_FILE_TRANSFER | 529 | #ifdef HAVE_FILE_TRANSFER |
529 | else if (strncmp(argv[i], "--get=", 6) == 0) { | 530 | else if (strncmp(argv[i], "--get=", 6) == 0) { |
530 | if (checkcfg(CFG_FILE_TRANSFER)) { | 531 | if (checkcfg(CFG_FILE_TRANSFER)) { |
531 | logargs(argc, argv); | 532 | logargs(argc, argv); |
532 | 533 | ||
533 | // verify path | 534 | // verify path |
534 | if ((i + 2) != argc) { | 535 | if ((i + 2) != argc) { |
535 | fprintf(stderr, "Error: invalid --get option, path expected\n"); | 536 | fprintf(stderr, "Error: invalid --get option, path expected\n"); |
@@ -541,7 +542,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
541 | fprintf(stderr, "Error: invalid file name %s\n", path); | 542 | fprintf(stderr, "Error: invalid file name %s\n", path); |
542 | exit(1); | 543 | exit(1); |
543 | } | 544 | } |
544 | 545 | ||
545 | // get file | 546 | // get file |
546 | pid_t pid = read_pid(argv[i] + 6); | 547 | pid_t pid = read_pid(argv[i] + 6); |
547 | sandboxfs(SANDBOX_FS_GET, pid, path, NULL); | 548 | sandboxfs(SANDBOX_FS_GET, pid, path, NULL); |
@@ -553,7 +554,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
553 | else if (strncmp(argv[i], "--put=", 6) == 0) { | 554 | else if (strncmp(argv[i], "--put=", 6) == 0) { |
554 | if (checkcfg(CFG_FILE_TRANSFER)) { | 555 | if (checkcfg(CFG_FILE_TRANSFER)) { |
555 | logargs(argc, argv); | 556 | logargs(argc, argv); |
556 | 557 | ||
557 | // verify path | 558 | // verify path |
558 | if ((i + 3) != argc) { | 559 | if ((i + 3) != argc) { |
559 | fprintf(stderr, "Error: invalid --put option, 2 paths expected\n"); | 560 | fprintf(stderr, "Error: invalid --put option, 2 paths expected\n"); |
@@ -571,7 +572,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
571 | fprintf(stderr, "Error: invalid file name %s\n", path2); | 572 | fprintf(stderr, "Error: invalid file name %s\n", path2); |
572 | exit(1); | 573 | exit(1); |
573 | } | 574 | } |
574 | 575 | ||
575 | // get file | 576 | // get file |
576 | pid_t pid = read_pid(argv[i] + 6); | 577 | pid_t pid = read_pid(argv[i] + 6); |
577 | sandboxfs(SANDBOX_FS_PUT, pid, path1, path2); | 578 | sandboxfs(SANDBOX_FS_PUT, pid, path1, path2); |
@@ -583,7 +584,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
583 | else if (strncmp(argv[i], "--ls=", 5) == 0) { | 584 | else if (strncmp(argv[i], "--ls=", 5) == 0) { |
584 | if (checkcfg(CFG_FILE_TRANSFER)) { | 585 | if (checkcfg(CFG_FILE_TRANSFER)) { |
585 | logargs(argc, argv); | 586 | logargs(argc, argv); |
586 | 587 | ||
587 | // verify path | 588 | // verify path |
588 | if ((i + 2) != argc) { | 589 | if ((i + 2) != argc) { |
589 | fprintf(stderr, "Error: invalid --ls option, path expected\n"); | 590 | fprintf(stderr, "Error: invalid --ls option, path expected\n"); |
@@ -595,7 +596,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
595 | fprintf(stderr, "Error: invalid file name %s\n", path); | 596 | fprintf(stderr, "Error: invalid file name %s\n", path); |
596 | exit(1); | 597 | exit(1); |
597 | } | 598 | } |
598 | 599 | ||
599 | // list directory contents | 600 | // list directory contents |
600 | pid_t pid = read_pid(argv[i] + 5); | 601 | pid_t pid = read_pid(argv[i] + 5); |
601 | sandboxfs(SANDBOX_FS_LS, pid, path, NULL); | 602 | sandboxfs(SANDBOX_FS_LS, pid, path, NULL); |
@@ -608,7 +609,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
608 | else if (strncmp(argv[i], "--join=", 7) == 0) { | 609 | else if (strncmp(argv[i], "--join=", 7) == 0) { |
609 | if (checkcfg(CFG_JOIN) || getuid() == 0) { | 610 | if (checkcfg(CFG_JOIN) || getuid() == 0) { |
610 | logargs(argc, argv); | 611 | logargs(argc, argv); |
611 | 612 | ||
612 | if (arg_shell_none) { | 613 | if (arg_shell_none) { |
613 | if (argc <= (i+1)) { | 614 | if (argc <= (i+1)) { |
614 | fprintf(stderr, "Error: --shell=none set, but no command specified\n"); | 615 | fprintf(stderr, "Error: --shell=none set, but no command specified\n"); |
@@ -616,10 +617,10 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
616 | } | 617 | } |
617 | cfg.original_program_index = i + 1; | 618 | cfg.original_program_index = i + 1; |
618 | } | 619 | } |
619 | 620 | ||
620 | if (!cfg.shell && !arg_shell_none) | 621 | if (!cfg.shell && !arg_shell_none) |
621 | cfg.shell = guess_shell(); | 622 | cfg.shell = guess_shell(); |
622 | 623 | ||
623 | // join sandbox by pid or by name | 624 | // join sandbox by pid or by name |
624 | pid_t pid = read_pid(argv[i] + 7); | 625 | pid_t pid = read_pid(argv[i] + 7); |
625 | join(pid, argc, argv, i + 1); | 626 | join(pid, argc, argv, i + 1); |
@@ -652,10 +653,10 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
652 | join(pid, argc, argv, i + 1); | 653 | join(pid, argc, argv, i + 1); |
653 | exit(0); | 654 | exit(0); |
654 | } | 655 | } |
655 | #endif | 656 | #endif |
656 | // if there no such sandbox continue argument processing | 657 | // if there no such sandbox continue argument processing |
657 | } | 658 | } |
658 | #ifdef HAVE_NETWORK | 659 | #ifdef HAVE_NETWORK |
659 | else if (strncmp(argv[i], "--join-network=", 15) == 0) { | 660 | else if (strncmp(argv[i], "--join-network=", 15) == 0) { |
660 | if (checkcfg(CFG_NETWORK)) { | 661 | if (checkcfg(CFG_NETWORK)) { |
661 | logargs(argc, argv); | 662 | logargs(argc, argv); |
@@ -664,7 +665,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
664 | fprintf(stderr, "Error: --join-network is only available to root user\n"); | 665 | fprintf(stderr, "Error: --join-network is only available to root user\n"); |
665 | exit(1); | 666 | exit(1); |
666 | } | 667 | } |
667 | 668 | ||
668 | if (!cfg.shell && !arg_shell_none) | 669 | if (!cfg.shell && !arg_shell_none) |
669 | cfg.shell = guess_shell(); | 670 | cfg.shell = guess_shell(); |
670 | 671 | ||
@@ -684,7 +685,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
684 | fprintf(stderr, "Error: --join-filesystem is only available to root user\n"); | 685 | fprintf(stderr, "Error: --join-filesystem is only available to root user\n"); |
685 | exit(1); | 686 | exit(1); |
686 | } | 687 | } |
687 | 688 | ||
688 | if (!cfg.shell && !arg_shell_none) | 689 | if (!cfg.shell && !arg_shell_none) |
689 | cfg.shell = guess_shell(); | 690 | cfg.shell = guess_shell(); |
690 | 691 | ||
@@ -695,7 +696,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
695 | } | 696 | } |
696 | else if (strncmp(argv[i], "--shutdown=", 11) == 0) { | 697 | else if (strncmp(argv[i], "--shutdown=", 11) == 0) { |
697 | logargs(argc, argv); | 698 | logargs(argc, argv); |
698 | 699 | ||
699 | // shutdown sandbox by pid or by name | 700 | // shutdown sandbox by pid or by name |
700 | pid_t pid = read_pid(argv[i] + 11); | 701 | pid_t pid = read_pid(argv[i] + 11); |
701 | shut(pid); | 702 | shut(pid); |
@@ -801,7 +802,7 @@ static int check_arg(int argc, char **argv, const char *argument) { | |||
801 | if (strncmp(argv[i], "--", 2) != 0) | 802 | if (strncmp(argv[i], "--", 2) != 0) |
802 | break; | 803 | break; |
803 | } | 804 | } |
804 | 805 | ||
805 | return found; | 806 | return found; |
806 | } | 807 | } |
807 | 808 | ||
@@ -825,7 +826,7 @@ int main(int argc, char **argv) { | |||
825 | 826 | ||
826 | // build /run/firejail directory structure | 827 | // build /run/firejail directory structure |
827 | preproc_build_firejail_dir(); | 828 | preproc_build_firejail_dir(); |
828 | 829 | ||
829 | if (check_arg(argc, argv, "--quiet")) | 830 | if (check_arg(argc, argv, "--quiet")) |
830 | arg_quiet = 1; | 831 | arg_quiet = 1; |
831 | if (check_arg(argc, argv, "--allow-debuggers")) { | 832 | if (check_arg(argc, argv, "--allow-debuggers")) { |
@@ -870,7 +871,7 @@ int main(int argc, char **argv) { | |||
870 | // If LXC is detected, start firejail sandbox | 871 | // If LXC is detected, start firejail sandbox |
871 | // otherwise try to detect a PID namespace by looking under /proc for specific kernel processes and: | 872 | // otherwise try to detect a PID namespace by looking under /proc for specific kernel processes and: |
872 | // - if --force flag is set, start firejail sandbox | 873 | // - if --force flag is set, start firejail sandbox |
873 | // -- if --force flag is not set, start the application in a /bin/bash shell | 874 | // -- if --force flag is not set, start the application in a /bin/bash shell |
874 | if (check_namespace_virt() == 0) { | 875 | if (check_namespace_virt() == 0) { |
875 | EUID_ROOT(); | 876 | EUID_ROOT(); |
876 | int rv = check_kernel_procs(); | 877 | int rv = check_kernel_procs(); |
@@ -884,7 +885,7 @@ int main(int argc, char **argv) { | |||
884 | printf("firejail version %s\n", VERSION); | 885 | printf("firejail version %s\n", VERSION); |
885 | exit(0); | 886 | exit(0); |
886 | } | 887 | } |
887 | 888 | ||
888 | // start the program directly without sandboxing | 889 | // start the program directly without sandboxing |
889 | run_no_sandbox(argc, argv); | 890 | run_no_sandbox(argc, argv); |
890 | // it will never get here! | 891 | // it will never get here! |
@@ -916,9 +917,9 @@ int main(int argc, char **argv) { | |||
916 | network_del_run_file(sandbox_pid); | 917 | network_del_run_file(sandbox_pid); |
917 | delete_name_file(sandbox_pid); | 918 | delete_name_file(sandbox_pid); |
918 | delete_x11_file(sandbox_pid); | 919 | delete_x11_file(sandbox_pid); |
919 | 920 | ||
920 | EUID_USER(); | 921 | EUID_USER(); |
921 | 922 | ||
922 | //check if the parent is sshd daemon | 923 | //check if the parent is sshd daemon |
923 | int parent_sshd = 0; | 924 | int parent_sshd = 0; |
924 | { | 925 | { |
@@ -959,7 +960,7 @@ int main(int argc, char **argv) { | |||
959 | } | 960 | } |
960 | EUID_USER();} | 961 | EUID_USER();} |
961 | #endif | 962 | #endif |
962 | 963 | ||
963 | drop_privs(1); | 964 | drop_privs(1); |
964 | int rv = system(argv[2]); | 965 | int rv = system(argv[2]); |
965 | exit(rv); | 966 | exit(rv); |
@@ -970,14 +971,14 @@ int main(int argc, char **argv) { | |||
970 | free(comm); | 971 | free(comm); |
971 | } | 972 | } |
972 | } | 973 | } |
973 | 974 | ||
974 | // is this a login shell, or a command passed by sshd, insert command line options from /etc/firejail/login.users | 975 | // is this a login shell, or a command passed by sshd, insert command line options from /etc/firejail/login.users |
975 | if (*argv[0] == '-' || parent_sshd) { | 976 | if (*argv[0] == '-' || parent_sshd) { |
976 | if (argc == 1) | 977 | if (argc == 1) |
977 | login_shell = 1; | 978 | login_shell = 1; |
978 | fullargc = restricted_shell(cfg.username); | 979 | fullargc = restricted_shell(cfg.username); |
979 | if (fullargc) { | 980 | if (fullargc) { |
980 | 981 | ||
981 | #ifdef DEBUG_RESTRICTED_SHELL | 982 | #ifdef DEBUG_RESTRICTED_SHELL |
982 | {EUID_ROOT(); | 983 | {EUID_ROOT(); |
983 | FILE *fp = fopen("/firelog", "a"); | 984 | FILE *fp = fopen("/firelog", "a"); |
@@ -991,7 +992,7 @@ int main(int argc, char **argv) { | |||
991 | } | 992 | } |
992 | EUID_USER();} | 993 | EUID_USER();} |
993 | #endif | 994 | #endif |
994 | 995 | ||
995 | int j; | 996 | int j; |
996 | for (i = 1, j = fullargc; i < argc && j < MAX_ARGS; i++, j++, fullargc++) | 997 | for (i = 1, j = fullargc; i < argc && j < MAX_ARGS; i++, j++, fullargc++) |
997 | fullargv[j] = argv[i]; | 998 | fullargv[j] = argv[i]; |
@@ -1019,23 +1020,23 @@ int main(int argc, char **argv) { | |||
1019 | // check --output option and execute it; | 1020 | // check --output option and execute it; |
1020 | check_output(argc, argv); // the function will not return if --output option was found | 1021 | check_output(argc, argv); // the function will not return if --output option was found |
1021 | } | 1022 | } |
1022 | 1023 | ||
1023 | 1024 | ||
1024 | // check for force-nonewprivs in /etc/firejail/firejail.config file | 1025 | // check for force-nonewprivs in /etc/firejail/firejail.config file |
1025 | if (checkcfg(CFG_FORCE_NONEWPRIVS)) | 1026 | if (checkcfg(CFG_FORCE_NONEWPRIVS)) |
1026 | arg_nonewprivs = 1; | 1027 | arg_nonewprivs = 1; |
1027 | 1028 | ||
1028 | if (arg_allow_debuggers) { | 1029 | if (arg_allow_debuggers) { |
1029 | char *cmd = strdup("noblacklist ${PATH}/strace"); | 1030 | char *cmd = strdup("noblacklist ${PATH}/strace"); |
1030 | if (!cmd) | 1031 | if (!cmd) |
1031 | errExit("strdup"); | 1032 | errExit("strdup"); |
1032 | profile_add(cmd); | 1033 | profile_add(cmd); |
1033 | } | 1034 | } |
1034 | 1035 | ||
1035 | // parse arguments | 1036 | // parse arguments |
1036 | for (i = 1; i < argc; i++) { | 1037 | for (i = 1; i < argc; i++) { |
1037 | run_cmd_and_exit(i, argc, argv); // will exit if the command is recognized | 1038 | run_cmd_and_exit(i, argc, argv); // will exit if the command is recognized |
1038 | 1039 | ||
1039 | if (strcmp(argv[i], "--debug") == 0) { | 1040 | if (strcmp(argv[i], "--debug") == 0) { |
1040 | if (!arg_quiet) { | 1041 | if (!arg_quiet) { |
1041 | arg_debug = 1; | 1042 | arg_debug = 1; |
@@ -1065,7 +1066,7 @@ int main(int argc, char **argv) { | |||
1065 | #ifdef HAVE_APPARMOR | 1066 | #ifdef HAVE_APPARMOR |
1066 | else if (strcmp(argv[i], "--apparmor") == 0) | 1067 | else if (strcmp(argv[i], "--apparmor") == 0) |
1067 | arg_apparmor = 1; | 1068 | arg_apparmor = 1; |
1068 | #endif | 1069 | #endif |
1069 | #ifdef HAVE_SECCOMP | 1070 | #ifdef HAVE_SECCOMP |
1070 | else if (strncmp(argv[i], "--protocol=", 11) == 0) { | 1071 | else if (strncmp(argv[i], "--protocol=", 11) == 0) { |
1071 | if (checkcfg(CFG_SECCOMP)) { | 1072 | if (checkcfg(CFG_SECCOMP)) { |
@@ -1079,7 +1080,7 @@ int main(int argc, char **argv) { | |||
1079 | errExit("strdup"); | 1080 | errExit("strdup"); |
1080 | } | 1081 | } |
1081 | } | 1082 | } |
1082 | else | 1083 | else |
1083 | exit_err_feature("seccomp"); | 1084 | exit_err_feature("seccomp"); |
1084 | } | 1085 | } |
1085 | else if (strcmp(argv[i], "--seccomp") == 0) { | 1086 | else if (strcmp(argv[i], "--seccomp") == 0) { |
@@ -1129,7 +1130,7 @@ int main(int argc, char **argv) { | |||
1129 | else | 1130 | else |
1130 | exit_err_feature("seccomp"); | 1131 | exit_err_feature("seccomp"); |
1131 | } | 1132 | } |
1132 | #endif | 1133 | #endif |
1133 | else if (strcmp(argv[i], "--caps") == 0) | 1134 | else if (strcmp(argv[i], "--caps") == 0) |
1134 | arg_caps_default_filter = 1; | 1135 | arg_caps_default_filter = 1; |
1135 | else if (strcmp(argv[i], "--caps.drop=all") == 0) | 1136 | else if (strcmp(argv[i], "--caps.drop=all") == 0) |
@@ -1160,22 +1161,22 @@ int main(int argc, char **argv) { | |||
1160 | check_unsigned(argv[i] + 16, "Error: invalid rlimit"); | 1161 | check_unsigned(argv[i] + 16, "Error: invalid rlimit"); |
1161 | sscanf(argv[i] + 16, "%llu", &cfg.rlimit_nofile); | 1162 | sscanf(argv[i] + 16, "%llu", &cfg.rlimit_nofile); |
1162 | arg_rlimit_nofile = 1; | 1163 | arg_rlimit_nofile = 1; |
1163 | } | 1164 | } |
1164 | else if (strncmp(argv[i], "--rlimit-nproc=", 15) == 0) { | 1165 | else if (strncmp(argv[i], "--rlimit-nproc=", 15) == 0) { |
1165 | check_unsigned(argv[i] + 15, "Error: invalid rlimit"); | 1166 | check_unsigned(argv[i] + 15, "Error: invalid rlimit"); |
1166 | sscanf(argv[i] + 15, "%llu", &cfg.rlimit_nproc); | 1167 | sscanf(argv[i] + 15, "%llu", &cfg.rlimit_nproc); |
1167 | arg_rlimit_nproc = 1; | 1168 | arg_rlimit_nproc = 1; |
1168 | } | 1169 | } |
1169 | else if (strncmp(argv[i], "--rlimit-fsize=", 15) == 0) { | 1170 | else if (strncmp(argv[i], "--rlimit-fsize=", 15) == 0) { |
1170 | check_unsigned(argv[i] + 15, "Error: invalid rlimit"); | 1171 | check_unsigned(argv[i] + 15, "Error: invalid rlimit"); |
1171 | sscanf(argv[i] + 15, "%llu", &cfg.rlimit_fsize); | 1172 | sscanf(argv[i] + 15, "%llu", &cfg.rlimit_fsize); |
1172 | arg_rlimit_fsize = 1; | 1173 | arg_rlimit_fsize = 1; |
1173 | } | 1174 | } |
1174 | else if (strncmp(argv[i], "--rlimit-sigpending=", 20) == 0) { | 1175 | else if (strncmp(argv[i], "--rlimit-sigpending=", 20) == 0) { |
1175 | check_unsigned(argv[i] + 20, "Error: invalid rlimit"); | 1176 | check_unsigned(argv[i] + 20, "Error: invalid rlimit"); |
1176 | sscanf(argv[i] + 20, "%llu", &cfg.rlimit_sigpending); | 1177 | sscanf(argv[i] + 20, "%llu", &cfg.rlimit_sigpending); |
1177 | arg_rlimit_sigpending = 1; | 1178 | arg_rlimit_sigpending = 1; |
1178 | } | 1179 | } |
1179 | else if (strncmp(argv[i], "--ipc-namespace", 15) == 0) | 1180 | else if (strncmp(argv[i], "--ipc-namespace", 15) == 0) |
1180 | arg_ipc = 1; | 1181 | arg_ipc = 1; |
1181 | else if (strncmp(argv[i], "--cpu=", 6) == 0) | 1182 | else if (strncmp(argv[i], "--cpu=", 6) == 0) |
@@ -1191,26 +1192,26 @@ int main(int argc, char **argv) { | |||
1191 | fprintf(stderr, "Error: only a cgroup can be defined\n"); | 1192 | fprintf(stderr, "Error: only a cgroup can be defined\n"); |
1192 | exit(1); | 1193 | exit(1); |
1193 | } | 1194 | } |
1194 | 1195 | ||
1195 | option_cgroup = 1; | 1196 | option_cgroup = 1; |
1196 | cfg.cgroup = strdup(argv[i] + 9); | 1197 | cfg.cgroup = strdup(argv[i] + 9); |
1197 | if (!cfg.cgroup) | 1198 | if (!cfg.cgroup) |
1198 | errExit("strdup"); | 1199 | errExit("strdup"); |
1199 | set_cgroup(cfg.cgroup); | 1200 | set_cgroup(cfg.cgroup); |
1200 | } | 1201 | } |
1201 | 1202 | ||
1202 | //************************************* | 1203 | //************************************* |
1203 | // filesystem | 1204 | // filesystem |
1204 | //************************************* | 1205 | //************************************* |
1205 | else if (strcmp(argv[i], "--allusers") == 0) | 1206 | else if (strcmp(argv[i], "--allusers") == 0) |
1206 | arg_allusers = 1; | 1207 | arg_allusers = 1; |
1207 | #ifdef HAVE_BIND | 1208 | #ifdef HAVE_BIND |
1208 | else if (strncmp(argv[i], "--bind=", 7) == 0) { | 1209 | else if (strncmp(argv[i], "--bind=", 7) == 0) { |
1209 | if (checkcfg(CFG_BIND)) { | 1210 | if (checkcfg(CFG_BIND)) { |
1210 | char *line; | 1211 | char *line; |
1211 | if (asprintf(&line, "bind %s", argv[i] + 7) == -1) | 1212 | if (asprintf(&line, "bind %s", argv[i] + 7) == -1) |
1212 | errExit("asprintf"); | 1213 | errExit("asprintf"); |
1213 | 1214 | ||
1214 | profile_check_line(line, 0, NULL); // will exit if something wrong | 1215 | profile_check_line(line, 0, NULL); // will exit if something wrong |
1215 | profile_add(line); | 1216 | profile_add(line); |
1216 | } | 1217 | } |
@@ -1222,7 +1223,7 @@ int main(int argc, char **argv) { | |||
1222 | char *line; | 1223 | char *line; |
1223 | if (asprintf(&line, "tmpfs %s", argv[i] + 8) == -1) | 1224 | if (asprintf(&line, "tmpfs %s", argv[i] + 8) == -1) |
1224 | errExit("asprintf"); | 1225 | errExit("asprintf"); |
1225 | 1226 | ||
1226 | profile_check_line(line, 0, NULL); // will exit if something wrong | 1227 | profile_check_line(line, 0, NULL); // will exit if something wrong |
1227 | profile_add(line); | 1228 | profile_add(line); |
1228 | } | 1229 | } |
@@ -1230,7 +1231,7 @@ int main(int argc, char **argv) { | |||
1230 | char *line; | 1231 | char *line; |
1231 | if (asprintf(&line, "blacklist %s", argv[i] + 12) == -1) | 1232 | if (asprintf(&line, "blacklist %s", argv[i] + 12) == -1) |
1232 | errExit("asprintf"); | 1233 | errExit("asprintf"); |
1233 | 1234 | ||
1234 | profile_check_line(line, 0, NULL); // will exit if something wrong | 1235 | profile_check_line(line, 0, NULL); // will exit if something wrong |
1235 | profile_add(line); | 1236 | profile_add(line); |
1236 | } | 1237 | } |
@@ -1238,7 +1239,7 @@ int main(int argc, char **argv) { | |||
1238 | char *line; | 1239 | char *line; |
1239 | if (asprintf(&line, "noblacklist %s", argv[i] + 14) == -1) | 1240 | if (asprintf(&line, "noblacklist %s", argv[i] + 14) == -1) |
1240 | errExit("asprintf"); | 1241 | errExit("asprintf"); |
1241 | 1242 | ||
1242 | profile_check_line(line, 0, NULL); // will exit if something wrong | 1243 | profile_check_line(line, 0, NULL); // will exit if something wrong |
1243 | profile_add(line); | 1244 | profile_add(line); |
1244 | } | 1245 | } |
@@ -1249,7 +1250,7 @@ int main(int argc, char **argv) { | |||
1249 | char *line; | 1250 | char *line; |
1250 | if (asprintf(&line, "whitelist %s", argv[i] + 12) == -1) | 1251 | if (asprintf(&line, "whitelist %s", argv[i] + 12) == -1) |
1251 | errExit("asprintf"); | 1252 | errExit("asprintf"); |
1252 | 1253 | ||
1253 | profile_check_line(line, 0, NULL); // will exit if something wrong | 1254 | profile_check_line(line, 0, NULL); // will exit if something wrong |
1254 | profile_add(line); | 1255 | profile_add(line); |
1255 | } | 1256 | } |
@@ -1260,17 +1261,17 @@ int main(int argc, char **argv) { | |||
1260 | char *line; | 1261 | char *line; |
1261 | if (asprintf(&line, "nowhitelist %s", argv[i] + 14) == -1) | 1262 | if (asprintf(&line, "nowhitelist %s", argv[i] + 14) == -1) |
1262 | errExit("asprintf"); | 1263 | errExit("asprintf"); |
1263 | 1264 | ||
1264 | profile_check_line(line, 0, NULL); // will exit if something wrong | 1265 | profile_check_line(line, 0, NULL); // will exit if something wrong |
1265 | profile_add(line); | 1266 | profile_add(line); |
1266 | } | 1267 | } |
1267 | #endif | 1268 | #endif |
1268 | 1269 | ||
1269 | else if (strncmp(argv[i], "--read-only=", 12) == 0) { | 1270 | else if (strncmp(argv[i], "--read-only=", 12) == 0) { |
1270 | char *line; | 1271 | char *line; |
1271 | if (asprintf(&line, "read-only %s", argv[i] + 12) == -1) | 1272 | if (asprintf(&line, "read-only %s", argv[i] + 12) == -1) |
1272 | errExit("asprintf"); | 1273 | errExit("asprintf"); |
1273 | 1274 | ||
1274 | profile_check_line(line, 0, NULL); // will exit if something wrong | 1275 | profile_check_line(line, 0, NULL); // will exit if something wrong |
1275 | profile_add(line); | 1276 | profile_add(line); |
1276 | } | 1277 | } |
@@ -1278,7 +1279,7 @@ int main(int argc, char **argv) { | |||
1278 | char *line; | 1279 | char *line; |
1279 | if (asprintf(&line, "noexec %s", argv[i] + 9) == -1) | 1280 | if (asprintf(&line, "noexec %s", argv[i] + 9) == -1) |
1280 | errExit("asprintf"); | 1281 | errExit("asprintf"); |
1281 | 1282 | ||
1282 | profile_check_line(line, 0, NULL); // will exit if something wrong | 1283 | profile_check_line(line, 0, NULL); // will exit if something wrong |
1283 | profile_add(line); | 1284 | profile_add(line); |
1284 | } | 1285 | } |
@@ -1286,7 +1287,7 @@ int main(int argc, char **argv) { | |||
1286 | char *line; | 1287 | char *line; |
1287 | if (asprintf(&line, "read-write %s", argv[i] + 13) == -1) | 1288 | if (asprintf(&line, "read-write %s", argv[i] + 13) == -1) |
1288 | errExit("asprintf"); | 1289 | errExit("asprintf"); |
1289 | 1290 | ||
1290 | profile_check_line(line, 0, NULL); // will exit if something wrong | 1291 | profile_check_line(line, 0, NULL); // will exit if something wrong |
1291 | profile_add(line); | 1292 | profile_add(line); |
1292 | } | 1293 | } |
@@ -1300,16 +1301,16 @@ int main(int argc, char **argv) { | |||
1300 | struct stat s; | 1301 | struct stat s; |
1301 | if (stat("/proc/sys/kernel/grsecurity", &s) == 0) { | 1302 | if (stat("/proc/sys/kernel/grsecurity", &s) == 0) { |
1302 | fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n"); | 1303 | fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n"); |
1303 | exit(1); | 1304 | exit(1); |
1304 | } | 1305 | } |
1305 | arg_overlay = 1; | 1306 | arg_overlay = 1; |
1306 | arg_overlay_keep = 1; | 1307 | arg_overlay_keep = 1; |
1307 | 1308 | ||
1308 | char *subdirname; | 1309 | char *subdirname; |
1309 | if (asprintf(&subdirname, "%d", getpid()) == -1) | 1310 | if (asprintf(&subdirname, "%d", getpid()) == -1) |
1310 | errExit("asprintf"); | 1311 | errExit("asprintf"); |
1311 | cfg.overlay_dir = fs_check_overlay_dir(subdirname, arg_overlay_reuse); | 1312 | cfg.overlay_dir = fs_check_overlay_dir(subdirname, arg_overlay_reuse); |
1312 | 1313 | ||
1313 | free(subdirname); | 1314 | free(subdirname); |
1314 | } | 1315 | } |
1315 | else | 1316 | else |
@@ -1329,13 +1330,13 @@ int main(int argc, char **argv) { | |||
1329 | arg_overlay = 1; | 1330 | arg_overlay = 1; |
1330 | arg_overlay_keep = 1; | 1331 | arg_overlay_keep = 1; |
1331 | arg_overlay_reuse = 1; | 1332 | arg_overlay_reuse = 1; |
1332 | 1333 | ||
1333 | char *subdirname = argv[i] + 16; | 1334 | char *subdirname = argv[i] + 16; |
1334 | if (subdirname == '\0') { | 1335 | if (subdirname == '\0') { |
1335 | fprintf(stderr, "Error: invalid overlay option\n"); | 1336 | fprintf(stderr, "Error: invalid overlay option\n"); |
1336 | exit(1); | 1337 | exit(1); |
1337 | } | 1338 | } |
1338 | 1339 | ||
1339 | // check name | 1340 | // check name |
1340 | invalid_filename(subdirname); | 1341 | invalid_filename(subdirname); |
1341 | if (strstr(subdirname, "..") || strstr(subdirname, "/")) { | 1342 | if (strstr(subdirname, "..") || strstr(subdirname, "/")) { |
@@ -1356,7 +1357,7 @@ int main(int argc, char **argv) { | |||
1356 | struct stat s; | 1357 | struct stat s; |
1357 | if (stat("/proc/sys/kernel/grsecurity", &s) == 0) { | 1358 | if (stat("/proc/sys/kernel/grsecurity", &s) == 0) { |
1358 | fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n"); | 1359 | fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n"); |
1359 | exit(1); | 1360 | exit(1); |
1360 | } | 1361 | } |
1361 | arg_overlay = 1; | 1362 | arg_overlay = 1; |
1362 | } | 1363 | } |
@@ -1371,7 +1372,7 @@ int main(int argc, char **argv) { | |||
1371 | fprintf(stderr, "Error: --noprofile and --profile options are mutually exclusive\n"); | 1372 | fprintf(stderr, "Error: --noprofile and --profile options are mutually exclusive\n"); |
1372 | exit(1); | 1373 | exit(1); |
1373 | } | 1374 | } |
1374 | 1375 | ||
1375 | char *ppath = expand_home(argv[i] + 10, cfg.homedir); | 1376 | char *ppath = expand_home(argv[i] + 10, cfg.homedir); |
1376 | if (!ppath) | 1377 | if (!ppath) |
1377 | errExit("strdup"); | 1378 | errExit("strdup"); |
@@ -1391,7 +1392,7 @@ int main(int argc, char **argv) { | |||
1391 | fprintf(stderr, "Error: invalid profile path\n"); | 1392 | fprintf(stderr, "Error: invalid profile path\n"); |
1392 | exit(1); | 1393 | exit(1); |
1393 | } | 1394 | } |
1394 | 1395 | ||
1395 | // access call checks as real UID/GID, not as effective UID/GID | 1396 | // access call checks as real UID/GID, not as effective UID/GID |
1396 | if (access(custom_profile_dir, R_OK)) { | 1397 | if (access(custom_profile_dir, R_OK)) { |
1397 | fprintf(stderr, "Error: cannot access profile directory\n"); | 1398 | fprintf(stderr, "Error: cannot access profile directory\n"); |
@@ -1415,11 +1416,11 @@ int main(int argc, char **argv) { | |||
1415 | fprintf(stderr, "Error: invalid ignore option\n"); | 1416 | fprintf(stderr, "Error: invalid ignore option\n"); |
1416 | exit(1); | 1417 | exit(1); |
1417 | } | 1418 | } |
1418 | 1419 | ||
1419 | // find an empty entry in profile_ignore array | 1420 | // find an empty entry in profile_ignore array |
1420 | int j; | 1421 | int j; |
1421 | for (j = 0; j < MAX_PROFILE_IGNORE; j++) { | 1422 | for (j = 0; j < MAX_PROFILE_IGNORE; j++) { |
1422 | if (cfg.profile_ignore[j] == NULL) | 1423 | if (cfg.profile_ignore[j] == NULL) |
1423 | break; | 1424 | break; |
1424 | } | 1425 | } |
1425 | if (j >= MAX_PROFILE_IGNORE) { | 1426 | if (j >= MAX_PROFILE_IGNORE) { |
@@ -1430,23 +1431,23 @@ int main(int argc, char **argv) { | |||
1430 | else | 1431 | else |
1431 | cfg.profile_ignore[j] = argv[i] + 9; | 1432 | cfg.profile_ignore[j] = argv[i] + 9; |
1432 | } | 1433 | } |
1433 | #ifdef HAVE_CHROOT | 1434 | #ifdef HAVE_CHROOT |
1434 | else if (strncmp(argv[i], "--chroot=", 9) == 0) { | 1435 | else if (strncmp(argv[i], "--chroot=", 9) == 0) { |
1435 | if (checkcfg(CFG_CHROOT)) { | 1436 | if (checkcfg(CFG_CHROOT)) { |
1436 | if (arg_overlay) { | 1437 | if (arg_overlay) { |
1437 | fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); | 1438 | fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); |
1438 | exit(1); | 1439 | exit(1); |
1439 | } | 1440 | } |
1440 | 1441 | ||
1441 | struct stat s; | 1442 | struct stat s; |
1442 | if (stat("/proc/sys/kernel/grsecurity", &s) == 0) { | 1443 | if (stat("/proc/sys/kernel/grsecurity", &s) == 0) { |
1443 | fprintf(stderr, "Error: --chroot option is not available on Grsecurity systems\n"); | 1444 | fprintf(stderr, "Error: --chroot option is not available on Grsecurity systems\n"); |
1444 | exit(1); | 1445 | exit(1); |
1445 | } | 1446 | } |
1446 | 1447 | ||
1447 | 1448 | ||
1448 | invalid_filename(argv[i] + 9); | 1449 | invalid_filename(argv[i] + 9); |
1449 | 1450 | ||
1450 | // extract chroot dirname | 1451 | // extract chroot dirname |
1451 | cfg.chrootdir = argv[i] + 9; | 1452 | cfg.chrootdir = argv[i] + 9; |
1452 | // if the directory starts with ~, expand the home directory | 1453 | // if the directory starts with ~, expand the home directory |
@@ -1456,13 +1457,13 @@ int main(int argc, char **argv) { | |||
1456 | errExit("asprintf"); | 1457 | errExit("asprintf"); |
1457 | cfg.chrootdir = tmp; | 1458 | cfg.chrootdir = tmp; |
1458 | } | 1459 | } |
1459 | 1460 | ||
1460 | // check chroot dirname exists | 1461 | // check chroot dirname exists |
1461 | if (strstr(cfg.chrootdir, "..") || !is_dir(cfg.chrootdir) || is_link(cfg.chrootdir)) { | 1462 | if (strstr(cfg.chrootdir, "..") || !is_dir(cfg.chrootdir) || is_link(cfg.chrootdir)) { |
1462 | fprintf(stderr, "Error: invalid directory %s\n", cfg.chrootdir); | 1463 | fprintf(stderr, "Error: invalid directory %s\n", cfg.chrootdir); |
1463 | return 1; | 1464 | return 1; |
1464 | } | 1465 | } |
1465 | 1466 | ||
1466 | // don't allow "--chroot=/" | 1467 | // don't allow "--chroot=/" |
1467 | char *rpath = realpath(cfg.chrootdir, NULL); | 1468 | char *rpath = realpath(cfg.chrootdir, NULL); |
1468 | if (rpath == NULL || strcmp(rpath, "/") == 0) { | 1469 | if (rpath == NULL || strcmp(rpath, "/") == 0) { |
@@ -1470,7 +1471,7 @@ int main(int argc, char **argv) { | |||
1470 | exit(1); | 1471 | exit(1); |
1471 | } | 1472 | } |
1472 | cfg.chrootdir = rpath; | 1473 | cfg.chrootdir = rpath; |
1473 | 1474 | ||
1474 | // check chroot directory structure | 1475 | // check chroot directory structure |
1475 | fs_check_chroot_dir(cfg.chrootdir); | 1476 | fs_check_chroot_dir(cfg.chrootdir); |
1476 | } | 1477 | } |
@@ -1528,7 +1529,7 @@ int main(int argc, char **argv) { | |||
1528 | fprintf(stderr, "Error: a private home directory was already defined with --private option.\n"); | 1529 | fprintf(stderr, "Error: a private home directory was already defined with --private option.\n"); |
1529 | exit(1); | 1530 | exit(1); |
1530 | } | 1531 | } |
1531 | 1532 | ||
1532 | // extract private home dirname | 1533 | // extract private home dirname |
1533 | if (*(argv[i] + 15) == '\0') { | 1534 | if (*(argv[i] + 15) == '\0') { |
1534 | fprintf(stderr, "Error: invalid private-home option\n"); | 1535 | fprintf(stderr, "Error: invalid private-home option\n"); |
@@ -1544,7 +1545,7 @@ int main(int argc, char **argv) { | |||
1544 | else | 1545 | else |
1545 | exit_err_feature("private-home"); | 1546 | exit_err_feature("private-home"); |
1546 | } | 1547 | } |
1547 | #endif | 1548 | #endif |
1548 | else if (strcmp(argv[i], "--private-dev") == 0) { | 1549 | else if (strcmp(argv[i], "--private-dev") == 0) { |
1549 | arg_private_dev = 1; | 1550 | arg_private_dev = 1; |
1550 | } | 1551 | } |
@@ -1553,7 +1554,7 @@ int main(int argc, char **argv) { | |||
1553 | fprintf(stderr, "Error: --private-etc and --writable-etc are mutually exclusive\n"); | 1554 | fprintf(stderr, "Error: --private-etc and --writable-etc are mutually exclusive\n"); |
1554 | exit(1); | 1555 | exit(1); |
1555 | } | 1556 | } |
1556 | 1557 | ||
1557 | // extract private etc list | 1558 | // extract private etc list |
1558 | if (*(argv[i] + 14) == '\0') { | 1559 | if (*(argv[i] + 14) == '\0') { |
1559 | fprintf(stderr, "Error: invalid private-etc option\n"); | 1560 | fprintf(stderr, "Error: invalid private-etc option\n"); |
@@ -1646,14 +1647,17 @@ int main(int argc, char **argv) { | |||
1646 | else if (strcmp(argv[i], "--nosound") == 0) { | 1647 | else if (strcmp(argv[i], "--nosound") == 0) { |
1647 | arg_nosound = 1; | 1648 | arg_nosound = 1; |
1648 | } | 1649 | } |
1650 | else if (strcmp(argv[i], "--novideo") == 0) { | ||
1651 | arg_novideo = 1; | ||
1652 | } | ||
1649 | else if (strcmp(argv[i], "--no3d") == 0) { | 1653 | else if (strcmp(argv[i], "--no3d") == 0) { |
1650 | arg_no3d = 1; | 1654 | arg_no3d = 1; |
1651 | } | 1655 | } |
1652 | 1656 | ||
1653 | //************************************* | 1657 | //************************************* |
1654 | // network | 1658 | // network |
1655 | //************************************* | 1659 | //************************************* |
1656 | #ifdef HAVE_NETWORK | 1660 | #ifdef HAVE_NETWORK |
1657 | else if (strncmp(argv[i], "--interface=", 12) == 0) { | 1661 | else if (strncmp(argv[i], "--interface=", 12) == 0) { |
1658 | if (checkcfg(CFG_NETWORK)) { | 1662 | if (checkcfg(CFG_NETWORK)) { |
1659 | #ifdef HAVE_NETWORK_RESTRICTED | 1663 | #ifdef HAVE_NETWORK_RESTRICTED |
@@ -1668,7 +1672,7 @@ int main(int argc, char **argv) { | |||
1668 | fprintf(stderr, "Error: --interface is allowed only to root user\n"); | 1672 | fprintf(stderr, "Error: --interface is allowed only to root user\n"); |
1669 | exit(1); | 1673 | exit(1); |
1670 | } | 1674 | } |
1671 | 1675 | ||
1672 | // checks | 1676 | // checks |
1673 | if (arg_nonetwork) { | 1677 | if (arg_nonetwork) { |
1674 | fprintf(stderr, "Error: --network=none and --interface are incompatible\n"); | 1678 | fprintf(stderr, "Error: --network=none and --interface are incompatible\n"); |
@@ -1683,7 +1687,7 @@ int main(int argc, char **argv) { | |||
1683 | fprintf(stderr, "Error: cannot find interface %s\n", argv[i] + 12); | 1687 | fprintf(stderr, "Error: cannot find interface %s\n", argv[i] + 12); |
1684 | exit(1); | 1688 | exit(1); |
1685 | } | 1689 | } |
1686 | 1690 | ||
1687 | Interface *intf; | 1691 | Interface *intf; |
1688 | if (cfg.interface0.configured == 0) | 1692 | if (cfg.interface0.configured == 0) |
1689 | intf = &cfg.interface0; | 1693 | intf = &cfg.interface0; |
@@ -1697,11 +1701,11 @@ int main(int argc, char **argv) { | |||
1697 | fprintf(stderr, "Error: maximum 4 interfaces are allowed\n"); | 1701 | fprintf(stderr, "Error: maximum 4 interfaces are allowed\n"); |
1698 | return 1; | 1702 | return 1; |
1699 | } | 1703 | } |
1700 | 1704 | ||
1701 | intf->dev = strdup(argv[i] + 12); | 1705 | intf->dev = strdup(argv[i] + 12); |
1702 | if (!intf->dev) | 1706 | if (!intf->dev) |
1703 | errExit("strdup"); | 1707 | errExit("strdup"); |
1704 | 1708 | ||
1705 | if (net_get_if_addr(intf->dev, &intf->ip, &intf->mask, intf->mac, &intf->mtu)) { | 1709 | if (net_get_if_addr(intf->dev, &intf->ip, &intf->mask, intf->mac, &intf->mtu)) { |
1706 | fwarning("interface %s is not configured\n", intf->dev); | 1710 | fwarning("interface %s is not configured\n", intf->dev); |
1707 | } | 1711 | } |
@@ -1742,7 +1746,7 @@ int main(int argc, char **argv) { | |||
1742 | fprintf(stderr, "Error: cannot attach to lo device\n"); | 1746 | fprintf(stderr, "Error: cannot attach to lo device\n"); |
1743 | exit(1); | 1747 | exit(1); |
1744 | } | 1748 | } |
1745 | 1749 | ||
1746 | Bridge *br; | 1750 | Bridge *br; |
1747 | if (cfg.bridge0.configured == 0) | 1751 | if (cfg.bridge0.configured == 0) |
1748 | br = &cfg.bridge0; | 1752 | br = &cfg.bridge0; |
@@ -1799,7 +1803,7 @@ int main(int argc, char **argv) { | |||
1799 | fprintf(stderr, "Error: cannot configure the IP range twice for the same interface\n"); | 1803 | fprintf(stderr, "Error: cannot configure the IP range twice for the same interface\n"); |
1800 | return 1; | 1804 | return 1; |
1801 | } | 1805 | } |
1802 | 1806 | ||
1803 | // parse option arguments | 1807 | // parse option arguments |
1804 | char *firstip = argv[i] + 10; | 1808 | char *firstip = argv[i] + 10; |
1805 | char *secondip = firstip; | 1809 | char *secondip = firstip; |
@@ -1814,7 +1818,7 @@ int main(int argc, char **argv) { | |||
1814 | } | 1818 | } |
1815 | *secondip = '\0'; | 1819 | *secondip = '\0'; |
1816 | secondip++; | 1820 | secondip++; |
1817 | 1821 | ||
1818 | // check addresses | 1822 | // check addresses |
1819 | if (atoip(firstip, &br->iprange_start) || atoip(secondip, &br->iprange_end) || | 1823 | if (atoip(firstip, &br->iprange_start) || atoip(secondip, &br->iprange_end) || |
1820 | br->iprange_start >= br->iprange_end) { | 1824 | br->iprange_start >= br->iprange_end) { |
@@ -1841,7 +1845,7 @@ int main(int argc, char **argv) { | |||
1841 | fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n"); | 1845 | fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n"); |
1842 | exit(1); | 1846 | exit(1); |
1843 | } | 1847 | } |
1844 | 1848 | ||
1845 | // read the address | 1849 | // read the address |
1846 | if (atomac(argv[i] + 6, br->macsandbox)) { | 1850 | if (atomac(argv[i] + 6, br->macsandbox)) { |
1847 | fprintf(stderr, "Error: invalid MAC address\n"); | 1851 | fprintf(stderr, "Error: invalid MAC address\n"); |
@@ -1859,7 +1863,7 @@ int main(int argc, char **argv) { | |||
1859 | fprintf(stderr, "Error: no network device configured\n"); | 1863 | fprintf(stderr, "Error: no network device configured\n"); |
1860 | exit(1); | 1864 | exit(1); |
1861 | } | 1865 | } |
1862 | 1866 | ||
1863 | if (sscanf(argv[i] + 6, "%d", &br->mtu) != 1 || br->mtu < 576 || br->mtu > 9198) { | 1867 | if (sscanf(argv[i] + 6, "%d", &br->mtu) != 1 || br->mtu < 576 || br->mtu > 9198) { |
1864 | fprintf(stderr, "Error: invalid mtu value\n"); | 1868 | fprintf(stderr, "Error: invalid mtu value\n"); |
1865 | exit(1); | 1869 | exit(1); |
@@ -1880,7 +1884,7 @@ int main(int argc, char **argv) { | |||
1880 | fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n"); | 1884 | fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n"); |
1881 | exit(1); | 1885 | exit(1); |
1882 | } | 1886 | } |
1883 | 1887 | ||
1884 | // configure this IP address for the last bridge defined | 1888 | // configure this IP address for the last bridge defined |
1885 | if (strcmp(argv[i] + 5, "none") == 0) | 1889 | if (strcmp(argv[i] + 5, "none") == 0) |
1886 | br->arg_ip_none = 1; | 1890 | br->arg_ip_none = 1; |
@@ -1906,7 +1910,7 @@ int main(int argc, char **argv) { | |||
1906 | fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n"); | 1910 | fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n"); |
1907 | exit(1); | 1911 | exit(1); |
1908 | } | 1912 | } |
1909 | 1913 | ||
1910 | // configure this IP address for the last bridge defined | 1914 | // configure this IP address for the last bridge defined |
1911 | // todo: verify ipv6 syntax | 1915 | // todo: verify ipv6 syntax |
1912 | br->ip6sandbox = argv[i] + 6; | 1916 | br->ip6sandbox = argv[i] + 6; |
@@ -1915,7 +1919,7 @@ int main(int argc, char **argv) { | |||
1915 | // exit(1); | 1919 | // exit(1); |
1916 | // } | 1920 | // } |
1917 | } | 1921 | } |
1918 | else | 1922 | else |
1919 | exit_err_feature("networking"); | 1923 | exit_err_feature("networking"); |
1920 | } | 1924 | } |
1921 | 1925 | ||
@@ -1930,14 +1934,14 @@ int main(int argc, char **argv) { | |||
1930 | else | 1934 | else |
1931 | exit_err_feature("networking"); | 1935 | exit_err_feature("networking"); |
1932 | } | 1936 | } |
1933 | #endif | 1937 | #endif |
1934 | else if (strncmp(argv[i], "--dns=", 6) == 0) { | 1938 | else if (strncmp(argv[i], "--dns=", 6) == 0) { |
1935 | uint32_t dns; | 1939 | uint32_t dns; |
1936 | if (atoip(argv[i] + 6, &dns)) { | 1940 | if (atoip(argv[i] + 6, &dns)) { |
1937 | fprintf(stderr, "Error: invalid DNS server IP address\n"); | 1941 | fprintf(stderr, "Error: invalid DNS server IP address\n"); |
1938 | return 1; | 1942 | return 1; |
1939 | } | 1943 | } |
1940 | 1944 | ||
1941 | if (cfg.dns1 == 0) | 1945 | if (cfg.dns1 == 0) |
1942 | cfg.dns1 = dns; | 1946 | cfg.dns1 = dns; |
1943 | else if (cfg.dns2 == 0) | 1947 | else if (cfg.dns2 == 0) |
@@ -1949,7 +1953,7 @@ int main(int argc, char **argv) { | |||
1949 | return 1; | 1953 | return 1; |
1950 | } | 1954 | } |
1951 | } | 1955 | } |
1952 | 1956 | ||
1953 | else if (strncmp(argv[i], "--hosts-file=", 13) == 0) | 1957 | else if (strncmp(argv[i], "--hosts-file=", 13) == 0) |
1954 | cfg.hosts_file = fs_check_hosts_file(argv[i] + 13); | 1958 | cfg.hosts_file = fs_check_hosts_file(argv[i] + 13); |
1955 | 1959 | ||
@@ -2042,7 +2046,7 @@ int main(int argc, char **argv) { | |||
2042 | arg_appimage = 1; | 2046 | arg_appimage = 1; |
2043 | else if (strcmp(argv[i], "--csh") == 0) { | 2047 | else if (strcmp(argv[i], "--csh") == 0) { |
2044 | if (arg_shell_none) { | 2048 | if (arg_shell_none) { |
2045 | 2049 | ||
2046 | fprintf(stderr, "Error: --shell=none was already specified.\n"); | 2050 | fprintf(stderr, "Error: --shell=none was already specified.\n"); |
2047 | return 1; | 2051 | return 1; |
2048 | } | 2052 | } |
@@ -2076,7 +2080,7 @@ int main(int argc, char **argv) { | |||
2076 | return 1; | 2080 | return 1; |
2077 | } | 2081 | } |
2078 | invalid_filename(argv[i] + 8); | 2082 | invalid_filename(argv[i] + 8); |
2079 | 2083 | ||
2080 | if (cfg.shell) { | 2084 | if (cfg.shell) { |
2081 | fprintf(stderr, "Error: only one user shell can be specified\n"); | 2085 | fprintf(stderr, "Error: only one user shell can be specified\n"); |
2082 | return 1; | 2086 | return 1; |
@@ -2110,7 +2114,7 @@ int main(int argc, char **argv) { | |||
2110 | return 1; | 2114 | return 1; |
2111 | } | 2115 | } |
2112 | } | 2116 | } |
2113 | 2117 | ||
2114 | // unlike all other x11 features, this is available always | 2118 | // unlike all other x11 features, this is available always |
2115 | else if (strcmp(argv[i], "--x11=none") == 0) { | 2119 | else if (strcmp(argv[i], "--x11=none") == 0) { |
2116 | arg_x11_block = 1; | 2120 | arg_x11_block = 1; |
@@ -2119,7 +2123,7 @@ int main(int argc, char **argv) { | |||
2119 | else if (strcmp(argv[i], "--x11=xorg") == 0) { | 2123 | else if (strcmp(argv[i], "--x11=xorg") == 0) { |
2120 | if (checkcfg(CFG_X11)) | 2124 | if (checkcfg(CFG_X11)) |
2121 | arg_x11_xorg = 1; | 2125 | arg_x11_xorg = 1; |
2122 | else | 2126 | else |
2123 | exit_err_feature("x11"); | 2127 | exit_err_feature("x11"); |
2124 | } | 2128 | } |
2125 | #endif | 2129 | #endif |
@@ -2139,7 +2143,7 @@ int main(int argc, char **argv) { | |||
2139 | fprintf(stderr, "This feature is not enabled in the current build\n"); | 2143 | fprintf(stderr, "This feature is not enabled in the current build\n"); |
2140 | exit(1); | 2144 | exit(1); |
2141 | } | 2145 | } |
2142 | 2146 | ||
2143 | else if (strcmp(argv[i], "--") == 0) { | 2147 | else if (strcmp(argv[i], "--") == 0) { |
2144 | // double dash - positional params to follow | 2148 | // double dash - positional params to follow |
2145 | arg_doubledash = 1; | 2149 | arg_doubledash = 1; |
@@ -2158,7 +2162,7 @@ int main(int argc, char **argv) { | |||
2158 | fprintf(stderr, "Error: invalid %s command line option\n", argv[i]); | 2162 | fprintf(stderr, "Error: invalid %s command line option\n", argv[i]); |
2159 | return 1; | 2163 | return 1; |
2160 | } | 2164 | } |
2161 | 2165 | ||
2162 | // we have a program name coming | 2166 | // we have a program name coming |
2163 | if (arg_appimage) { | 2167 | if (arg_appimage) { |
2164 | cfg.command_name = strdup(argv[i]); | 2168 | cfg.command_name = strdup(argv[i]); |
@@ -2171,7 +2175,7 @@ int main(int argc, char **argv) { | |||
2171 | break; | 2175 | break; |
2172 | } | 2176 | } |
2173 | } | 2177 | } |
2174 | 2178 | ||
2175 | // prog_index could still be -1 if no program was specified | 2179 | // prog_index could still be -1 if no program was specified |
2176 | if (prog_index == -1 && arg_shell_none) { | 2180 | if (prog_index == -1 && arg_shell_none) { |
2177 | fprintf(stderr, "Error: shell=none configured, but no program specified\n"); | 2181 | fprintf(stderr, "Error: shell=none configured, but no program specified\n"); |
@@ -2182,7 +2186,7 @@ int main(int argc, char **argv) { | |||
2182 | if (arg_trace && arg_tracelog) { | 2186 | if (arg_trace && arg_tracelog) { |
2183 | fwarning("--trace and --tracelog are mutually exclusive; --tracelog disabled\n"); | 2187 | fwarning("--trace and --tracelog are mutually exclusive; --tracelog disabled\n"); |
2184 | } | 2188 | } |
2185 | 2189 | ||
2186 | // check user namespace (--noroot) options | 2190 | // check user namespace (--noroot) options |
2187 | if (arg_noroot) { | 2191 | if (arg_noroot) { |
2188 | if (arg_overlay) { | 2192 | if (arg_overlay) { |
@@ -2235,12 +2239,12 @@ int main(int argc, char **argv) { | |||
2235 | fprintf(stderr, "Error: command must be specified when --shell=none used.\n"); | 2239 | fprintf(stderr, "Error: command must be specified when --shell=none used.\n"); |
2236 | exit(1); | 2240 | exit(1); |
2237 | }*/ | 2241 | }*/ |
2238 | 2242 | ||
2239 | assert(cfg.command_name); | 2243 | assert(cfg.command_name); |
2240 | if (arg_debug) | 2244 | if (arg_debug) |
2241 | printf("Command name #%s#\n", cfg.command_name); | 2245 | printf("Command name #%s#\n", cfg.command_name); |
2242 | 2246 | ||
2243 | 2247 | ||
2244 | // load the profile | 2248 | // load the profile |
2245 | if (!arg_noprofile) { | 2249 | if (!arg_noprofile) { |
2246 | if (!custom_profile) { | 2250 | if (!custom_profile) { |
@@ -2278,14 +2282,14 @@ int main(int argc, char **argv) { | |||
2278 | profile_name = DEFAULT_ROOT_PROFILE; | 2282 | profile_name = DEFAULT_ROOT_PROFILE; |
2279 | if (arg_debug) | 2283 | if (arg_debug) |
2280 | printf("Attempting to find %s.profile...\n", profile_name); | 2284 | printf("Attempting to find %s.profile...\n", profile_name); |
2281 | 2285 | ||
2282 | // look for the profile in ~/.config/firejail directory | 2286 | // look for the profile in ~/.config/firejail directory |
2283 | char *usercfgdir; | 2287 | char *usercfgdir; |
2284 | if (asprintf(&usercfgdir, "%s/.config/firejail", cfg.homedir) == -1) | 2288 | if (asprintf(&usercfgdir, "%s/.config/firejail", cfg.homedir) == -1) |
2285 | errExit("asprintf"); | 2289 | errExit("asprintf"); |
2286 | custom_profile = profile_find(profile_name, usercfgdir); | 2290 | custom_profile = profile_find(profile_name, usercfgdir); |
2287 | free(usercfgdir); | 2291 | free(usercfgdir); |
2288 | 2292 | ||
2289 | if (!custom_profile) { | 2293 | if (!custom_profile) { |
2290 | // look for the profile in /etc/firejail directory | 2294 | // look for the profile in /etc/firejail directory |
2291 | if (custom_profile_dir) | 2295 | if (custom_profile_dir) |
@@ -2297,7 +2301,7 @@ int main(int argc, char **argv) { | |||
2297 | fprintf(stderr, "Error: no default.profile installed\n"); | 2301 | fprintf(stderr, "Error: no default.profile installed\n"); |
2298 | exit(1); | 2302 | exit(1); |
2299 | } | 2303 | } |
2300 | 2304 | ||
2301 | if (custom_profile && !arg_quiet) | 2305 | if (custom_profile && !arg_quiet) |
2302 | printf("\n** Note: you can use --noprofile to disable %s.profile **\n\n", profile_name); | 2306 | printf("\n** Note: you can use --noprofile to disable %s.profile **\n\n", profile_name); |
2303 | } | 2307 | } |
@@ -2309,7 +2313,7 @@ int main(int argc, char **argv) { | |||
2309 | 2313 | ||
2310 | // check network configuration options - it will exit if anything went wrong | 2314 | // check network configuration options - it will exit if anything went wrong |
2311 | net_check_cfg(); | 2315 | net_check_cfg(); |
2312 | 2316 | ||
2313 | // check and assign an IP address - for macvlan it will be done again in the sandbox! | 2317 | // check and assign an IP address - for macvlan it will be done again in the sandbox! |
2314 | if (any_bridge_configured()) { | 2318 | if (any_bridge_configured()) { |
2315 | EUID_ROOT(); | 2319 | EUID_ROOT(); |
@@ -2319,12 +2323,12 @@ int main(int argc, char **argv) { | |||
2319 | (void) rv; | 2323 | (void) rv; |
2320 | flock(lockfd, LOCK_EX); | 2324 | flock(lockfd, LOCK_EX); |
2321 | } | 2325 | } |
2322 | 2326 | ||
2323 | check_network(&cfg.bridge0); | 2327 | check_network(&cfg.bridge0); |
2324 | check_network(&cfg.bridge1); | 2328 | check_network(&cfg.bridge1); |
2325 | check_network(&cfg.bridge2); | 2329 | check_network(&cfg.bridge2); |
2326 | check_network(&cfg.bridge3); | 2330 | check_network(&cfg.bridge3); |
2327 | 2331 | ||
2328 | // save network mapping in shared memory | 2332 | // save network mapping in shared memory |
2329 | network_set_run_file(sandbox_pid); | 2333 | network_set_run_file(sandbox_pid); |
2330 | EUID_USER(); | 2334 | EUID_USER(); |
@@ -2354,10 +2358,10 @@ int main(int argc, char **argv) { | |||
2354 | if (display > 0) | 2358 | if (display > 0) |
2355 | set_x11_file(sandbox_pid, display); | 2359 | set_x11_file(sandbox_pid, display); |
2356 | EUID_USER(); | 2360 | EUID_USER(); |
2357 | 2361 | ||
2358 | // clone environment | 2362 | // clone environment |
2359 | int flags = CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD; | 2363 | int flags = CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD; |
2360 | 2364 | ||
2361 | // in root mode also enable CLONE_NEWIPC | 2365 | // in root mode also enable CLONE_NEWIPC |
2362 | // in user mode CLONE_NEWIPC will break MIT Shared Memory Extension (MIT-SHM) | 2366 | // in user mode CLONE_NEWIPC will break MIT Shared Memory Extension (MIT-SHM) |
2363 | if (getuid() == 0 || arg_ipc) { | 2367 | if (getuid() == 0 || arg_ipc) { |
@@ -2365,7 +2369,7 @@ int main(int argc, char **argv) { | |||
2365 | if (arg_debug) | 2369 | if (arg_debug) |
2366 | printf("Enabling IPC namespace\n"); | 2370 | printf("Enabling IPC namespace\n"); |
2367 | } | 2371 | } |
2368 | 2372 | ||
2369 | if (any_bridge_configured() || any_interface_configured() || arg_nonetwork) { | 2373 | if (any_bridge_configured() || any_interface_configured() || arg_nonetwork) { |
2370 | flags |= CLONE_NEWNET; | 2374 | flags |= CLONE_NEWNET; |
2371 | } | 2375 | } |
@@ -2387,9 +2391,9 @@ int main(int argc, char **argv) { | |||
2387 | if (getuid() == 0) // only for root | 2391 | if (getuid() == 0) // only for root |
2388 | printf("The new log directory is /proc/%d/root/var/log\n", child); | 2392 | printf("The new log directory is /proc/%d/root/var/log\n", child); |
2389 | } | 2393 | } |
2390 | 2394 | ||
2391 | if (!arg_nonetwork) { | 2395 | if (!arg_nonetwork) { |
2392 | EUID_ROOT(); | 2396 | EUID_ROOT(); |
2393 | pid_t net_child = fork(); | 2397 | pid_t net_child = fork(); |
2394 | if (net_child < 0) | 2398 | if (net_child < 0) |
2395 | errExit("fork"); | 2399 | errExit("fork"); |
@@ -2401,11 +2405,11 @@ int main(int argc, char **argv) { | |||
2401 | errExit("setregid"); | 2405 | errExit("setregid"); |
2402 | network_main(child); | 2406 | network_main(child); |
2403 | if (arg_debug) | 2407 | if (arg_debug) |
2404 | printf("Host network configured\n"); | 2408 | printf("Host network configured\n"); |
2405 | #ifdef HAVE_GCOV | 2409 | #ifdef HAVE_GCOV |
2406 | __gcov_flush(); | 2410 | __gcov_flush(); |
2407 | #endif | 2411 | #endif |
2408 | _exit(0); | 2412 | _exit(0); |
2409 | } | 2413 | } |
2410 | 2414 | ||
2411 | // wait for the child to finish | 2415 | // wait for the child to finish |
@@ -2416,10 +2420,10 @@ int main(int argc, char **argv) { | |||
2416 | // close each end of the unused pipes | 2420 | // close each end of the unused pipes |
2417 | close(parent_to_child_fds[0]); | 2421 | close(parent_to_child_fds[0]); |
2418 | close(child_to_parent_fds[1]); | 2422 | close(child_to_parent_fds[1]); |
2419 | 2423 | ||
2420 | // notify child that base setup is complete | 2424 | // notify child that base setup is complete |
2421 | notify_other(parent_to_child_fds[1]); | 2425 | notify_other(parent_to_child_fds[1]); |
2422 | 2426 | ||
2423 | // wait for child to create new user namespace with CLONE_NEWUSER | 2427 | // wait for child to create new user namespace with CLONE_NEWUSER |
2424 | wait_for_other(child_to_parent_fds[0]); | 2428 | wait_for_other(child_to_parent_fds[0]); |
2425 | close(child_to_parent_fds[0]); | 2429 | close(child_to_parent_fds[0]); |
@@ -2440,7 +2444,7 @@ int main(int argc, char **argv) { | |||
2440 | EUID_USER(); | 2444 | EUID_USER(); |
2441 | free(map); | 2445 | free(map); |
2442 | free(map_path); | 2446 | free(map_path); |
2443 | 2447 | ||
2444 | // gid file | 2448 | // gid file |
2445 | if (asprintf(&map_path, "/proc/%d/gid_map", child) == -1) | 2449 | if (asprintf(&map_path, "/proc/%d/gid_map", child) == -1) |
2446 | errExit("asprintf"); | 2450 | errExit("asprintf"); |
@@ -2452,7 +2456,7 @@ int main(int argc, char **argv) { | |||
2452 | gid_t gid = getgid(); | 2456 | gid_t gid = getgid(); |
2453 | sprintf(ptr, "%d %d 1\n", gid, gid); | 2457 | sprintf(ptr, "%d %d 1\n", gid, gid); |
2454 | ptr += strlen(ptr); | 2458 | ptr += strlen(ptr); |
2455 | 2459 | ||
2456 | if (!arg_nogroups) { | 2460 | if (!arg_nogroups) { |
2457 | // add tty group | 2461 | // add tty group |
2458 | gid_t g = get_group_id("tty"); | 2462 | gid_t g = get_group_id("tty"); |
@@ -2460,38 +2464,38 @@ int main(int argc, char **argv) { | |||
2460 | sprintf(ptr, "%d %d 1\n", g, g); | 2464 | sprintf(ptr, "%d %d 1\n", g, g); |
2461 | ptr += strlen(ptr); | 2465 | ptr += strlen(ptr); |
2462 | } | 2466 | } |
2463 | 2467 | ||
2464 | // add audio group | 2468 | // add audio group |
2465 | g = get_group_id("audio"); | 2469 | g = get_group_id("audio"); |
2466 | if (g) { | 2470 | if (g) { |
2467 | sprintf(ptr, "%d %d 1\n", g, g); | 2471 | sprintf(ptr, "%d %d 1\n", g, g); |
2468 | ptr += strlen(ptr); | 2472 | ptr += strlen(ptr); |
2469 | } | 2473 | } |
2470 | 2474 | ||
2471 | // add video group | 2475 | // add video group |
2472 | g = get_group_id("video"); | 2476 | g = get_group_id("video"); |
2473 | if (g) { | 2477 | if (g) { |
2474 | sprintf(ptr, "%d %d 1\n", g, g); | 2478 | sprintf(ptr, "%d %d 1\n", g, g); |
2475 | ptr += strlen(ptr); | 2479 | ptr += strlen(ptr); |
2476 | } | 2480 | } |
2477 | 2481 | ||
2478 | // add games group | 2482 | // add games group |
2479 | g = get_group_id("games"); | 2483 | g = get_group_id("games"); |
2480 | if (g) { | 2484 | if (g) { |
2481 | sprintf(ptr, "%d %d 1\n", g, g); | 2485 | sprintf(ptr, "%d %d 1\n", g, g); |
2482 | } | 2486 | } |
2483 | } | 2487 | } |
2484 | 2488 | ||
2485 | EUID_ROOT(); | 2489 | EUID_ROOT(); |
2486 | update_map(gidmap, map_path); | 2490 | update_map(gidmap, map_path); |
2487 | EUID_USER(); | 2491 | EUID_USER(); |
2488 | free(map_path); | 2492 | free(map_path); |
2489 | } | 2493 | } |
2490 | 2494 | ||
2491 | // notify child that UID/GID mapping is complete | 2495 | // notify child that UID/GID mapping is complete |
2492 | notify_other(parent_to_child_fds[1]); | 2496 | notify_other(parent_to_child_fds[1]); |
2493 | close(parent_to_child_fds[1]); | 2497 | close(parent_to_child_fds[1]); |
2494 | 2498 | ||
2495 | EUID_ROOT(); | 2499 | EUID_ROOT(); |
2496 | if (lockfd != -1) { | 2500 | if (lockfd != -1) { |
2497 | flock(lockfd, LOCK_UN); | 2501 | flock(lockfd, LOCK_UN); |
@@ -2499,13 +2503,13 @@ int main(int argc, char **argv) { | |||
2499 | } | 2503 | } |
2500 | 2504 | ||
2501 | // create name file under /run/firejail | 2505 | // create name file under /run/firejail |
2502 | 2506 | ||
2503 | 2507 | ||
2504 | // handle CTRL-C in parent | 2508 | // handle CTRL-C in parent |
2505 | signal (SIGINT, my_handler); | 2509 | signal (SIGINT, my_handler); |
2506 | signal (SIGTERM, my_handler); | 2510 | signal (SIGTERM, my_handler); |
2507 | 2511 | ||
2508 | 2512 | ||
2509 | // wait for the child to finish | 2513 | // wait for the child to finish |
2510 | EUID_USER(); | 2514 | EUID_USER(); |
2511 | int status = 0; | 2515 | int status = 0; |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 9ae2aa5b4..11258892e 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -28,8 +28,8 @@ int profile_find(const char *name, const char *dir) { | |||
28 | EUID_ASSERT(); | 28 | EUID_ASSERT(); |
29 | assert(name); | 29 | assert(name); |
30 | assert(dir); | 30 | assert(dir); |
31 | 31 | ||
32 | int rv = 0; | 32 | int rv = 0; |
33 | DIR *dp; | 33 | DIR *dp; |
34 | char *pname; | 34 | char *pname; |
35 | if (asprintf(&pname, "%s.profile", name) == -1) | 35 | if (asprintf(&pname, "%s.profile", name) == -1) |
@@ -74,17 +74,17 @@ static void warning_feature_disabled(const char *feature) { | |||
74 | // return 0 if the command was already executed inside the function | 74 | // return 0 if the command was already executed inside the function |
75 | int profile_check_line(char *ptr, int lineno, const char *fname) { | 75 | int profile_check_line(char *ptr, int lineno, const char *fname) { |
76 | EUID_ASSERT(); | 76 | EUID_ASSERT(); |
77 | 77 | ||
78 | // check ignore list | 78 | // check ignore list |
79 | int i; | 79 | int i; |
80 | for (i = 0; i < MAX_PROFILE_IGNORE; i++) { | 80 | for (i = 0; i < MAX_PROFILE_IGNORE; i++) { |
81 | if (cfg.profile_ignore[i] == NULL) | 81 | if (cfg.profile_ignore[i] == NULL) |
82 | break; | 82 | break; |
83 | 83 | ||
84 | if (strncmp(ptr, cfg.profile_ignore[i], strlen(cfg.profile_ignore[i])) == 0) | 84 | if (strncmp(ptr, cfg.profile_ignore[i], strlen(cfg.profile_ignore[i])) == 0) |
85 | return 0; // ignore line | 85 | return 0; // ignore line |
86 | } | 86 | } |
87 | 87 | ||
88 | if (strncmp(ptr, "ignore ", 7) == 0) { | 88 | if (strncmp(ptr, "ignore ", 7) == 0) { |
89 | char *str = strdup(ptr + 7); | 89 | char *str = strdup(ptr + 7); |
90 | if (*str == '\0') { | 90 | if (*str == '\0') { |
@@ -94,7 +94,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
94 | // find an empty entry in profile_ignore array | 94 | // find an empty entry in profile_ignore array |
95 | int j; | 95 | int j; |
96 | for (j = 0; j < MAX_PROFILE_IGNORE; j++) { | 96 | for (j = 0; j < MAX_PROFILE_IGNORE; j++) { |
97 | if (cfg.profile_ignore[j] == NULL) | 97 | if (cfg.profile_ignore[j] == NULL) |
98 | break; | 98 | break; |
99 | } | 99 | } |
100 | if (j >= MAX_PROFILE_IGNORE) { | 100 | if (j >= MAX_PROFILE_IGNORE) { |
@@ -102,18 +102,18 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
102 | exit(1); | 102 | exit(1); |
103 | } | 103 | } |
104 | // ... and configure it | 104 | // ... and configure it |
105 | else | 105 | else |
106 | cfg.profile_ignore[j] = str; | 106 | cfg.profile_ignore[j] = str; |
107 | 107 | ||
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | // mkdir | 111 | // mkdir |
112 | if (strncmp(ptr, "mkdir ", 6) == 0) { | 112 | if (strncmp(ptr, "mkdir ", 6) == 0) { |
113 | fs_mkdir(ptr + 6); | 113 | fs_mkdir(ptr + 6); |
114 | return 1; // process mkdir again while applying blacklists | 114 | return 1; // process mkdir again while applying blacklists |
115 | } | 115 | } |
116 | // mkfile | 116 | // mkfile |
117 | if (strncmp(ptr, "mkfile ", 7) == 0) { | 117 | if (strncmp(ptr, "mkfile ", 7) == 0) { |
118 | fs_mkfile(ptr + 7); | 118 | fs_mkfile(ptr + 7); |
119 | return 1; // process mkfile again while applying blacklists | 119 | return 1; // process mkfile again while applying blacklists |
@@ -166,7 +166,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
166 | else if (strcmp(ptr, "shell none") == 0) { | 166 | else if (strcmp(ptr, "shell none") == 0) { |
167 | arg_shell_none = 1; | 167 | arg_shell_none = 1; |
168 | return 0; | 168 | return 0; |
169 | } | 169 | } |
170 | else if (strcmp(ptr, "tracelog") == 0) { | 170 | else if (strcmp(ptr, "tracelog") == 0) { |
171 | arg_tracelog = 1; | 171 | arg_tracelog = 1; |
172 | return 0; | 172 | return 0; |
@@ -210,6 +210,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
210 | arg_nosound = 1; | 210 | arg_nosound = 1; |
211 | return 0; | 211 | return 0; |
212 | } | 212 | } |
213 | else if (strcmp(ptr, "novideo") == 0) { | ||
214 | arg_novideo = 1; | ||
215 | return 0; | ||
216 | } | ||
213 | else if (strcmp(ptr, "no3d") == 0) { | 217 | else if (strcmp(ptr, "no3d") == 0) { |
214 | arg_no3d = 1; | 218 | arg_no3d = 1; |
215 | return 0; | 219 | return 0; |
@@ -217,7 +221,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
217 | else if (strcmp(ptr, "allow-private-blacklist") == 0) { | 221 | else if (strcmp(ptr, "allow-private-blacklist") == 0) { |
218 | arg_allow_private_blacklist = 1; | 222 | arg_allow_private_blacklist = 1; |
219 | return 0; | 223 | return 0; |
220 | } | 224 | } |
221 | else if (strcmp(ptr, "netfilter") == 0) { | 225 | else if (strcmp(ptr, "netfilter") == 0) { |
222 | #ifdef HAVE_NETWORK | 226 | #ifdef HAVE_NETWORK |
223 | if (checkcfg(CFG_NETWORK)) | 227 | if (checkcfg(CFG_NETWORK)) |
@@ -288,7 +292,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
288 | fprintf(stderr, "Error: only \"net none\" is allowed to non-root users\n"); | 292 | fprintf(stderr, "Error: only \"net none\" is allowed to non-root users\n"); |
289 | exit(1); | 293 | exit(1); |
290 | } | 294 | } |
291 | 295 | ||
292 | if (strcmp(ptr + 4, "lo") == 0) { | 296 | if (strcmp(ptr + 4, "lo") == 0) { |
293 | fprintf(stderr, "Error: cannot attach to lo device\n"); | 297 | fprintf(stderr, "Error: cannot attach to lo device\n"); |
294 | exit(1); | 298 | exit(1); |
@@ -314,7 +318,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
314 | #endif | 318 | #endif |
315 | return 0; | 319 | return 0; |
316 | } | 320 | } |
317 | 321 | ||
318 | else if (strncmp(ptr, "veth-name ", 10) == 0) { | 322 | else if (strncmp(ptr, "veth-name ", 10) == 0) { |
319 | #ifdef HAVE_NETWORK | 323 | #ifdef HAVE_NETWORK |
320 | if (checkcfg(CFG_NETWORK)) { | 324 | if (checkcfg(CFG_NETWORK)) { |
@@ -365,7 +369,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
365 | } | 369 | } |
366 | *secondip = '\0'; | 370 | *secondip = '\0'; |
367 | secondip++; | 371 | secondip++; |
368 | 372 | ||
369 | // check addresses | 373 | // check addresses |
370 | if (atoip(firstip, &br->iprange_start) || atoip(secondip, &br->iprange_end) || | 374 | if (atoip(firstip, &br->iprange_start) || atoip(secondip, &br->iprange_end) || |
371 | br->iprange_start >= br->iprange_end) { | 375 | br->iprange_start >= br->iprange_end) { |
@@ -392,7 +396,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
392 | fprintf(stderr, "Error: no network device configured\n"); | 396 | fprintf(stderr, "Error: no network device configured\n"); |
393 | exit(1); | 397 | exit(1); |
394 | } | 398 | } |
395 | 399 | ||
396 | if (mac_not_zero(br->macsandbox)) { | 400 | if (mac_not_zero(br->macsandbox)) { |
397 | fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n"); | 401 | fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n"); |
398 | exit(1); | 402 | exit(1); |
@@ -418,7 +422,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
418 | fprintf(stderr, "Error: no network device configured\n"); | 422 | fprintf(stderr, "Error: no network device configured\n"); |
419 | exit(1); | 423 | exit(1); |
420 | } | 424 | } |
421 | 425 | ||
422 | if (sscanf(ptr + 4, "%d", &br->mtu) != 1 || br->mtu < 576 || br->mtu > 9198) { | 426 | if (sscanf(ptr + 4, "%d", &br->mtu) != 1 || br->mtu < 576 || br->mtu > 9198) { |
423 | fprintf(stderr, "Error: invalid mtu value\n"); | 427 | fprintf(stderr, "Error: invalid mtu value\n"); |
424 | exit(1); | 428 | exit(1); |
@@ -479,7 +483,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
479 | // fprintf(stderr, "Error: invalid IP address\n"); | 483 | // fprintf(stderr, "Error: invalid IP address\n"); |
480 | // exit(1); | 484 | // exit(1); |
481 | // } | 485 | // } |
482 | 486 | ||
483 | } | 487 | } |
484 | else | 488 | else |
485 | warning_feature_disabled("networking"); | 489 | warning_feature_disabled("networking"); |
@@ -502,7 +506,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
502 | } | 506 | } |
503 | 507 | ||
504 | if (strcmp(ptr, "apparmor") == 0) { | 508 | if (strcmp(ptr, "apparmor") == 0) { |
505 | #ifdef HAVE_APPARMOR | 509 | #ifdef HAVE_APPARMOR |
506 | arg_apparmor = 1; | 510 | arg_apparmor = 1; |
507 | #endif | 511 | #endif |
508 | return 0; | 512 | return 0; |
@@ -515,7 +519,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
515 | fwarning("a protocol list is present, the new list \"%s\" will not be installed\n", ptr + 9); | 519 | fwarning("a protocol list is present, the new list \"%s\" will not be installed\n", ptr + 9); |
516 | return 0; | 520 | return 0; |
517 | } | 521 | } |
518 | 522 | ||
519 | // store list | 523 | // store list |
520 | cfg.protocol = strdup(ptr + 9); | 524 | cfg.protocol = strdup(ptr + 9); |
521 | if (!cfg.protocol) | 525 | if (!cfg.protocol) |
@@ -526,7 +530,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
526 | #endif | 530 | #endif |
527 | return 0; | 531 | return 0; |
528 | } | 532 | } |
529 | 533 | ||
530 | if (strncmp(ptr, "env ", 4) == 0) { | 534 | if (strncmp(ptr, "env ", 4) == 0) { |
531 | env_store(ptr + 4, SETENV); | 535 | env_store(ptr + 4, SETENV); |
532 | return 0; | 536 | return 0; |
@@ -535,7 +539,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
535 | env_store(ptr + 6, RMENV); | 539 | env_store(ptr + 6, RMENV); |
536 | return 0; | 540 | return 0; |
537 | } | 541 | } |
538 | 542 | ||
539 | // seccomp drop list on top of default list | 543 | // seccomp drop list on top of default list |
540 | if (strncmp(ptr, "seccomp ", 8) == 0) { | 544 | if (strncmp(ptr, "seccomp ", 8) == 0) { |
541 | #ifdef HAVE_SECCOMP | 545 | #ifdef HAVE_SECCOMP |
@@ -549,7 +553,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
549 | 553 | ||
550 | return 0; | 554 | return 0; |
551 | } | 555 | } |
552 | 556 | ||
553 | // seccomp drop list without default list | 557 | // seccomp drop list without default list |
554 | if (strncmp(ptr, "seccomp.drop ", 13) == 0) { | 558 | if (strncmp(ptr, "seccomp.drop ", 13) == 0) { |
555 | #ifdef HAVE_SECCOMP | 559 | #ifdef HAVE_SECCOMP |
@@ -559,7 +563,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
559 | } | 563 | } |
560 | else | 564 | else |
561 | warning_feature_disabled("seccomp"); | 565 | warning_feature_disabled("seccomp"); |
562 | #endif | 566 | #endif |
563 | return 0; | 567 | return 0; |
564 | } | 568 | } |
565 | 569 | ||
@@ -572,10 +576,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
572 | } | 576 | } |
573 | else | 577 | else |
574 | warning_feature_disabled("seccomp"); | 578 | warning_feature_disabled("seccomp"); |
575 | #endif | 579 | #endif |
576 | return 0; | 580 | return 0; |
577 | } | 581 | } |
578 | 582 | ||
579 | // caps drop list | 583 | // caps drop list |
580 | if (strncmp(ptr, "caps.drop ", 10) == 0) { | 584 | if (strncmp(ptr, "caps.drop ", 10) == 0) { |
581 | arg_caps_drop = 1; | 585 | arg_caps_drop = 1; |
@@ -586,7 +590,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
586 | caps_check_list(arg_caps_list, NULL); | 590 | caps_check_list(arg_caps_list, NULL); |
587 | return 0; | 591 | return 0; |
588 | } | 592 | } |
589 | 593 | ||
590 | // caps keep list | 594 | // caps keep list |
591 | if (strncmp(ptr, "caps.keep ", 10) == 0) { | 595 | if (strncmp(ptr, "caps.keep ", 10) == 0) { |
592 | arg_caps_keep = 1; | 596 | arg_caps_keep = 1; |
@@ -603,13 +607,13 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
603 | cfg.hostname = ptr + 9; | 607 | cfg.hostname = ptr + 9; |
604 | return 0; | 608 | return 0; |
605 | } | 609 | } |
606 | 610 | ||
607 | // hosts-file | 611 | // hosts-file |
608 | if (strncmp(ptr, "hosts-file ", 11) == 0) { | 612 | if (strncmp(ptr, "hosts-file ", 11) == 0) { |
609 | cfg.hosts_file = fs_check_hosts_file(ptr + 11); | 613 | cfg.hosts_file = fs_check_hosts_file(ptr + 11); |
610 | return 0; | 614 | return 0; |
611 | } | 615 | } |
612 | 616 | ||
613 | // dns | 617 | // dns |
614 | if (strncmp(ptr, "dns ", 4) == 0) { | 618 | if (strncmp(ptr, "dns ", 4) == 0) { |
615 | uint32_t dns; | 619 | uint32_t dns; |
@@ -617,7 +621,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
617 | fprintf(stderr, "Error: invalid DNS server IP address\n"); | 621 | fprintf(stderr, "Error: invalid DNS server IP address\n"); |
618 | return 1; | 622 | return 1; |
619 | } | 623 | } |
620 | 624 | ||
621 | if (cfg.dns1 == 0) | 625 | if (cfg.dns1 == 0) |
622 | cfg.dns1 = dns; | 626 | cfg.dns1 = dns; |
623 | else if (cfg.dns2 == 0) | 627 | else if (cfg.dns2 == 0) |
@@ -630,13 +634,13 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
630 | } | 634 | } |
631 | return 0; | 635 | return 0; |
632 | } | 636 | } |
633 | 637 | ||
634 | // cpu affinity | 638 | // cpu affinity |
635 | if (strncmp(ptr, "cpu ", 4) == 0) { | 639 | if (strncmp(ptr, "cpu ", 4) == 0) { |
636 | read_cpu_list(ptr + 4); | 640 | read_cpu_list(ptr + 4); |
637 | return 0; | 641 | return 0; |
638 | } | 642 | } |
639 | 643 | ||
640 | // nice value | 644 | // nice value |
641 | if (strncmp(ptr, "nice ", 4) == 0) { | 645 | if (strncmp(ptr, "nice ", 4) == 0) { |
642 | cfg.nice = atoi(ptr + 5); | 646 | cfg.nice = atoi(ptr + 5); |
@@ -651,7 +655,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
651 | set_cgroup(ptr + 7); | 655 | set_cgroup(ptr + 7); |
652 | return 0; | 656 | return 0; |
653 | } | 657 | } |
654 | 658 | ||
655 | // writable-etc | 659 | // writable-etc |
656 | if (strcmp(ptr, "writable-etc") == 0) { | 660 | if (strcmp(ptr, "writable-etc") == 0) { |
657 | if (cfg.etc_private_keep) { | 661 | if (cfg.etc_private_keep) { |
@@ -661,7 +665,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
661 | arg_writable_etc = 1; | 665 | arg_writable_etc = 1; |
662 | return 0; | 666 | return 0; |
663 | } | 667 | } |
664 | 668 | ||
665 | if (strcmp(ptr, "machine-id") == 0) { | 669 | if (strcmp(ptr, "machine-id") == 0) { |
666 | arg_machineid = 1; | 670 | arg_machineid = 1; |
667 | return 0; | 671 | return 0; |
@@ -675,7 +679,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
675 | arg_writable_var_log = 1; | 679 | arg_writable_var_log = 1; |
676 | return 0; | 680 | return 0; |
677 | } | 681 | } |
678 | 682 | ||
679 | // private directory | 683 | // private directory |
680 | if (strncmp(ptr, "private ", 8) == 0) { | 684 | if (strncmp(ptr, "private ", 8) == 0) { |
681 | cfg.home_private = ptr + 8; | 685 | cfg.home_private = ptr + 8; |
@@ -717,7 +721,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
717 | #endif | 721 | #endif |
718 | return 0; | 722 | return 0; |
719 | } | 723 | } |
720 | 724 | ||
721 | if (strcmp(ptr, "x11 xpra") == 0) { | 725 | if (strcmp(ptr, "x11 xpra") == 0) { |
722 | #ifdef HAVE_X11 | 726 | #ifdef HAVE_X11 |
723 | if (checkcfg(CFG_X11)) { | 727 | if (checkcfg(CFG_X11)) { |
@@ -736,7 +740,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
736 | #endif | 740 | #endif |
737 | return 0; | 741 | return 0; |
738 | } | 742 | } |
739 | 743 | ||
740 | if (strcmp(ptr, "x11 xvfb") == 0) { | 744 | if (strcmp(ptr, "x11 xvfb") == 0) { |
741 | #ifdef HAVE_X11 | 745 | #ifdef HAVE_X11 |
742 | if (checkcfg(CFG_X11)) { | 746 | if (checkcfg(CFG_X11)) { |
@@ -766,15 +770,15 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
766 | else { | 770 | else { |
767 | // start x11 | 771 | // start x11 |
768 | x11_start(cfg.original_argc, cfg.original_argv); | 772 | x11_start(cfg.original_argc, cfg.original_argv); |
769 | exit(0); | 773 | exit(0); |
770 | } | 774 | } |
771 | } | 775 | } |
772 | else | 776 | else |
773 | warning_feature_disabled("x11"); | 777 | warning_feature_disabled("x11"); |
774 | #endif | 778 | #endif |
775 | return 0; | 779 | return 0; |
776 | } | 780 | } |
777 | 781 | ||
778 | // private /etc list of files and directories | 782 | // private /etc list of files and directories |
779 | if (strncmp(ptr, "private-etc ", 12) == 0) { | 783 | if (strncmp(ptr, "private-etc ", 12) == 0) { |
780 | if (arg_writable_etc) { | 784 | if (arg_writable_etc) { |
@@ -788,7 +792,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
788 | cfg.etc_private_keep = ptr + 12; | 792 | cfg.etc_private_keep = ptr + 12; |
789 | } | 793 | } |
790 | arg_private_etc = 1; | 794 | arg_private_etc = 1; |
791 | 795 | ||
792 | return 0; | 796 | return 0; |
793 | } | 797 | } |
794 | 798 | ||
@@ -801,7 +805,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
801 | cfg.opt_private_keep = ptr + 12; | 805 | cfg.opt_private_keep = ptr + 12; |
802 | } | 806 | } |
803 | arg_private_opt = 1; | 807 | arg_private_opt = 1; |
804 | 808 | ||
805 | return 0; | 809 | return 0; |
806 | } | 810 | } |
807 | 811 | ||
@@ -814,7 +818,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
814 | cfg.srv_private_keep = ptr + 12; | 818 | cfg.srv_private_keep = ptr + 12; |
815 | } | 819 | } |
816 | arg_private_srv = 1; | 820 | arg_private_srv = 1; |
817 | 821 | ||
818 | return 0; | 822 | return 0; |
819 | } | 823 | } |
820 | 824 | ||
@@ -906,13 +910,13 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
906 | 910 | ||
907 | // filesystem bind | 911 | // filesystem bind |
908 | if (strncmp(ptr, "bind ", 5) == 0) { | 912 | if (strncmp(ptr, "bind ", 5) == 0) { |
909 | #ifdef HAVE_BIND | 913 | #ifdef HAVE_BIND |
910 | if (checkcfg(CFG_BIND)) { | 914 | if (checkcfg(CFG_BIND)) { |
911 | if (getuid() != 0) { | 915 | if (getuid() != 0) { |
912 | fprintf(stderr, "Error: --bind option is available only if running as root\n"); | 916 | fprintf(stderr, "Error: --bind option is available only if running as root\n"); |
913 | exit(1); | 917 | exit(1); |
914 | } | 918 | } |
915 | 919 | ||
916 | // extract two directories | 920 | // extract two directories |
917 | char *dname1 = ptr + 5; | 921 | char *dname1 = ptr + 5; |
918 | char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories | 922 | char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories |
@@ -920,7 +924,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
920 | fprintf(stderr, "Error: missing second directory for bind\n"); | 924 | fprintf(stderr, "Error: missing second directory for bind\n"); |
921 | exit(1); | 925 | exit(1); |
922 | } | 926 | } |
923 | 927 | ||
924 | // check directories | 928 | // check directories |
925 | invalid_filename(dname1); | 929 | invalid_filename(dname1); |
926 | invalid_filename(dname2); | 930 | invalid_filename(dname2); |
@@ -932,14 +936,14 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
932 | fprintf(stderr, "Symbolic links are not allowed for bind command\n"); | 936 | fprintf(stderr, "Symbolic links are not allowed for bind command\n"); |
933 | exit(1); | 937 | exit(1); |
934 | } | 938 | } |
935 | 939 | ||
936 | // insert comma back | 940 | // insert comma back |
937 | *(dname2 - 1) = ','; | 941 | *(dname2 - 1) = ','; |
938 | return 1; | 942 | return 1; |
939 | } | 943 | } |
940 | else | 944 | else |
941 | warning_feature_disabled("bind"); | 945 | warning_feature_disabled("bind"); |
942 | #endif | 946 | #endif |
943 | return 0; | 947 | return 0; |
944 | } | 948 | } |
945 | 949 | ||
@@ -969,8 +973,8 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
969 | fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); | 973 | fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); |
970 | exit(1); | 974 | exit(1); |
971 | } | 975 | } |
972 | 976 | ||
973 | return 0; | 977 | return 0; |
974 | } | 978 | } |
975 | 979 | ||
976 | if (strncmp(ptr, "join-or-start ", 14) == 0) { | 980 | if (strncmp(ptr, "join-or-start ", 14) == 0) { |
@@ -1005,14 +1009,14 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1005 | else if (strncmp(ptr, "noblacklist ", 12) == 0) | 1009 | else if (strncmp(ptr, "noblacklist ", 12) == 0) |
1006 | ptr += 12; | 1010 | ptr += 12; |
1007 | else if (strncmp(ptr, "whitelist ", 10) == 0) { | 1011 | else if (strncmp(ptr, "whitelist ", 10) == 0) { |
1008 | #ifdef HAVE_WHITELIST | 1012 | #ifdef HAVE_WHITELIST |
1009 | if (checkcfg(CFG_WHITELIST)) { | 1013 | if (checkcfg(CFG_WHITELIST)) { |
1010 | arg_whitelist = 1; | 1014 | arg_whitelist = 1; |
1011 | ptr += 10; | 1015 | ptr += 10; |
1012 | } | 1016 | } |
1013 | else | 1017 | else |
1014 | return 0; | 1018 | return 0; |
1015 | #else | 1019 | #else |
1016 | return 0; | 1020 | return 0; |
1017 | #endif | 1021 | #endif |
1018 | } | 1022 | } |
@@ -1058,13 +1062,13 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1058 | // add a profile entry in cfg.profile list; use str to populate the list | 1062 | // add a profile entry in cfg.profile list; use str to populate the list |
1059 | void profile_add(char *str) { | 1063 | void profile_add(char *str) { |
1060 | EUID_ASSERT(); | 1064 | EUID_ASSERT(); |
1061 | 1065 | ||
1062 | ProfileEntry *prf = malloc(sizeof(ProfileEntry)); | 1066 | ProfileEntry *prf = malloc(sizeof(ProfileEntry)); |
1063 | if (!prf) | 1067 | if (!prf) |
1064 | errExit("malloc"); | 1068 | errExit("malloc"); |
1065 | memset(prf, 0, sizeof(ProfileEntry)); | 1069 | memset(prf, 0, sizeof(ProfileEntry)); |
1066 | prf->next = NULL; | 1070 | prf->next = NULL; |
1067 | prf->data = str; | 1071 | prf->data = str; |
1068 | 1072 | ||
1069 | // add prf to the list | 1073 | // add prf to the list |
1070 | if (cfg.profile == NULL) { | 1074 | if (cfg.profile == NULL) { |
@@ -1081,11 +1085,11 @@ void profile_add(char *str) { | |||
1081 | static int include_level = 0; | 1085 | static int include_level = 0; |
1082 | void profile_read(const char *fname) { | 1086 | void profile_read(const char *fname) { |
1083 | EUID_ASSERT(); | 1087 | EUID_ASSERT(); |
1084 | 1088 | ||
1085 | // exit program if maximum include level was reached | 1089 | // exit program if maximum include level was reached |
1086 | if (include_level > MAX_INCLUDE_LEVEL) { | 1090 | if (include_level > MAX_INCLUDE_LEVEL) { |
1087 | fprintf(stderr, "Error: maximum profile include level was reached\n"); | 1091 | fprintf(stderr, "Error: maximum profile include level was reached\n"); |
1088 | exit(1); | 1092 | exit(1); |
1089 | } | 1093 | } |
1090 | 1094 | ||
1091 | // check file | 1095 | // check file |
@@ -1100,7 +1104,7 @@ void profile_read(const char *fname) { | |||
1100 | char *ptr = strstr(base, ".local"); | 1104 | char *ptr = strstr(base, ".local"); |
1101 | if (ptr && strlen(ptr) == 6) | 1105 | if (ptr && strlen(ptr) == 6) |
1102 | return; | 1106 | return; |
1103 | 1107 | ||
1104 | fprintf(stderr, "Error: cannot access profile file\n"); | 1108 | fprintf(stderr, "Error: cannot access profile file\n"); |
1105 | exit(1); | 1109 | exit(1); |
1106 | } | 1110 | } |
@@ -1114,7 +1118,7 @@ void profile_read(const char *fname) { | |||
1114 | return; | 1118 | return; |
1115 | } | 1119 | } |
1116 | } | 1120 | } |
1117 | 1121 | ||
1118 | // open profile file: | 1122 | // open profile file: |
1119 | FILE *fp = fopen(fname, "r"); | 1123 | FILE *fp = fopen(fname, "r"); |
1120 | if (fp == NULL) { | 1124 | if (fp == NULL) { |
@@ -1133,13 +1137,13 @@ void profile_read(const char *fname) { | |||
1133 | char *ptr = line_remove_spaces(buf); | 1137 | char *ptr = line_remove_spaces(buf); |
1134 | if (ptr == NULL) | 1138 | if (ptr == NULL) |
1135 | continue; | 1139 | continue; |
1136 | 1140 | ||
1137 | // comments | 1141 | // comments |
1138 | if (*ptr == '#' || *ptr == '\0') { | 1142 | if (*ptr == '#' || *ptr == '\0') { |
1139 | free(ptr); | 1143 | free(ptr); |
1140 | continue; | 1144 | continue; |
1141 | } | 1145 | } |
1142 | 1146 | ||
1143 | // process quiet | 1147 | // process quiet |
1144 | if (strcmp(ptr, "quiet") == 0) { | 1148 | if (strcmp(ptr, "quiet") == 0) { |
1145 | arg_quiet = 1; | 1149 | arg_quiet = 1; |
@@ -1155,13 +1159,13 @@ void profile_read(const char *fname) { | |||
1155 | // process include | 1159 | // process include |
1156 | if (strncmp(ptr, "include ", 8) == 0) { | 1160 | if (strncmp(ptr, "include ", 8) == 0) { |
1157 | include_level++; | 1161 | include_level++; |
1158 | 1162 | ||
1159 | // extract profile filename and new skip params | 1163 | // extract profile filename and new skip params |
1160 | char *newprofile = ptr + 8; // profile name | 1164 | char *newprofile = ptr + 8; // profile name |
1161 | 1165 | ||
1162 | // expand ${HOME}/ in front of the new profile file | 1166 | // expand ${HOME}/ in front of the new profile file |
1163 | char *newprofile2 = expand_home(newprofile, cfg.homedir); | 1167 | char *newprofile2 = expand_home(newprofile, cfg.homedir); |
1164 | 1168 | ||
1165 | // recursivity | 1169 | // recursivity |
1166 | profile_read((newprofile2)? newprofile2:newprofile); | 1170 | profile_read((newprofile2)? newprofile2:newprofile); |
1167 | include_level--; | 1171 | include_level--; |
@@ -1170,7 +1174,7 @@ void profile_read(const char *fname) { | |||
1170 | free(ptr); | 1174 | free(ptr); |
1171 | continue; | 1175 | continue; |
1172 | } | 1176 | } |
1173 | 1177 | ||
1174 | // verify syntax, exit in case of error | 1178 | // verify syntax, exit in case of error |
1175 | if (profile_check_line(ptr, lineno, fname)) | 1179 | if (profile_check_line(ptr, lineno, fname)) |
1176 | profile_add(ptr); | 1180 | profile_add(ptr); |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 3ff104d26..0b4d63c1b 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -17,7 +17,7 @@ | |||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | 17 | * with this program; if not, write to the Free Software Foundation, Inc., |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include "firejail.h" | 21 | #include "firejail.h" |
22 | #include <sys/mount.h> | 22 | #include <sys/mount.h> |
23 | #include <sys/wait.h> | 23 | #include <sys/wait.h> |
@@ -65,7 +65,7 @@ static void sandbox_handler(int sig){ | |||
65 | FILE *fp = fopen(monfile, "r"); | 65 | FILE *fp = fopen(monfile, "r"); |
66 | if (!fp) | 66 | if (!fp) |
67 | break; | 67 | break; |
68 | 68 | ||
69 | char c; | 69 | char c; |
70 | size_t count = fread(&c, 1, 1, fp); | 70 | size_t count = fread(&c, 1, 1, fp); |
71 | fclose(fp); | 71 | fclose(fp); |
@@ -78,7 +78,7 @@ static void sandbox_handler(int sig){ | |||
78 | monsec--; | 78 | monsec--; |
79 | } | 79 | } |
80 | free(monfile); | 80 | free(monfile); |
81 | 81 | ||
82 | } | 82 | } |
83 | 83 | ||
84 | 84 | ||
@@ -115,7 +115,7 @@ void save_nogroups(void) { | |||
115 | fprintf(stderr, "Error: cannot save nogroups state\n"); | 115 | fprintf(stderr, "Error: cannot save nogroups state\n"); |
116 | exit(1); | 116 | exit(1); |
117 | } | 117 | } |
118 | 118 | ||
119 | } | 119 | } |
120 | 120 | ||
121 | static void sandbox_if_up(Bridge *br) { | 121 | static void sandbox_if_up(Bridge *br) { |
@@ -132,7 +132,7 @@ static void sandbox_if_up(Bridge *br) { | |||
132 | fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev); | 132 | fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev); |
133 | exit(1); | 133 | exit(1); |
134 | } | 134 | } |
135 | 135 | ||
136 | // just assign the address | 136 | // just assign the address |
137 | assert(br->ipsandbox); | 137 | assert(br->ipsandbox); |
138 | if (arg_debug) | 138 | if (arg_debug) |
@@ -149,19 +149,19 @@ static void sandbox_if_up(Bridge *br) { | |||
149 | fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev); | 149 | fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev); |
150 | exit(1); | 150 | exit(1); |
151 | } | 151 | } |
152 | 152 | ||
153 | uint32_t rv = arp_check(dev, br->ipsandbox, br->ip); | 153 | uint32_t rv = arp_check(dev, br->ipsandbox, br->ip); |
154 | if (rv) { | 154 | if (rv) { |
155 | fprintf(stderr, "Error: the address %d.%d.%d.%d is already in use.\n", PRINT_IP(br->ipsandbox)); | 155 | fprintf(stderr, "Error: the address %d.%d.%d.%d is already in use.\n", PRINT_IP(br->ipsandbox)); |
156 | exit(1); | 156 | exit(1); |
157 | } | 157 | } |
158 | } | 158 | } |
159 | 159 | ||
160 | if (arg_debug) | 160 | if (arg_debug) |
161 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev); | 161 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev); |
162 | net_config_interface(dev, br->ipsandbox, br->mask, br->mtu); | 162 | net_config_interface(dev, br->ipsandbox, br->mask, br->mtu); |
163 | } | 163 | } |
164 | 164 | ||
165 | if (br->ip6sandbox) | 165 | if (br->ip6sandbox) |
166 | net_if_ip6(dev, br->ip6sandbox); | 166 | net_if_ip6(dev, br->ip6sandbox); |
167 | } | 167 | } |
@@ -171,14 +171,14 @@ static void chk_chroot(void) { | |||
171 | char *mycont = getenv("container"); | 171 | char *mycont = getenv("container"); |
172 | if (mycont) | 172 | if (mycont) |
173 | return; | 173 | return; |
174 | 174 | ||
175 | // check if this is a regular chroot | 175 | // check if this is a regular chroot |
176 | struct stat s; | 176 | struct stat s; |
177 | if (stat("/", &s) == 0) { | 177 | if (stat("/", &s) == 0) { |
178 | if (s.st_ino != 2) | 178 | if (s.st_ino != 2) |
179 | return; | 179 | return; |
180 | } | 180 | } |
181 | 181 | ||
182 | fprintf(stderr, "Error: cannot mount filesystem as slave\n"); | 182 | fprintf(stderr, "Error: cannot mount filesystem as slave\n"); |
183 | exit(1); | 183 | exit(1); |
184 | } | 184 | } |
@@ -238,7 +238,7 @@ static int monitor_application(pid_t app_pid) { | |||
238 | continue; | 238 | continue; |
239 | if (pid == 1) | 239 | if (pid == 1) |
240 | continue; | 240 | continue; |
241 | 241 | ||
242 | // todo: make this generic | 242 | // todo: make this generic |
243 | // Dillo browser leaves a dpid process running, we need to shut it down | 243 | // Dillo browser leaves a dpid process running, we need to shut it down |
244 | int found = 0; | 244 | int found = 0; |
@@ -268,7 +268,7 @@ void start_audit(void) { | |||
268 | char *audit_prog; | 268 | char *audit_prog; |
269 | if (asprintf(&audit_prog, "%s/firejail/faudit", LIBDIR) == -1) | 269 | if (asprintf(&audit_prog, "%s/firejail/faudit", LIBDIR) == -1) |
270 | errExit("asprintf"); | 270 | errExit("asprintf"); |
271 | assert(getenv("LD_PRELOAD") == NULL); | 271 | assert(getenv("LD_PRELOAD") == NULL); |
272 | execl(audit_prog, audit_prog, NULL); | 272 | execl(audit_prog, audit_prog, NULL); |
273 | perror("execl"); | 273 | perror("execl"); |
274 | exit(1); | 274 | exit(1); |
@@ -281,7 +281,7 @@ static void print_time(void) { | |||
281 | usleep(1000); | 281 | usleep(1000); |
282 | unsigned long long onems = getticks() - end_timestamp; | 282 | unsigned long long onems = getticks() - end_timestamp; |
283 | if (onems) { | 283 | if (onems) { |
284 | printf("Child process initialized in %.02f ms\n", | 284 | printf("Child process initialized in %.02f ms\n", |
285 | (float) (end_timestamp - start_timestamp) / (float) onems); | 285 | (float) (end_timestamp - start_timestamp) / (float) onems); |
286 | return; | 286 | return; |
287 | } | 287 | } |
@@ -301,7 +301,7 @@ void start_application(void) { | |||
301 | printf("starting application\n"); | 301 | printf("starting application\n"); |
302 | printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD")); | 302 | printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD")); |
303 | } | 303 | } |
304 | 304 | ||
305 | //**************************************** | 305 | //**************************************** |
306 | // audit | 306 | // audit |
307 | //**************************************** | 307 | //**************************************** |
@@ -405,12 +405,12 @@ static void enforce_filters(void) { | |||
405 | free(cfg.seccomp_list_keep); | 405 | free(cfg.seccomp_list_keep); |
406 | cfg.seccomp_list_keep = NULL; | 406 | cfg.seccomp_list_keep = NULL; |
407 | } | 407 | } |
408 | 408 | ||
409 | // disable all capabilities | 409 | // disable all capabilities |
410 | if (arg_caps_default_filter || arg_caps_list) | 410 | if (arg_caps_default_filter || arg_caps_list) |
411 | fwarning("all capabilities disabled for a regular user in chroot\n"); | 411 | fwarning("all capabilities disabled for a regular user in chroot\n"); |
412 | arg_caps_drop_all = 1; | 412 | arg_caps_drop_all = 1; |
413 | 413 | ||
414 | // drop all supplementary groups; /etc/group file inside chroot | 414 | // drop all supplementary groups; /etc/group file inside chroot |
415 | // is controlled by a regular usr | 415 | // is controlled by a regular usr |
416 | arg_nogroups = 1; | 416 | arg_nogroups = 1; |
@@ -424,12 +424,12 @@ int sandbox(void* sandbox_arg) { | |||
424 | 424 | ||
425 | pid_t child_pid = getpid(); | 425 | pid_t child_pid = getpid(); |
426 | if (arg_debug) | 426 | if (arg_debug) |
427 | printf("Initializing child process\n"); | 427 | printf("Initializing child process\n"); |
428 | 428 | ||
429 | // close each end of the unused pipes | 429 | // close each end of the unused pipes |
430 | close(parent_to_child_fds[1]); | 430 | close(parent_to_child_fds[1]); |
431 | close(child_to_parent_fds[0]); | 431 | close(child_to_parent_fds[0]); |
432 | 432 | ||
433 | // wait for parent to do base setup | 433 | // wait for parent to do base setup |
434 | wait_for_other(parent_to_child_fds[0]); | 434 | wait_for_other(parent_to_child_fds[0]); |
435 | 435 | ||
@@ -454,7 +454,7 @@ int sandbox(void* sandbox_arg) { | |||
454 | } | 454 | } |
455 | // ... and mount a tmpfs on top of /run/firejail/mnt directory | 455 | // ... and mount a tmpfs on top of /run/firejail/mnt directory |
456 | preproc_mount_mnt_dir(); | 456 | preproc_mount_mnt_dir(); |
457 | 457 | ||
458 | //**************************** | 458 | //**************************** |
459 | // log sandbox data | 459 | // log sandbox data |
460 | //**************************** | 460 | //**************************** |
@@ -463,12 +463,12 @@ int sandbox(void* sandbox_arg) { | |||
463 | fs_logger2int("sandbox pid:", (int) sandbox_pid); | 463 | fs_logger2int("sandbox pid:", (int) sandbox_pid); |
464 | if (cfg.chrootdir) | 464 | if (cfg.chrootdir) |
465 | fs_logger("sandbox filesystem: chroot"); | 465 | fs_logger("sandbox filesystem: chroot"); |
466 | else if (arg_overlay) | 466 | else if (arg_overlay) |
467 | fs_logger("sandbox filesystem: overlay"); | 467 | fs_logger("sandbox filesystem: overlay"); |
468 | else | 468 | else |
469 | fs_logger("sandbox filesystem: local"); | 469 | fs_logger("sandbox filesystem: local"); |
470 | fs_logger("install mount namespace"); | 470 | fs_logger("install mount namespace"); |
471 | 471 | ||
472 | //**************************** | 472 | //**************************** |
473 | // netfilter | 473 | // netfilter |
474 | //**************************** | 474 | //**************************** |
@@ -496,23 +496,23 @@ int sandbox(void* sandbox_arg) { | |||
496 | else if (any_bridge_configured() || any_interface_configured()) { | 496 | else if (any_bridge_configured() || any_interface_configured()) { |
497 | // configure lo and eth0...eth3 | 497 | // configure lo and eth0...eth3 |
498 | net_if_up("lo"); | 498 | net_if_up("lo"); |
499 | 499 | ||
500 | if (mac_not_zero(cfg.bridge0.macsandbox)) | 500 | if (mac_not_zero(cfg.bridge0.macsandbox)) |
501 | net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox); | 501 | net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox); |
502 | sandbox_if_up(&cfg.bridge0); | 502 | sandbox_if_up(&cfg.bridge0); |
503 | 503 | ||
504 | if (mac_not_zero(cfg.bridge1.macsandbox)) | 504 | if (mac_not_zero(cfg.bridge1.macsandbox)) |
505 | net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox); | 505 | net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox); |
506 | sandbox_if_up(&cfg.bridge1); | 506 | sandbox_if_up(&cfg.bridge1); |
507 | 507 | ||
508 | if (mac_not_zero(cfg.bridge2.macsandbox)) | 508 | if (mac_not_zero(cfg.bridge2.macsandbox)) |
509 | net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox); | 509 | net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox); |
510 | sandbox_if_up(&cfg.bridge2); | 510 | sandbox_if_up(&cfg.bridge2); |
511 | 511 | ||
512 | if (mac_not_zero(cfg.bridge3.macsandbox)) | 512 | if (mac_not_zero(cfg.bridge3.macsandbox)) |
513 | net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox); | 513 | net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox); |
514 | sandbox_if_up(&cfg.bridge3); | 514 | sandbox_if_up(&cfg.bridge3); |
515 | 515 | ||
516 | 516 | ||
517 | // moving an interface in a namespace using --interface will reset the interface configuration; | 517 | // moving an interface in a namespace using --interface will reset the interface configuration; |
518 | // we need to put the configuration back | 518 | // we need to put the configuration back |
@@ -520,23 +520,23 @@ int sandbox(void* sandbox_arg) { | |||
520 | if (arg_debug) | 520 | if (arg_debug) |
521 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface0.ip), cfg.interface0.dev); | 521 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface0.ip), cfg.interface0.dev); |
522 | net_config_interface(cfg.interface0.dev, cfg.interface0.ip, cfg.interface0.mask, cfg.interface0.mtu); | 522 | net_config_interface(cfg.interface0.dev, cfg.interface0.ip, cfg.interface0.mask, cfg.interface0.mtu); |
523 | } | 523 | } |
524 | if (cfg.interface1.configured && cfg.interface1.ip) { | 524 | if (cfg.interface1.configured && cfg.interface1.ip) { |
525 | if (arg_debug) | 525 | if (arg_debug) |
526 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface1.ip), cfg.interface1.dev); | 526 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface1.ip), cfg.interface1.dev); |
527 | net_config_interface(cfg.interface1.dev, cfg.interface1.ip, cfg.interface1.mask, cfg.interface1.mtu); | 527 | net_config_interface(cfg.interface1.dev, cfg.interface1.ip, cfg.interface1.mask, cfg.interface1.mtu); |
528 | } | 528 | } |
529 | if (cfg.interface2.configured && cfg.interface2.ip) { | 529 | if (cfg.interface2.configured && cfg.interface2.ip) { |
530 | if (arg_debug) | 530 | if (arg_debug) |
531 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface2.ip), cfg.interface2.dev); | 531 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface2.ip), cfg.interface2.dev); |
532 | net_config_interface(cfg.interface2.dev, cfg.interface2.ip, cfg.interface2.mask, cfg.interface2.mtu); | 532 | net_config_interface(cfg.interface2.dev, cfg.interface2.ip, cfg.interface2.mask, cfg.interface2.mtu); |
533 | } | 533 | } |
534 | if (cfg.interface3.configured && cfg.interface3.ip) { | 534 | if (cfg.interface3.configured && cfg.interface3.ip) { |
535 | if (arg_debug) | 535 | if (arg_debug) |
536 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface3.ip), cfg.interface3.dev); | 536 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface3.ip), cfg.interface3.dev); |
537 | net_config_interface(cfg.interface3.dev, cfg.interface3.ip, cfg.interface3.mask, cfg.interface3.mtu); | 537 | net_config_interface(cfg.interface3.dev, cfg.interface3.ip, cfg.interface3.mask, cfg.interface3.mtu); |
538 | } | 538 | } |
539 | 539 | ||
540 | // add a default route | 540 | // add a default route |
541 | if (cfg.defaultgw) { | 541 | if (cfg.defaultgw) { |
542 | // set the default route | 542 | // set the default route |
@@ -549,7 +549,7 @@ int sandbox(void* sandbox_arg) { | |||
549 | if (arg_debug) | 549 | if (arg_debug) |
550 | printf("Network namespace enabled\n"); | 550 | printf("Network namespace enabled\n"); |
551 | } | 551 | } |
552 | 552 | ||
553 | 553 | ||
554 | // print network configuration | 554 | // print network configuration |
555 | if (!arg_quiet) { | 555 | if (!arg_quiet) { |
@@ -561,7 +561,7 @@ int sandbox(void* sandbox_arg) { | |||
561 | sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 3, PATH_FNET, "printif", "scan"); | 561 | sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 3, PATH_FNET, "printif", "scan"); |
562 | else | 562 | else |
563 | sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, PATH_FNET, "printif", "scan"); | 563 | sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, PATH_FNET, "printif", "scan"); |
564 | 564 | ||
565 | } | 565 | } |
566 | if (cfg.defaultgw != 0) { | 566 | if (cfg.defaultgw != 0) { |
567 | if (gw_cfg_failed) | 567 | if (gw_cfg_failed) |
@@ -585,7 +585,7 @@ int sandbox(void* sandbox_arg) { | |||
585 | } | 585 | } |
586 | else | 586 | else |
587 | env_ibus_load(); | 587 | env_ibus_load(); |
588 | 588 | ||
589 | //**************************** | 589 | //**************************** |
590 | // fs pre-processing: | 590 | // fs pre-processing: |
591 | // - build seccomp filters | 591 | // - build seccomp filters |
@@ -602,7 +602,7 @@ int sandbox(void* sandbox_arg) { | |||
602 | if (rv) | 602 | if (rv) |
603 | exit(rv); | 603 | exit(rv); |
604 | } | 604 | } |
605 | #endif | 605 | #endif |
606 | 606 | ||
607 | // trace pre-install | 607 | // trace pre-install |
608 | if (arg_trace || arg_tracelog) | 608 | if (arg_trace || arg_tracelog) |
@@ -622,13 +622,13 @@ int sandbox(void* sandbox_arg) { | |||
622 | enforce_filters(); | 622 | enforce_filters(); |
623 | #ifdef HAVE_SECCOMP | 623 | #ifdef HAVE_SECCOMP |
624 | enforce_seccomp = 1; | 624 | enforce_seccomp = 1; |
625 | #endif | 625 | #endif |
626 | } | 626 | } |
627 | 627 | ||
628 | #ifdef HAVE_CHROOT | 628 | #ifdef HAVE_CHROOT |
629 | if (cfg.chrootdir) { | 629 | if (cfg.chrootdir) { |
630 | fs_chroot(cfg.chrootdir); | 630 | fs_chroot(cfg.chrootdir); |
631 | 631 | ||
632 | // force caps and seccomp if not started as root | 632 | // force caps and seccomp if not started as root |
633 | if (getuid() != 0) { | 633 | if (getuid() != 0) { |
634 | enforce_filters(); | 634 | enforce_filters(); |
@@ -638,14 +638,14 @@ int sandbox(void* sandbox_arg) { | |||
638 | } | 638 | } |
639 | else | 639 | else |
640 | arg_seccomp = 1; | 640 | arg_seccomp = 1; |
641 | 641 | ||
642 | //**************************** | 642 | //**************************** |
643 | // trace pre-install, this time inside chroot | 643 | // trace pre-install, this time inside chroot |
644 | //**************************** | 644 | //**************************** |
645 | if (arg_trace || arg_tracelog) | 645 | if (arg_trace || arg_tracelog) |
646 | fs_trace_preload(); | 646 | fs_trace_preload(); |
647 | } | 647 | } |
648 | else | 648 | else |
649 | #endif | 649 | #endif |
650 | #ifdef HAVE_OVERLAYFS | 650 | #ifdef HAVE_OVERLAYFS |
651 | if (arg_overlay) { | 651 | if (arg_overlay) { |
@@ -663,7 +663,7 @@ int sandbox(void* sandbox_arg) { | |||
663 | else | 663 | else |
664 | #endif | 664 | #endif |
665 | fs_basic_fs(); | 665 | fs_basic_fs(); |
666 | 666 | ||
667 | //**************************** | 667 | //**************************** |
668 | // private mode | 668 | // private mode |
669 | //**************************** | 669 | //**************************** |
@@ -696,7 +696,7 @@ int sandbox(void* sandbox_arg) { | |||
696 | else | 696 | else |
697 | fs_private_dev(); | 697 | fs_private_dev(); |
698 | } | 698 | } |
699 | 699 | ||
700 | if (arg_private_etc) { | 700 | if (arg_private_etc) { |
701 | if (cfg.chrootdir) | 701 | if (cfg.chrootdir) |
702 | fwarning("private-etc feature is disabled in chroot\n"); | 702 | fwarning("private-etc feature is disabled in chroot\n"); |
@@ -709,7 +709,7 @@ int sandbox(void* sandbox_arg) { | |||
709 | fs_trace_preload(); | 709 | fs_trace_preload(); |
710 | } | 710 | } |
711 | } | 711 | } |
712 | 712 | ||
713 | if (arg_private_opt) { | 713 | if (arg_private_opt) { |
714 | if (cfg.chrootdir) | 714 | if (cfg.chrootdir) |
715 | fwarning("private-opt feature is disabled in chroot\n"); | 715 | fwarning("private-opt feature is disabled in chroot\n"); |
@@ -719,7 +719,7 @@ int sandbox(void* sandbox_arg) { | |||
719 | fs_private_dir_list("/opt", RUN_OPT_DIR, cfg.opt_private_keep); | 719 | fs_private_dir_list("/opt", RUN_OPT_DIR, cfg.opt_private_keep); |
720 | } | 720 | } |
721 | } | 721 | } |
722 | 722 | ||
723 | if (arg_private_srv) { | 723 | if (arg_private_srv) { |
724 | if (cfg.chrootdir) | 724 | if (cfg.chrootdir) |
725 | fwarning("private-srv feature is disabled in chroot\n"); | 725 | fwarning("private-srv feature is disabled in chroot\n"); |
@@ -729,7 +729,7 @@ int sandbox(void* sandbox_arg) { | |||
729 | fs_private_dir_list("/srv", RUN_SRV_DIR, cfg.srv_private_keep); | 729 | fs_private_dir_list("/srv", RUN_SRV_DIR, cfg.srv_private_keep); |
730 | } | 730 | } |
731 | } | 731 | } |
732 | 732 | ||
733 | if (arg_private_bin) { | 733 | if (arg_private_bin) { |
734 | if (cfg.chrootdir) | 734 | if (cfg.chrootdir) |
735 | fwarning("private-bin feature is disabled in chroot\n"); | 735 | fwarning("private-bin feature is disabled in chroot\n"); |
@@ -748,7 +748,7 @@ int sandbox(void* sandbox_arg) { | |||
748 | fs_private_bin_list(); | 748 | fs_private_bin_list(); |
749 | } | 749 | } |
750 | } | 750 | } |
751 | 751 | ||
752 | if (arg_private_tmp) { | 752 | if (arg_private_tmp) { |
753 | if (cfg.chrootdir) | 753 | if (cfg.chrootdir) |
754 | fwarning("private-tmp feature is disabled in chroot\n"); | 754 | fwarning("private-tmp feature is disabled in chroot\n"); |
@@ -762,7 +762,7 @@ int sandbox(void* sandbox_arg) { | |||
762 | } | 762 | } |
763 | } | 763 | } |
764 | 764 | ||
765 | 765 | ||
766 | //**************************** | 766 | //**************************** |
767 | // hosts and hostname | 767 | // hosts and hostname |
768 | //**************************** | 768 | //**************************** |
@@ -777,19 +777,19 @@ int sandbox(void* sandbox_arg) { | |||
777 | //**************************** | 777 | //**************************** |
778 | if (arg_netns) | 778 | if (arg_netns) |
779 | netns_mounts(arg_netns); | 779 | netns_mounts(arg_netns); |
780 | 780 | ||
781 | //**************************** | 781 | //**************************** |
782 | // update /proc, /sys, /dev, /boot directory | 782 | // update /proc, /sys, /dev, /boot directory |
783 | //**************************** | 783 | //**************************** |
784 | if (checkcfg(CFG_REMOUNT_PROC_SYS)) | 784 | if (checkcfg(CFG_REMOUNT_PROC_SYS)) |
785 | fs_proc_sys_dev_boot(); | 785 | fs_proc_sys_dev_boot(); |
786 | 786 | ||
787 | //**************************** | 787 | //**************************** |
788 | // handle /mnt and /media | 788 | // handle /mnt and /media |
789 | //**************************** | 789 | //**************************** |
790 | if (checkcfg(CFG_DISABLE_MNT)) | 790 | if (checkcfg(CFG_DISABLE_MNT)) |
791 | fs_mnt(); | 791 | fs_mnt(); |
792 | 792 | ||
793 | //**************************** | 793 | //**************************** |
794 | // nosound/no3d and fix for pulseaudio 7.0 | 794 | // nosound/no3d and fix for pulseaudio 7.0 |
795 | //**************************** | 795 | //**************************** |
@@ -802,35 +802,43 @@ int sandbox(void* sandbox_arg) { | |||
802 | } | 802 | } |
803 | else | 803 | else |
804 | pulseaudio_init(); | 804 | pulseaudio_init(); |
805 | 805 | ||
806 | if (arg_no3d) | 806 | if (arg_no3d) |
807 | fs_dev_disable_3d(); | 807 | fs_dev_disable_3d(); |
808 | 808 | ||
809 | //**************************** | ||
810 | // novideo | ||
811 | //**************************** | ||
812 | if (arg_novideo) { | ||
813 | // disable /dev/video* | ||
814 | fs_dev_disable_video(); | ||
815 | } | ||
816 | |||
809 | //**************************** | 817 | //**************************** |
810 | // apply the profile file | 818 | // apply the profile file |
811 | //**************************** | 819 | //**************************** |
812 | // apply all whitelist commands ... | 820 | // apply all whitelist commands ... |
813 | if (cfg.chrootdir) | 821 | if (cfg.chrootdir) |
814 | fwarning("whitelist feature is disabled in chroot\n"); | 822 | fwarning("whitelist feature is disabled in chroot\n"); |
815 | else if (arg_overlay) | 823 | else if (arg_overlay) |
816 | fwarning("whitelist feature is disabled in overlay\n"); | 824 | fwarning("whitelist feature is disabled in overlay\n"); |
817 | else | 825 | else |
818 | fs_whitelist(); | 826 | fs_whitelist(); |
819 | 827 | ||
820 | // ... followed by blacklist commands | 828 | // ... followed by blacklist commands |
821 | fs_blacklist(); // mkdir and mkfile are processed all over again | 829 | fs_blacklist(); // mkdir and mkfile are processed all over again |
822 | 830 | ||
823 | //**************************** | 831 | //**************************** |
824 | // install trace | 832 | // install trace |
825 | //**************************** | 833 | //**************************** |
826 | if (arg_trace || arg_tracelog) | 834 | if (arg_trace || arg_tracelog) |
827 | fs_trace(); | 835 | fs_trace(); |
828 | 836 | ||
829 | //**************************** | 837 | //**************************** |
830 | // set dns | 838 | // set dns |
831 | //**************************** | 839 | //**************************** |
832 | fs_resolvconf(); | 840 | fs_resolvconf(); |
833 | 841 | ||
834 | //**************************** | 842 | //**************************** |
835 | // fs post-processing | 843 | // fs post-processing |
836 | //**************************** | 844 | //**************************** |
@@ -846,7 +854,7 @@ int sandbox(void* sandbox_arg) { | |||
846 | if (chdir(cfg.cwd) == 0) | 854 | if (chdir(cfg.cwd) == 0) |
847 | cwd = 1; | 855 | cwd = 1; |
848 | } | 856 | } |
849 | 857 | ||
850 | if (!cwd) { | 858 | if (!cwd) { |
851 | if (chdir("/") < 0) | 859 | if (chdir("/") < 0) |
852 | errExit("chdir"); | 860 | errExit("chdir"); |
@@ -866,8 +874,8 @@ int sandbox(void* sandbox_arg) { | |||
866 | free(cpath); | 874 | free(cpath); |
867 | } | 875 | } |
868 | } | 876 | } |
869 | 877 | ||
870 | 878 | ||
871 | // set nice | 879 | // set nice |
872 | if (arg_nice) { | 880 | if (arg_nice) { |
873 | errno = 0; | 881 | errno = 0; |
@@ -878,12 +886,12 @@ int sandbox(void* sandbox_arg) { | |||
878 | errno = 0; | 886 | errno = 0; |
879 | } | 887 | } |
880 | } | 888 | } |
881 | 889 | ||
882 | // clean /tmp/.X11-unix sockets | 890 | // clean /tmp/.X11-unix sockets |
883 | fs_x11(); | 891 | fs_x11(); |
884 | if (arg_x11_xorg) | 892 | if (arg_x11_xorg) |
885 | x11_xorg(); | 893 | x11_xorg(); |
886 | 894 | ||
887 | //**************************** | 895 | //**************************** |
888 | // set security filters | 896 | // set security filters |
889 | //**************************** | 897 | //**************************** |
@@ -899,7 +907,7 @@ int sandbox(void* sandbox_arg) { | |||
899 | save_cpu(); // save cpu affinity mask to CPU_CFG file | 907 | save_cpu(); // save cpu affinity mask to CPU_CFG file |
900 | set_cpu_affinity(); | 908 | set_cpu_affinity(); |
901 | } | 909 | } |
902 | 910 | ||
903 | // save cgroup in CGROUP_CFG file | 911 | // save cgroup in CGROUP_CFG file |
904 | if (cfg.cgroup) | 912 | if (cfg.cgroup) |
905 | save_cgroup(); | 913 | save_cgroup(); |
@@ -911,7 +919,7 @@ int sandbox(void* sandbox_arg) { | |||
911 | if (cfg.protocol) { | 919 | if (cfg.protocol) { |
912 | if (arg_debug) | 920 | if (arg_debug) |
913 | printf("Install protocol filter: %s\n", cfg.protocol); | 921 | printf("Install protocol filter: %s\n", cfg.protocol); |
914 | seccomp_load(RUN_SECCOMP_PROTOCOL); // install filter | 922 | seccomp_load(RUN_SECCOMP_PROTOCOL); // install filter |
915 | protocol_filter_save(); // save filter in RUN_PROTOCOL_CFG | 923 | protocol_filter_save(); // save filter in RUN_PROTOCOL_CFG |
916 | } | 924 | } |
917 | #endif | 925 | #endif |
@@ -939,12 +947,12 @@ int sandbox(void* sandbox_arg) { | |||
939 | } | 947 | } |
940 | else | 948 | else |
941 | drop_privs(arg_nogroups); | 949 | drop_privs(arg_nogroups); |
942 | 950 | ||
943 | // notify parent that new user namespace has been created so a proper | 951 | // notify parent that new user namespace has been created so a proper |
944 | // UID/GID map can be setup | 952 | // UID/GID map can be setup |
945 | notify_other(child_to_parent_fds[1]); | 953 | notify_other(child_to_parent_fds[1]); |
946 | close(child_to_parent_fds[1]); | 954 | close(child_to_parent_fds[1]); |
947 | 955 | ||
948 | // wait for parent to finish setting up a proper UID/GID map | 956 | // wait for parent to finish setting up a proper UID/GID map |
949 | wait_for_other(parent_to_child_fds[0]); | 957 | wait_for_other(parent_to_child_fds[0]); |
950 | close(parent_to_child_fds[0]); | 958 | close(parent_to_child_fds[0]); |
@@ -956,7 +964,7 @@ int sandbox(void* sandbox_arg) { | |||
956 | printf("noroot user namespace installed\n"); | 964 | printf("noroot user namespace installed\n"); |
957 | set_caps(); | 965 | set_caps(); |
958 | } | 966 | } |
959 | 967 | ||
960 | //**************************************** | 968 | //**************************************** |
961 | // Set NO_NEW_PRIVS if desired | 969 | // Set NO_NEW_PRIVS if desired |
962 | //**************************************** | 970 | //**************************************** |
@@ -989,7 +997,7 @@ int sandbox(void* sandbox_arg) { | |||
989 | else if (arg_debug) | 997 | else if (arg_debug) |
990 | printf("AppArmor enabled\n"); | 998 | printf("AppArmor enabled\n"); |
991 | } | 999 | } |
992 | #endif | 1000 | #endif |
993 | prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died | 1001 | prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died |
994 | start_application(); // start app | 1002 | start_application(); // start app |
995 | } | 1003 | } |
diff --git a/src/firejail/usage.c b/src/firejail/usage.c index a21633349..76930e1de 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c | |||
@@ -36,10 +36,10 @@ void usage(void) { | |||
36 | printf(" --apparmor - enable AppArmor confinement.\n"); | 36 | printf(" --apparmor - enable AppArmor confinement.\n"); |
37 | printf(" --appimage - sandbox an AppImage application.\n"); | 37 | printf(" --appimage - sandbox an AppImage application.\n"); |
38 | printf(" --audit[=test-program] - audit the sandbox.\n"); | 38 | printf(" --audit[=test-program] - audit the sandbox.\n"); |
39 | #ifdef HAVE_NETWORK | 39 | #ifdef HAVE_NETWORK |
40 | printf(" --bandwidth=name|pid - set bandwidth limits.\n"); | 40 | printf(" --bandwidth=name|pid - set bandwidth limits.\n"); |
41 | #endif | 41 | #endif |
42 | #ifdef HAVE_BIND | 42 | #ifdef HAVE_BIND |
43 | printf(" --bind=dirname1,dirname2 - mount-bind dirname1 on top of dirname2.\n"); | 43 | printf(" --bind=dirname1,dirname2 - mount-bind dirname1 on top of dirname2.\n"); |
44 | printf(" --bind=filename1,filename2 - mount-bind filename1 on top of filename2.\n"); | 44 | printf(" --bind=filename1,filename2 - mount-bind filename1 on top of filename2.\n"); |
45 | #endif | 45 | #endif |
@@ -51,7 +51,7 @@ void usage(void) { | |||
51 | printf(" --caps.keep=capability,capability - whitelist capabilities filter.\n"); | 51 | printf(" --caps.keep=capability,capability - whitelist capabilities filter.\n"); |
52 | printf(" --caps.print=name|pid - print the caps filter.\n"); | 52 | printf(" --caps.print=name|pid - print the caps filter.\n"); |
53 | printf(" --cgroup=tasks-file - place the sandbox in the specified control group.\n"); | 53 | printf(" --cgroup=tasks-file - place the sandbox in the specified control group.\n"); |
54 | #ifdef HAVE_CHROOT | 54 | #ifdef HAVE_CHROOT |
55 | printf(" --chroot=dirname - chroot into directory.\n"); | 55 | printf(" --chroot=dirname - chroot into directory.\n"); |
56 | #endif | 56 | #endif |
57 | printf(" --cpu=cpu-number,cpu-number - set cpu affinity.\n"); | 57 | printf(" --cpu=cpu-number,cpu-number - set cpu affinity.\n"); |
@@ -64,15 +64,15 @@ void usage(void) { | |||
64 | printf(" --debug-errnos - print all recognized error numbers.\n"); | 64 | printf(" --debug-errnos - print all recognized error numbers.\n"); |
65 | printf(" --debug-protocols - print all recognized protocols.\n"); | 65 | printf(" --debug-protocols - print all recognized protocols.\n"); |
66 | printf(" --debug-syscalls - print all recognized system calls.\n"); | 66 | printf(" --debug-syscalls - print all recognized system calls.\n"); |
67 | #ifdef HAVE_WHITELIST | 67 | #ifdef HAVE_WHITELIST |
68 | printf(" --debug-whitelists - debug whitelisting.\n"); | 68 | printf(" --debug-whitelists - debug whitelisting.\n"); |
69 | #endif | 69 | #endif |
70 | #ifdef HAVE_NETWORK | 70 | #ifdef HAVE_NETWORK |
71 | printf(" --defaultgw=address - configure default gateway.\n"); | 71 | printf(" --defaultgw=address - configure default gateway.\n"); |
72 | #endif | 72 | #endif |
73 | printf(" --dns=address - set DNS server.\n"); | 73 | printf(" --dns=address - set DNS server.\n"); |
74 | printf(" --dns.print=name|pid - print DNS configuration.\n"); | 74 | printf(" --dns.print=name|pid - print DNS configuration.\n"); |
75 | 75 | ||
76 | printf(" --env=name=value - set environment variable.\n"); | 76 | printf(" --env=name=value - set environment variable.\n"); |
77 | printf(" --force - attempt to start a new sandbox inside the existing sandbox.\n"); | 77 | printf(" --force - attempt to start a new sandbox inside the existing sandbox.\n"); |
78 | printf(" --fs.print=name|pid - print the filesystem log.\n"); | 78 | printf(" --fs.print=name|pid - print the filesystem log.\n"); |
@@ -86,7 +86,7 @@ void usage(void) { | |||
86 | printf(" --hostname=name - set sandbox hostname.\n"); | 86 | printf(" --hostname=name - set sandbox hostname.\n"); |
87 | printf(" --hosts-file=file - use file as /etc/hosts.\n"); | 87 | printf(" --hosts-file=file - use file as /etc/hosts.\n"); |
88 | printf(" --ignore=command - ignore command in profile files.\n"); | 88 | printf(" --ignore=command - ignore command in profile files.\n"); |
89 | #ifdef HAVE_NETWORK | 89 | #ifdef HAVE_NETWORK |
90 | printf(" --interface=name - move interface in sandbox.\n"); | 90 | printf(" --interface=name - move interface in sandbox.\n"); |
91 | printf(" --ip=address - set interface IP address.\n"); | 91 | printf(" --ip=address - set interface IP address.\n"); |
92 | printf(" --ip=none - no IP address and no default gateway are configured.\n"); | 92 | printf(" --ip=none - no IP address and no default gateway are configured.\n"); |
@@ -96,21 +96,21 @@ void usage(void) { | |||
96 | printf(" --ipc-namespace - enable a new IPC namespace.\n"); | 96 | printf(" --ipc-namespace - enable a new IPC namespace.\n"); |
97 | printf(" --join=name|pid - join the sandbox.\n"); | 97 | printf(" --join=name|pid - join the sandbox.\n"); |
98 | printf(" --join-filesystem=name|pid - join the mount namespace.\n"); | 98 | printf(" --join-filesystem=name|pid - join the mount namespace.\n"); |
99 | #ifdef HAVE_NETWORK | 99 | #ifdef HAVE_NETWORK |
100 | printf(" --join-network=name|pid - join the network namespace.\n"); | 100 | printf(" --join-network=name|pid - join the network namespace.\n"); |
101 | #endif | 101 | #endif |
102 | printf(" --join-or-start=name|pid - join the sandbox or start a new one.\n"); | 102 | printf(" --join-or-start=name|pid - join the sandbox or start a new one.\n"); |
103 | printf(" --list - list all sandboxes.\n"); | 103 | printf(" --list - list all sandboxes.\n"); |
104 | printf(" --ls=name|pid dir_or_filename - list files in sandbox container.\n"); | 104 | printf(" --ls=name|pid dir_or_filename - list files in sandbox container.\n"); |
105 | #ifdef HAVE_NETWORK | 105 | #ifdef HAVE_NETWORK |
106 | printf(" --mac=xx:xx:xx:xx:xx:xx - set interface MAC address.\n"); | 106 | printf(" --mac=xx:xx:xx:xx:xx:xx - set interface MAC address.\n"); |
107 | #endif | 107 | #endif |
108 | printf(" --machine-id - preserve /etc/machine-id\n"); | 108 | printf(" --machine-id - preserve /etc/machine-id\n"); |
109 | #ifdef HAVE_NETWORK | 109 | #ifdef HAVE_NETWORK |
110 | printf(" --mtu=number - set interface MTU.\n"); | 110 | printf(" --mtu=number - set interface MTU.\n"); |
111 | #endif | 111 | #endif |
112 | printf(" --name=name - set sandbox name.\n"); | 112 | printf(" --name=name - set sandbox name.\n"); |
113 | #ifdef HAVE_NETWORK | 113 | #ifdef HAVE_NETWORK |
114 | printf(" --net=bridgename - enable network namespaces and connect to this bridge.\n"); | 114 | printf(" --net=bridgename - enable network namespaces and connect to this bridge.\n"); |
115 | printf(" --net=ethernet_interface - enable network namespaces and connect to this\n"); | 115 | printf(" --net=ethernet_interface - enable network namespaces and connect to this\n"); |
116 | printf("\tEthernet interface.\n"); | 116 | printf("\tEthernet interface.\n"); |
@@ -127,17 +127,18 @@ void usage(void) { | |||
127 | printf(" --nogroups - disable supplementary groups.\n"); | 127 | printf(" --nogroups - disable supplementary groups.\n"); |
128 | printf(" --nonewprivs - sets the NO_NEW_PRIVS prctl.\n"); | 128 | printf(" --nonewprivs - sets the NO_NEW_PRIVS prctl.\n"); |
129 | printf(" --noprofile - do not use a security profile.\n"); | 129 | printf(" --noprofile - do not use a security profile.\n"); |
130 | #ifdef HAVE_USERNS | 130 | #ifdef HAVE_USERNS |
131 | printf(" --noroot - install a user namespace with only the current user.\n"); | 131 | printf(" --noroot - install a user namespace with only the current user.\n"); |
132 | #endif | 132 | #endif |
133 | printf(" --nosound - disable sound system.\n"); | 133 | printf(" --nosound - disable sound system.\n"); |
134 | printf(" --novideo - disable video devices.\n"); | ||
134 | printf(" --nowhitelist=filename - disable whitelist for file or directory .\n"); | 135 | printf(" --nowhitelist=filename - disable whitelist for file or directory .\n"); |
135 | printf(" --output=logfile - stdout logging and log rotation.\n"); | 136 | printf(" --output=logfile - stdout logging and log rotation.\n"); |
136 | printf(" --overlay - mount a filesystem overlay on top of the current filesystem.\n"); | 137 | printf(" --overlay - mount a filesystem overlay on top of the current filesystem.\n"); |
137 | printf(" --overlay-named=name - mount a filesystem overlay on top of the current\n"); | 138 | printf(" --overlay-named=name - mount a filesystem overlay on top of the current\n"); |
138 | printf("\tfilesystem, and store it in name directory.\n"); | 139 | printf("\tfilesystem, and store it in name directory.\n"); |
139 | printf(" --overlay-tmpfs - mount a temporary filesystem overlay on top of the current\n"); | 140 | printf(" --overlay-tmpfs - mount a temporary filesystem overlay on top of the current\n"); |
140 | printf("\tfilesystem.\n"); | 141 | printf("\tfilesystem.\n"); |
141 | printf(" --overlay-clean - clean all overlays stored in $HOME/.firejail directory.\n"); | 142 | printf(" --overlay-clean - clean all overlays stored in $HOME/.firejail directory.\n"); |
142 | printf(" --private - temporary home directory.\n"); | 143 | printf(" --private - temporary home directory.\n"); |
143 | printf(" --private=directory - use directory as user home.\n"); | 144 | printf(" --private=directory - use directory as user home.\n"); |
@@ -169,9 +170,9 @@ void usage(void) { | |||
169 | printf(" --rlimit-sigpending=number - set the maximum number of pending signals\n"); | 170 | printf(" --rlimit-sigpending=number - set the maximum number of pending signals\n"); |
170 | printf("\tfor a process.\n"); | 171 | printf("\tfor a process.\n"); |
171 | printf(" --rmenv=name - remove environment variable in the new sandbox.\n"); | 172 | printf(" --rmenv=name - remove environment variable in the new sandbox.\n"); |
172 | #ifdef HAVE_NETWORK | 173 | #ifdef HAVE_NETWORK |
173 | printf(" --scan - ARP-scan all the networks from inside a network namespace.\n"); | 174 | printf(" --scan - ARP-scan all the networks from inside a network namespace.\n"); |
174 | #endif | 175 | #endif |
175 | #ifdef HAVE_SECCOMP | 176 | #ifdef HAVE_SECCOMP |
176 | printf(" --seccomp - enable seccomp filter and apply the default blacklist.\n"); | 177 | printf(" --seccomp - enable seccomp filter and apply the default blacklist.\n"); |
177 | printf(" --seccomp=syscall,syscall,syscall - enable seccomp filter, blacklist the\n"); | 178 | printf(" --seccomp=syscall,syscall,syscall - enable seccomp filter, blacklist the\n"); |
@@ -195,12 +196,12 @@ void usage(void) { | |||
195 | printf("\tdirectoires blacklisted by the security profile.\n"); | 196 | printf("\tdirectoires blacklisted by the security profile.\n"); |
196 | printf(" --tree - print a tree of all sandboxed processes.\n"); | 197 | printf(" --tree - print a tree of all sandboxed processes.\n"); |
197 | printf(" --version - print program version and exit.\n"); | 198 | printf(" --version - print program version and exit.\n"); |
198 | #ifdef HAVE_NETWORK | 199 | #ifdef HAVE_NETWORK |
199 | printf(" --veth-name=name - use this name for the interface connected to the bridge.\n"); | 200 | printf(" --veth-name=name - use this name for the interface connected to the bridge.\n"); |
200 | #endif | 201 | #endif |
201 | #ifdef HAVE_WHITELIST | 202 | #ifdef HAVE_WHITELIST |
202 | printf(" --whitelist=filename - whitelist directory or file.\n"); | 203 | printf(" --whitelist=filename - whitelist directory or file.\n"); |
203 | #endif | 204 | #endif |
204 | printf(" --writable-etc - /etc directory is mounted read-write.\n"); | 205 | printf(" --writable-etc - /etc directory is mounted read-write.\n"); |
205 | printf(" --writable-var - /var directory is mounted read-write.\n"); | 206 | printf(" --writable-var - /var directory is mounted read-write.\n"); |
206 | printf(" --writable-var-log - use the real /var/log directory, not a clone.\n"); | 207 | printf(" --writable-var-log - use the real /var/log directory, not a clone.\n"); |
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index bb1bd86b9..cbffa9ce4 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt | |||
@@ -50,7 +50,7 @@ Parent pid 8553, child pid 8554 | |||
50 | .br | 50 | .br |
51 | Child process initialized | 51 | Child process initialized |
52 | .br | 52 | .br |
53 | [...] | 53 | [...] |
54 | .br | 54 | .br |
55 | 55 | ||
56 | .br | 56 | .br |
@@ -92,7 +92,7 @@ Example: "include ${CFG}/firefox.profile" will load "/etc/firejail/firefox.profi | |||
92 | 92 | ||
93 | System configuration files in ${CFG} are overwritten during software installation. | 93 | System configuration files in ${CFG} are overwritten during software installation. |
94 | Persistent configuration at system level is handled in ".local" files. For every | 94 | Persistent configuration at system level is handled in ".local" files. For every |
95 | profile file in ${CFG} directory, the user can create a corresponding .local file | 95 | profile file in ${CFG} directory, the user can create a corresponding .local file |
96 | storing modifications to the persistent configuration. Persistent .local files | 96 | storing modifications to the persistent configuration. Persistent .local files |
97 | are included at the start of regular profile files. | 97 | are included at the start of regular profile files. |
98 | 98 | ||
@@ -255,7 +255,7 @@ Blacklist violations logged to syslog. | |||
255 | \fBwhitelist file_or_directory | 255 | \fBwhitelist file_or_directory |
256 | Whitelist directory or file. A temporary file system is mounted on the top directory, and the | 256 | Whitelist directory or file. A temporary file system is mounted on the top directory, and the |
257 | whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, | 257 | whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, |
258 | everything else is discarded when the sandbox is closed. The top directory could be | 258 | everything else is discarded when the sandbox is closed. The top directory could be |
259 | user home, /dev, /media, /mnt, /opt, /srv, /var, and /tmp. | 259 | user home, /dev, /media, /mnt, /opt, /srv, /var, and /tmp. |
260 | .br | 260 | .br |
261 | 261 | ||
@@ -405,6 +405,8 @@ Enable IPC namespace. | |||
405 | \fBnosound | 405 | \fBnosound |
406 | Disable sound system. | 406 | Disable sound system. |
407 | .TP | 407 | .TP |
408 | \fBnovideo | ||
409 | Disable video devices. | ||
408 | \fBno3d | 410 | \fBno3d |
409 | Disable 3D hardware acceleration. | 411 | Disable 3D hardware acceleration. |
410 | 412 | ||
@@ -533,7 +535,7 @@ really need network access. | |||
533 | 535 | ||
534 | .TP | 536 | .TP |
535 | \fBveth-name name | 537 | \fBveth-name name |
536 | Use this name for the interface connected to the bridge for --net=bridge_interface commands, | 538 | Use this name for the interface connected to the bridge for --net=bridge_interface commands, |
537 | instead of the default one. | 539 | instead of the default one. |
538 | 540 | ||
539 | .SH Other | 541 | .SH Other |
@@ -585,6 +587,3 @@ Homepage: http://firejail.wordpress.com | |||
585 | \&\flfiremon\fR\|(1), | 587 | \&\flfiremon\fR\|(1), |
586 | \&\flfirecfg\fR\|(1), | 588 | \&\flfirecfg\fR\|(1), |
587 | \&\flfirejail-login\fR\|(5) | 589 | \&\flfirejail-login\fR\|(5) |
588 | |||
589 | |||
590 | |||
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 38bb6a19e..de300d47b 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -42,7 +42,7 @@ and it is integrated with Linux Control Groups. | |||
42 | .PP | 42 | .PP |
43 | Written in C with virtually no dependencies, the software runs on any Linux computer with a 3.x kernel version | 43 | Written in C with virtually no dependencies, the software runs on any Linux computer with a 3.x kernel version |
44 | or newer. | 44 | or newer. |
45 | It can sandbox any type of processes: servers, graphical applications, and even user login sessions. | 45 | It can sandbox any type of processes: servers, graphical applications, and even user login sessions. |
46 | .PP | 46 | .PP |
47 | Firejail allows the user to manage application security using security profiles. | 47 | Firejail allows the user to manage application security using security profiles. |
48 | Each profile defines a set of permissions for a specific application or group | 48 | Each profile defines a set of permissions for a specific application or group |
@@ -52,13 +52,13 @@ Linux programs, such as Mozilla Firefox, Chromium, VLC, Transmission etc. | |||
52 | .SH USAGE | 52 | .SH USAGE |
53 | Without any options, the sandbox consists of a filesystem build in a new mount namespace, | 53 | Without any options, the sandbox consists of a filesystem build in a new mount namespace, |
54 | and new PID and UTS namespaces. IPC, network and user namespaces can be added using the | 54 | and new PID and UTS namespaces. IPC, network and user namespaces can be added using the |
55 | command line options. The default Firejail filesystem is based on the host filesystem with the main | 55 | command line options. The default Firejail filesystem is based on the host filesystem with the main |
56 | system directories mounted read-only. These directories are /etc, /var, /usr, /bin, /sbin, /lib, /lib32, | 56 | system directories mounted read-only. These directories are /etc, /var, /usr, /bin, /sbin, /lib, /lib32, |
57 | /libx32 and /lib64. Only /home and /tmp are writable. | 57 | /libx32 and /lib64. Only /home and /tmp are writable. |
58 | .PP | 58 | .PP |
59 | As it starts up, Firejail tries to find a security profile based on the name of the application. | 59 | As it starts up, Firejail tries to find a security profile based on the name of the application. |
60 | If an appropriate profile is not found, Firejail will use a default profile. | 60 | If an appropriate profile is not found, Firejail will use a default profile. |
61 | The default profile is quite restrictive. In case the application doesn't work, use --noprofile option | 61 | The default profile is quite restrictive. In case the application doesn't work, use --noprofile option |
62 | to disable it. For more information, please see \fBSECURITY PROFILES\fR section below. | 62 | to disable it. For more information, please see \fBSECURITY PROFILES\fR section below. |
63 | .PP | 63 | .PP |
64 | If a program argument is not specified, Firejail starts /bin/bash shell. | 64 | If a program argument is not specified, Firejail starts /bin/bash shell. |
@@ -657,7 +657,7 @@ $ sudo firejail --join-network=browser ip addr | |||
657 | .br | 657 | .br |
658 | Switching to pid 1932, the first child process inside the sandbox | 658 | Switching to pid 1932, the first child process inside the sandbox |
659 | .br | 659 | .br |
660 | 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default | 660 | 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default |
661 | .br | 661 | .br |
662 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 | 662 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 |
663 | .br | 663 | .br |
@@ -665,11 +665,11 @@ Switching to pid 1932, the first child process inside the sandbox | |||
665 | .br | 665 | .br |
666 | valid_lft forever preferred_lft forever | 666 | valid_lft forever preferred_lft forever |
667 | .br | 667 | .br |
668 | inet6 ::1/128 scope host | 668 | inet6 ::1/128 scope host |
669 | .br | 669 | .br |
670 | valid_lft forever preferred_lft forever | 670 | valid_lft forever preferred_lft forever |
671 | .br | 671 | .br |
672 | 2: eth0-1931: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default | 672 | 2: eth0-1931: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default |
673 | .br | 673 | .br |
674 | link/ether 76:58:14:42:78:e4 brd ff:ff:ff:ff:ff:ff | 674 | link/ether 76:58:14:42:78:e4 brd ff:ff:ff:ff:ff:ff |
675 | .br | 675 | .br |
@@ -677,7 +677,7 @@ Switching to pid 1932, the first child process inside the sandbox | |||
677 | .br | 677 | .br |
678 | valid_lft forever preferred_lft forever | 678 | valid_lft forever preferred_lft forever |
679 | .br | 679 | .br |
680 | inet6 fe80::7458:14ff:fe42:78e4/64 scope link | 680 | inet6 fe80::7458:14ff:fe42:78e4/64 scope link |
681 | .br | 681 | .br |
682 | valid_lft forever preferred_lft forever | 682 | valid_lft forever preferred_lft forever |
683 | 683 | ||
@@ -702,13 +702,13 @@ Example: | |||
702 | .br | 702 | .br |
703 | $ firejail \-\-list | 703 | $ firejail \-\-list |
704 | .br | 704 | .br |
705 | 7015:netblue:firejail firefox | 705 | 7015:netblue:firejail firefox |
706 | .br | 706 | .br |
707 | 7056:netblue:firejail \-\-net=eth0 transmission-gtk | 707 | 7056:netblue:firejail \-\-net=eth0 transmission-gtk |
708 | .br | 708 | .br |
709 | 7064:netblue:firejail \-\-noroot xterm | 709 | 7064:netblue:firejail \-\-noroot xterm |
710 | .br | 710 | .br |
711 | $ | 711 | $ |
712 | .TP | 712 | .TP |
713 | \fB\-\-mac=address | 713 | \fB\-\-mac=address |
714 | Assign MAC addresses to the last network interface defined by a \-\-net option. | 714 | Assign MAC addresses to the last network interface defined by a \-\-net option. |
@@ -998,7 +998,7 @@ $ | |||
998 | 998 | ||
999 | .TP | 999 | .TP |
1000 | \fB\-\-noprofile | 1000 | \fB\-\-noprofile |
1001 | Do not use a security profile. | 1001 | Do not use a security profile. |
1002 | .br | 1002 | .br |
1003 | 1003 | ||
1004 | .br | 1004 | .br |
@@ -1012,7 +1012,7 @@ Parent pid 8553, child pid 8554 | |||
1012 | .br | 1012 | .br |
1013 | Child process initialized | 1013 | Child process initialized |
1014 | .br | 1014 | .br |
1015 | [...] | 1015 | [...] |
1016 | .br | 1016 | .br |
1017 | 1017 | ||
1018 | .br | 1018 | .br |
@@ -1067,6 +1067,11 @@ Example: | |||
1067 | $ firejail \-\-nosound firefox | 1067 | $ firejail \-\-nosound firefox |
1068 | 1068 | ||
1069 | .TP | 1069 | .TP |
1070 | \fB\-\-novideo | ||
1071 | Disable video devices. | ||
1072 | .br | ||
1073 | |||
1074 | .TP | ||
1070 | \fB\-\-nowhitelist=dirname_or_filename | 1075 | \fB\-\-nowhitelist=dirname_or_filename |
1071 | Disable whitelist for this directory or file. | 1076 | Disable whitelist for this directory or file. |
1072 | 1077 | ||
@@ -1200,7 +1205,7 @@ $ firejail \-\-private-home=.mozilla firefox | |||
1200 | Build a new /bin in a temporary filesystem, and copy the programs in the list. | 1205 | Build a new /bin in a temporary filesystem, and copy the programs in the list. |
1201 | If no listed file is found, /bin directory will be empty. | 1206 | If no listed file is found, /bin directory will be empty. |
1202 | The same directory is also bind-mounted over /sbin, /usr/bin, /usr/sbin and /usr/local/bin. | 1207 | The same directory is also bind-mounted over /sbin, /usr/bin, /usr/sbin and /usr/local/bin. |
1203 | All modifications are discarded when the sandbox is closed. | 1208 | All modifications are discarded when the sandbox is closed. |
1204 | .br | 1209 | .br |
1205 | 1210 | ||
1206 | .br | 1211 | .br |
@@ -1240,7 +1245,7 @@ $ | |||
1240 | Build a new /etc in a temporary | 1245 | Build a new /etc in a temporary |
1241 | filesystem, and copy the files and directories in the list. | 1246 | filesystem, and copy the files and directories in the list. |
1242 | If no listed file is found, /etc directory will be empty. | 1247 | If no listed file is found, /etc directory will be empty. |
1243 | All modifications are discarded when the sandbox is closed. | 1248 | All modifications are discarded when the sandbox is closed. |
1244 | .br | 1249 | .br |
1245 | 1250 | ||
1246 | .br | 1251 | .br |
@@ -1255,7 +1260,7 @@ nsswitch.conf,passwd,resolv.conf | |||
1255 | Build a new /opt in a temporary | 1260 | Build a new /opt in a temporary |
1256 | filesystem, and copy the files and directories in the list. | 1261 | filesystem, and copy the files and directories in the list. |
1257 | If no listed file is found, /opt directory will be empty. | 1262 | If no listed file is found, /opt directory will be empty. |
1258 | All modifications are discarded when the sandbox is closed. | 1263 | All modifications are discarded when the sandbox is closed. |
1259 | .br | 1264 | .br |
1260 | 1265 | ||
1261 | .br | 1266 | .br |
@@ -1268,7 +1273,7 @@ $ firejail --private-opt=firefox /opt/firefox/firefox | |||
1268 | Build a new /srv in a temporary | 1273 | Build a new /srv in a temporary |
1269 | filesystem, and copy the files and directories in the list. | 1274 | filesystem, and copy the files and directories in the list. |
1270 | If no listed file is found, /srv directory will be empty. | 1275 | If no listed file is found, /srv directory will be empty. |
1271 | All modifications are discarded when the sandbox is closed. | 1276 | All modifications are discarded when the sandbox is closed. |
1272 | .br | 1277 | .br |
1273 | 1278 | ||
1274 | .br | 1279 | .br |
@@ -1573,7 +1578,7 @@ SECCOMP Filter: | |||
1573 | .br | 1578 | .br |
1574 | RETURN_ALLOW | 1579 | RETURN_ALLOW |
1575 | .br | 1580 | .br |
1576 | $ | 1581 | $ |
1577 | .TP | 1582 | .TP |
1578 | \fB\-\-shell=none | 1583 | \fB\-\-shell=none |
1579 | Run the program directly, without a user shell. | 1584 | Run the program directly, without a user shell. |
@@ -1665,7 +1670,7 @@ parent is shutting down, bye... | |||
1665 | .TP | 1670 | .TP |
1666 | \fB\-\-tracelog | 1671 | \fB\-\-tracelog |
1667 | This option enables auditing blacklisted files and directories. A message | 1672 | This option enables auditing blacklisted files and directories. A message |
1668 | is sent to syslog in case the file or the directory is accessed. | 1673 | is sent to syslog in case the file or the directory is accessed. |
1669 | .br | 1674 | .br |
1670 | 1675 | ||
1671 | .br | 1676 | .br |
@@ -1698,13 +1703,13 @@ $ firejail \-\-tree | |||
1698 | .br | 1703 | .br |
1699 | 11903:netblue:firejail iceweasel | 1704 | 11903:netblue:firejail iceweasel |
1700 | .br | 1705 | .br |
1701 | 11904:netblue:iceweasel | 1706 | 11904:netblue:iceweasel |
1702 | .br | 1707 | .br |
1703 | 11957:netblue:/usr/lib/iceweasel/plugin-container | 1708 | 11957:netblue:/usr/lib/iceweasel/plugin-container |
1704 | .br | 1709 | .br |
1705 | 11969:netblue:firejail \-\-net=eth0 transmission-gtk | 1710 | 11969:netblue:firejail \-\-net=eth0 transmission-gtk |
1706 | .br | 1711 | .br |
1707 | 11970:netblue:transmission-gtk | 1712 | 11970:netblue:transmission-gtk |
1708 | 1713 | ||
1709 | .TP | 1714 | .TP |
1710 | \fB\-\-version | 1715 | \fB\-\-version |
@@ -1720,7 +1725,7 @@ firejail version 0.9.27 | |||
1720 | 1725 | ||
1721 | .TP | 1726 | .TP |
1722 | \fB\-\-veth-name=name | 1727 | \fB\-\-veth-name=name |
1723 | Use this name for the interface connected to the bridge for --net=bridge_interface commands, | 1728 | Use this name for the interface connected to the bridge for --net=bridge_interface commands, |
1724 | instead of the default one. | 1729 | instead of the default one. |
1725 | .br | 1730 | .br |
1726 | 1731 | ||
@@ -1733,7 +1738,7 @@ $ firejail \-\-net=br0 --veth-name=if0 | |||
1733 | \fB\-\-whitelist=dirname_or_filename | 1738 | \fB\-\-whitelist=dirname_or_filename |
1734 | Whitelist directory or file. A temporary file system is mounted on the top directory, and the | 1739 | Whitelist directory or file. A temporary file system is mounted on the top directory, and the |
1735 | whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, | 1740 | whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, |
1736 | everything else is discarded when the sandbox is closed. The top directory could be | 1741 | everything else is discarded when the sandbox is closed. The top directory could be |
1737 | user home, /dev, /media, /mnt, /opt, /srv, /var, and /tmp. | 1742 | user home, /dev, /media, /mnt, /opt, /srv, /var, and /tmp. |
1738 | .br | 1743 | .br |
1739 | 1744 | ||
@@ -1789,7 +1794,7 @@ Sandbox the application using Xpra, Xephyr, Xvfb or Xorg security extension. | |||
1789 | The sandbox will prevents screenshot and keylogger applications started inside the sandbox from accessing | 1794 | The sandbox will prevents screenshot and keylogger applications started inside the sandbox from accessing |
1790 | clients running outside the sandbox. | 1795 | clients running outside the sandbox. |
1791 | Firejail will try first Xpra, and if Xpra is not installed on the system, it will try to find Xephyr. | 1796 | Firejail will try first Xpra, and if Xpra is not installed on the system, it will try to find Xephyr. |
1792 | If all fails, Firejail will not attempt to use Xvfb or X11 security extension. | 1797 | If all fails, Firejail will not attempt to use Xvfb or X11 security extension. |
1793 | .br | 1798 | .br |
1794 | 1799 | ||
1795 | .br | 1800 | .br |
@@ -1828,7 +1833,7 @@ A security profile for OpenBox is provided. | |||
1828 | 1833 | ||
1829 | .br | 1834 | .br |
1830 | Xephyr is developed by Xorg project. On Debian platforms it is installed with the command \fBsudo apt-get install xserver-xephyr\fR. | 1835 | Xephyr is developed by Xorg project. On Debian platforms it is installed with the command \fBsudo apt-get install xserver-xephyr\fR. |
1831 | This feature is not available when running as root. | 1836 | This feature is not available when running as root. |
1832 | .br | 1837 | .br |
1833 | 1838 | ||
1834 | .br | 1839 | .br |
@@ -1838,9 +1843,9 @@ $ firejail \-\-x11=xephyr --net=eth0 openbox | |||
1838 | 1843 | ||
1839 | .TP | 1844 | .TP |
1840 | \fB\-\-x11=xorg | 1845 | \fB\-\-x11=xorg |
1841 | Sandbox the application using the untrusted mode implemented by X11 security extension. | 1846 | Sandbox the application using the untrusted mode implemented by X11 security extension. |
1842 | The extension is available in Xorg package | 1847 | The extension is available in Xorg package |
1843 | and it is installed by default on most Linux distributions. It provides support for a simple trusted/untrusted | 1848 | and it is installed by default on most Linux distributions. It provides support for a simple trusted/untrusted |
1844 | connection model. Untrusted clients are restricted in certain ways to prevent them from reading window | 1849 | connection model. Untrusted clients are restricted in certain ways to prevent them from reading window |
1845 | contents of other clients, stealing input events, etc. | 1850 | contents of other clients, stealing input events, etc. |
1846 | 1851 | ||
@@ -1875,9 +1880,9 @@ $ firejail \-\-x11=xpra --net=eth0 firefox | |||
1875 | 1880 | ||
1876 | .TP | 1881 | .TP |
1877 | \fB\-\-x11=xvfb | 1882 | \fB\-\-x11=xvfb |
1878 | Start Xvfb X11 server and attach the sandbox to this server. | 1883 | Start Xvfb X11 server and attach the sandbox to this server. |
1879 | Xvfb, short for X virtual framebuffer, performs all graphical operations in memory | 1884 | Xvfb, short for X virtual framebuffer, performs all graphical operations in memory |
1880 | without showing any screen output. Xvfb is mainly used for remote access and software | 1885 | without showing any screen output. Xvfb is mainly used for remote access and software |
1881 | testing on headless servers. | 1886 | testing on headless servers. |
1882 | .br | 1887 | .br |
1883 | 1888 | ||
@@ -1992,7 +1997,7 @@ $ firejail --tree | |||
1992 | .br | 1997 | .br |
1993 | 1190:netblue:firejail firefox | 1998 | 1190:netblue:firejail firefox |
1994 | .br | 1999 | .br |
1995 | 1220:netblue:/bin/sh -c "/usr/lib/firefox/firefox" | 2000 | 1220:netblue:/bin/sh -c "/usr/lib/firefox/firefox" |
1996 | .br | 2001 | .br |
1997 | 1221:netblue:/usr/lib/firefox/firefox | 2002 | 1221:netblue:/usr/lib/firefox/firefox |
1998 | .RE | 2003 | .RE |
@@ -2246,7 +2251,7 @@ Parent pid 8553, child pid 8554 | |||
2246 | .br | 2251 | .br |
2247 | Child process initialized | 2252 | Child process initialized |
2248 | .br | 2253 | .br |
2249 | [...] | 2254 | [...] |
2250 | .br | 2255 | .br |
2251 | 2256 | ||
2252 | .br | 2257 | .br |
@@ -2260,7 +2265,7 @@ Child process initialized | |||
2260 | .RE | 2265 | .RE |
2261 | 2266 | ||
2262 | See man 5 firejail-profile for profile file syntax information. | 2267 | See man 5 firejail-profile for profile file syntax information. |
2263 | 2268 | ||
2264 | .SH RESTRICTED SHELL | 2269 | .SH RESTRICTED SHELL |
2265 | To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in | 2270 | To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in |
2266 | /etc/passwd file for each user that needs to be restricted. Alternatively, | 2271 | /etc/passwd file for each user that needs to be restricted. Alternatively, |
@@ -2307,6 +2312,3 @@ Homepage: http://firejail.wordpress.com | |||
2307 | \&\flfirecfg\fR\|(1), | 2312 | \&\flfirecfg\fR\|(1), |
2308 | \&\flfirejail-profile\fR\|(5), | 2313 | \&\flfirejail-profile\fR\|(5), |
2309 | \&\flfirejail-login\fR\|(5) | 2314 | \&\flfirejail-login\fR\|(5) |
2310 | |||
2311 | |||
2312 | |||