Codebase list firejail / 0440153
Merge tag 'upstream/0.9.44.6' Upstream version 0.9.44.6 # gpg: Signature made Mon 16 Jan 2017 07:24:43 PM CET # gpg: using RSA key D8F6FA7DEA24D90D6EAC733BCCF04928DB0EEAA7 # gpg: issuer "reiner@reiner-h.de" # gpg: Good signature from "Reiner Herrmann <reiner@reiner-h.de>" [ultimate] # Primary key fingerprint: 2F5D AF3F C1F7 93D9 4F3D 900C A721 DA05 5374 AA4F # Subkey fingerprint: D8F6 FA7D EA24 D90D 6EAC 733B CCF0 4928 DB0E EAA7 Reiner Herrmann 7 years ago
25 changed file(s) with 334 addition(s) and 188 deletion(s). Raw diff Collapse all Expand all
7676 - added gnome-chess profile
7777 - added DOSBox profile
7878 - evince profile enhancement
79 Mike Frysinger (vapier@gentoo.org)
80 - Gentoo compile patch
7981 valoq (https://github.com/valoq)
8082 - LibreOffice profile fixes
8183 - cherrytree profile fixes
0 firejail (0.9.44.6) baseline; urgency=low
1 * security: new fix for CVE-2017-5180 reported by Sebastian Krahmer last week
2 * security: major cleanup of file copying code
3 * security: tightening the rules for --chroot and --overlay features
4 * bugfix: ported Gentoo compile patch
5 * bugfix: Nvidia drivers bug in --private-dev
6 * bugfix: fix ASSERT_PERMS_FD macro
7 * feature: allow local customization using .local files under /etc/firejail
8 backported from our development branch
9 * feature: spoof machine-id backported from our development branch
10 -- netblue30 <netblue30@yahoo.com> Sun, 15 Jan 2017 10:00:00 -0500
11
012 firejail (0.9.44.4) baseline; urgency=low
1 * security: --bandwidth root shell found by Martin Carpenter
13 * security: --bandwidth root shell found by Martin Carpenter (CVE-2017-5207)
214 * security: disabled --allow-debuggers when running on kernel
315 versions prior to 4.8; a kernel bug in ptrace system call
416 allows a full bypass of seccomp filter; problem reported by Lizzie Dixon
17 (CVE-2017-5206)
518 * security: root exploit found by Sebastian Krahmer (CVE-2017-5180)
619 -- netblue30 <netblue30@yahoo.com> Sat, 7 Jan 2017 10:00:00 -0500
720
00 #! /bin/sh
11 # Guess values for system-dependent variables and create Makefiles.
2 # Generated by GNU Autoconf 2.69 for firejail 0.9.44.4.
2 # Generated by GNU Autoconf 2.69 for firejail 0.9.44.6.
33 #
44 # Report bugs to <netblue30@yahoo.com>.
55 #
579579 # Identity of this package.
580580 PACKAGE_NAME='firejail'
581581 PACKAGE_TARNAME='firejail'
582 PACKAGE_VERSION='0.9.44.4'
583 PACKAGE_STRING='firejail 0.9.44.4'
582 PACKAGE_VERSION='0.9.44.6'
583 PACKAGE_STRING='firejail 0.9.44.6'
584584 PACKAGE_BUGREPORT='netblue30@yahoo.com'
585585 PACKAGE_URL='http://firejail.wordpress.com'
586586
12581258 # Omit some internal or obsolete options to make the list less imposing.
12591259 # This message is too long to be a string in the A/UX 3.1 sh.
12601260 cat <<_ACEOF
1261 \`configure' configures firejail 0.9.44.4 to adapt to many kinds of systems.
1261 \`configure' configures firejail 0.9.44.6 to adapt to many kinds of systems.
12621262
12631263 Usage: $0 [OPTION]... [VAR=VALUE]...
12641264
13191319
13201320 if test -n "$ac_init_help"; then
13211321 case $ac_init_help in
1322 short | recursive ) echo "Configuration of firejail 0.9.44.4:";;
1322 short | recursive ) echo "Configuration of firejail 0.9.44.6:";;
13231323 esac
13241324 cat <<\_ACEOF
13251325
14231423 test -n "$ac_init_help" && exit $ac_status
14241424 if $ac_init_version; then
14251425 cat <<\_ACEOF
1426 firejail configure 0.9.44.4
1426 firejail configure 0.9.44.6
14271427 generated by GNU Autoconf 2.69
14281428
14291429 Copyright (C) 2012 Free Software Foundation, Inc.
17251725 This file contains any messages produced by compilers while
17261726 running configure, to aid debugging if configure makes a mistake.
17271727
1728 It was created by firejail $as_me 0.9.44.4, which was
1728 It was created by firejail $as_me 0.9.44.6, which was
17291729 generated by GNU Autoconf 2.69. Invocation command line was
17301730
17311731 $ $0 $@
43024302 # report actual input values of CONFIG_FILES etc. instead of their
43034303 # values after options handling.
43044304 ac_log="
4305 This file was extended by firejail $as_me 0.9.44.4, which was
4305 This file was extended by firejail $as_me 0.9.44.6, which was
43064306 generated by GNU Autoconf 2.69. Invocation command line was
43074307
43084308 CONFIG_FILES = $CONFIG_FILES
43564356 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
43574357 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
43584358 ac_cs_version="\\
4359 firejail config.status 0.9.44.4
4359 firejail config.status 0.9.44.6
43604360 configured by $0, generated by GNU Autoconf 2.69,
43614361 with options \\"\$ac_cs_config\\"
43624362
00 AC_PREREQ([2.68])
1 AC_INIT(firejail, 0.9.44.4, netblue30@yahoo.com, , http://firejail.wordpress.com)
1 AC_INIT(firejail, 0.9.44.6, netblue30@yahoo.com, , http://firejail.wordpress.com)
22 AC_CONFIG_SRCDIR([src/firejail/main.c])
33 #AC_CONFIG_HEADERS([config.h])
44
0 # Local customizations come here
1 include /etc/firejail/disable-common.local
2
03 # History files in $HOME
14 blacklist-nolog ${HOME}/.history
25 blacklist-nolog ${HOME}/.*_history
0 # Local customizations come here
1 include /etc/firejail/disable-devel.local
2
03 # development tools
14
25 # GCC
0 # Local customizations come here
1 include /etc/firejail/disable-passwdmgr.local
2
03 blacklist ${HOME}/.pki/nssdb
14 blacklist ${HOME}/.lastpass
25 blacklist ${HOME}/.keepassx
0 # Local customizations come here
1 include /etc/firejail/disable-programs.local
2
03 # various programs
14 blacklist ${HOME}/.Atom
25 blacklist ${HOME}/.remmina
0 # Local customizations come here
1 include /etc/firejail/whitelist-common.local
2
03 # common whitelist for all profiles
14
25 whitelist ~/.XCompose
00 #!/bin/bash
1 VERSION="0.9.44.4"
1 VERSION="0.9.44.6"
22 rm -fr ~/rpmbuild
33 rm -f firejail-$VERSION-1.x86_64.rpm
44
457457 chmod u+s /usr/bin/firejail
458458
459459 %changelog
460 * Sun Jan 15 2017 netblue30 <netblue30@yahoo.com> 0.9.44.6-1
461 - security release
462
460463 * Sat Jan 7 2017 netblue30 <netblue30@yahoo.com> 0.9.44.4-1
461464 - security release
462465
6767 #define RUN_HOSTNAME_FILE "/run/firejail/mnt/hostname"
6868 #define RUN_HOSTS_FILE "/run/firejail/mnt/hosts"
6969 #define RUN_RESOLVCONF_FILE "/run/firejail/mnt/resolv.conf"
70 #define RUN_MACHINEID "/run/firejail/mnt/machine-id"
7071 #define RUN_LDPRELOAD_FILE "/run/firejail/mnt/ld.so.preload"
7172 #define RUN_UTMP_FILE "/run/firejail/mnt/utmp"
7273 #define RUN_PASSWD_FILE "/run/firejail/mnt/passwd"
9192 #define ASSERT_PERMS_FD(fd, uid, gid, mode) \
9293 do { \
9394 struct stat s;\
94 if (stat(fd, &s) == -1) errExit("stat");\
95 if (fstat(fd, &s) == -1) errExit("stat");\
9596 assert(s.st_uid == uid);\
9697 assert(s.st_gid == gid);\
9798 assert((s.st_mode & 07777) == (mode));\
326327 extern int arg_x11_block; // block X11
327328 extern int arg_x11_xorg; // use X11 security extention
328329 extern int arg_allusers; // all user home directories visible
330 extern int arg_machineid; // preserve /etc/machine-id
329331
330332 extern int login_shell;
331333 extern int parent_to_child_fds[2];
390392 void fs_overlayfs(void);
391393 // chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf
392394 void fs_chroot(const char *rootdir);
393 int fs_check_chroot_dir(const char *rootdir);
395 void fs_check_chroot_dir(const char *rootdir);
394396 void fs_private_tmp(void);
395397
396398 // profile.c
445447 void logargs(int argc, char **argv) ;
446448 void logerr(const char *msg);
447449 int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode);
450 void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode);
451 void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode);
448452 int is_dir(const char *fname);
449453 int is_link(const char *fname);
450454 char *line_remove_spaces(const char *buf);
564568 // fs_etc.c
565569 void fs_check_etc_list(void);
566570 void fs_private_etc_list(void);
571 void fs_machineid(void);
567572
568573 // no_sandbox.c
569574 int check_namespace_virt(void);
2525 #include <dirent.h>
2626 #include <fcntl.h>
2727 #include <errno.h>
28 #include <sys/wait.h>
29
2830
2931 static void fs_rdwr(const char *dir);
3032
161163 fprintf(stderr, "Error: invalid /bin/cp file\n");
162164 exit(1);
163165 }
164 int rv = copy_file(fname, RUN_CP_COMMAND, 0, 0, 0755);
166 int rv = copy_file(fname, RUN_CP_COMMAND, 0, 0, 0755); // root needed
165167 if (rv) {
166168 fprintf(stderr, "Error: cannot access /bin/cp\n");
167169 exit(1);
775777 fs_var_lib();
776778 fs_var_cache();
777779 fs_var_utmp();
778
780 fs_machineid();
781
779782 // don't leak user information
780783 restrict_users();
781784
796799 // create ~/.firejail directory
797800 if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1)
798801 errExit("asprintf");
802
803 if (is_link(dirname)) {
804 fprintf(stderr, "Error: invalid ~/.firejail directory\n");
805 exit(1);
806 }
799807 if (stat(dirname, &s) == -1) {
800 /* coverity[toctou] */
801 if (mkdir(dirname, 0700))
802 errExit("mkdir");
803 if (chmod(dirname, 0700) == -1)
804 errExit("chmod");
805 ASSERT_PERMS(dirname, getuid(), getgid(), 0700);
806 }
807 else if (is_link(dirname)) {
808 // create directory
809 pid_t child = fork();
810 if (child < 0)
811 errExit("fork");
812 if (child == 0) {
813 // drop privileges
814 drop_privs(0);
815
816 // create directory
817 if (mkdir(dirname, 0700))
818 errExit("mkdir");
819 if (chmod(dirname, 0700) == -1)
820 errExit("chmod");
821 ASSERT_PERMS(dirname, getuid(), getgid(), 0700);
822 _exit(0);
823 }
824 // wait for the child to finish
825 waitpid(child, NULL, 0);
826 if (stat(dirname, &s) == -1) {
827 fprintf(stderr, "Error: cannot create ~/.firejail directory\n");
828 exit(1);
829 }
830 }
831 else if (s.st_uid != getuid()) {
808832 fprintf(stderr, "Error: invalid ~/.firejail directory\n");
809833 exit(1);
810834 }
10821106 fs_var_lib();
10831107 fs_var_cache();
10841108 fs_var_utmp();
1109 fs_machineid();
10851110
10861111 // don't leak user information
10871112 restrict_users();
11011126
11021127
11031128 #ifdef HAVE_CHROOT
1104 // return 1 if error
1105 int fs_check_chroot_dir(const char *rootdir) {
1129 void fs_check_chroot_dir(const char *rootdir) {
11061130 EUID_ASSERT();
11071131 assert(rootdir);
11081132 struct stat s;
11091133 char *name;
11101134
1135 if (strcmp(rootdir, "/tmp") == 0 || strcmp(rootdir, "/var/tmp") == 0) {
1136 fprintf(stderr, "Error: invalid chroot directory\n");
1137 exit(1);
1138 }
1139
11111140 // rootdir has to be owned by root
11121141 if (stat(rootdir, &s) != 0) {
11131142 fprintf(stderr, "Error: cannot find chroot directory\n");
1114 return 1;
1143 exit(1);
11151144 }
11161145 if (s.st_uid != 0) {
11171146 fprintf(stderr, "Error: chroot directory should be owned by root\n");
1118 return 1;
1147 exit(1);
11191148 }
11201149
11211150 // check /dev
11231152 errExit("asprintf");
11241153 if (stat(name, &s) == -1) {
11251154 fprintf(stderr, "Error: cannot find /dev in chroot directory\n");
1126 return 1;
1155 exit(1);
1156 }
1157 if (s.st_uid != 0) {
1158 fprintf(stderr, "Error: chroot /dev directory should be owned by root\n");
1159 exit(1);
11271160 }
11281161 free(name);
11291162
11321165 errExit("asprintf");
11331166 if (stat(name, &s) == -1) {
11341167 fprintf(stderr, "Error: cannot find /var/tmp in chroot directory\n");
1135 return 1;
1168 exit(1);
1169 }
1170 if (s.st_uid != 0) {
1171 fprintf(stderr, "Error: chroot /var/tmp directory should be owned by root\n");
1172 exit(1);
11361173 }
11371174 free(name);
11381175
11411178 errExit("asprintf");
11421179 if (stat(name, &s) == -1) {
11431180 fprintf(stderr, "Error: cannot find /proc in chroot directory\n");
1144 return 1;
1181 exit(1);
1182 }
1183 if (s.st_uid != 0) {
1184 fprintf(stderr, "Error: chroot /proc directory should be owned by root\n");
1185 exit(1);
11451186 }
11461187 free(name);
11471188
11501191 errExit("asprintf");
11511192 if (stat(name, &s) == -1) {
11521193 fprintf(stderr, "Error: cannot find /tmp in chroot directory\n");
1153 return 1;
1194 exit(1);
1195 }
1196 if (s.st_uid != 0) {
1197 fprintf(stderr, "Error: chroot /tmp directory should be owned by root\n");
1198 exit(1);
11541199 }
11551200 free(name);
11561201
1157 // check /bin/bash
1158 // if (asprintf(&name, "%s/bin/bash", rootdir) == -1)
1159 // errExit("asprintf");
1160 // if (stat(name, &s) == -1) {
1161 // fprintf(stderr, "Error: cannot find /bin/bash in chroot directory\n");
1162 // return 1;
1163 // }
1164 // free(name);
1202 // check /etc
1203 if (asprintf(&name, "%s/etc", rootdir) == -1)
1204 errExit("asprintf");
1205 if (stat(name, &s) == -1) {
1206 fprintf(stderr, "Error: cannot find /etc in chroot directory\n");
1207 exit(1);
1208 }
1209 if (s.st_uid != 0) {
1210 fprintf(stderr, "Error: chroot /etc directory should be owned by root\n");
1211 exit(1);
1212 }
1213 free(name);
1214
1215 // check /etc/resolv.conf
1216 if (asprintf(&name, "%s/etc/resolv.conf", rootdir) == -1)
1217 errExit("asprintf");
1218 if (stat(name, &s) == 0) {
1219 if (s.st_uid != 0) {
1220 fprintf(stderr, "Error: chroot /etc/resolv.conf should be owned by root\n");
1221 exit(1);
1222 }
1223 }
1224 if (is_link(name)) {
1225 fprintf(stderr, "Error: invalid %s file\n", name);
1226 exit(1);
1227 }
1228 free(name);
11651229
11661230 // check x11 socket directory
11671231 if (getenv("FIREJAIL_X11")) {
11711235 errExit("asprintf");
11721236 if (stat(name, &s) == -1) {
11731237 fprintf(stderr, "Error: cannot find /tmp/.X11-unix in chroot directory\n");
1174 return 1;
1238 exit(1);
1239 }
1240 if (s.st_uid != 0) {
1241 fprintf(stderr, "Error: chroot /tmp/.X11-unix directory should be owned by root\n");
1242 exit(1);
11751243 }
11761244 free(name);
11771245 }
1178
1179 return 0;
11801246 }
11811247
11821248 // chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf
12131279 char *rundir;
12141280 if (asprintf(&rundir, "%s/run", rootdir) == -1)
12151281 errExit("asprintf");
1282 if (is_link(rundir)) {
1283 fprintf(stderr, "Error: invalid run directory inside chroot\n");
1284 exit(1);
1285 }
12161286 if (!is_dir(rundir)) {
12171287 int rv = mkdir(rundir, 0755);
12181288 (void) rv;
12321302 fprintf(stderr, "Error: invalid %s file\n", fname);
12331303 exit(1);
12341304 }
1235 if (copy_file("/etc/resolv.conf", fname, 0, 0, 0644) == -1)
1305 if (copy_file("/etc/resolv.conf", fname, 0, 0, 0644) == -1) // root needed
12361306 fprintf(stderr, "Warning: /etc/resolv.conf not initialized\n");
12371307 }
12381308
12541324 fs_var_lib();
12551325 fs_var_cache();
12561326 fs_var_utmp();
1327 fs_machineid();
12571328
12581329 // don't leak user information
12591330 restrict_users();
2727 #ifndef _BSD_SOURCE
2828 #define _BSD_SOURCE
2929 #endif
30 #include <sys/sysmacros.h>
3031 #include <sys/types.h>
3132
3233 typedef struct {
5051 {"/dev/nvidia8", RUN_DEV_DIR "/nvidia8", 0, 1},
5152 {"/dev/nvidia9", RUN_DEV_DIR "/nvidia9", 0, 1},
5253 {"/dev/nvidiactl", RUN_DEV_DIR "/nvidiactl", 0, 1},
53 {"/dev/nvidia-modset", RUN_DEV_DIR "/nvidia-modset", 0, 1},
54 {"/dev/nvidia-modeset", RUN_DEV_DIR "/nvidia-modeset", 0, 1},
5455 {"/dev/nvidia-uvm", RUN_DEV_DIR "/nvidia-uvm", 0, 1},
5556 {NULL, NULL, 0, 0}
5657 };
2222 #include <sys/types.h>
2323 #include <sys/wait.h>
2424 #include <unistd.h>
25 #include <time.h>
26
27 // spoof /etc/machine_id
28 void fs_machineid(void) {
29 union machineid_t {
30 uint8_t u8[16];
31 uint32_t u32[4];
32 } mid;
33
34 // if --machine-id flag is active, do nothing
35 if (arg_machineid)
36 return;
37
38 // init random number generator
39 srand(time(NULL));
40
41 // generate random id
42 mid.u32[0] = rand();
43 mid.u32[1] = rand();
44 mid.u32[2] = rand();
45 mid.u32[3] = rand();
46
47 // UUID version 4 and DCE variant
48 mid.u8[6] = (mid.u8[6] & 0x0F) | 0x40;
49 mid.u8[8] = (mid.u8[8] & 0x3F) | 0x80;
50
51 // write it in a file
52 FILE *fp = fopen(RUN_MACHINEID, "w");
53 if (!fp)
54 errExit("fopen");
55 fprintf(fp, "%08x%08x%08x%08x\n", mid.u32[0], mid.u32[1], mid.u32[2], mid.u32[3]);
56 fclose(fp);
57 if (set_perms(RUN_MACHINEID, 0, 0, 0444))
58 errExit("set_perms");
59
60
61 struct stat s;
62 if (stat("/etc/machine-id", &s) == 0) {
63 if (arg_debug)
64 printf("installing a new /etc/machine-id\n");
65
66 if (mount(RUN_MACHINEID, "/etc/machine-id", "none", MS_BIND, "mode=444,gid=0"))
67 errExit("mount");
68 }
69 if (stat("/var/lib/dbus/machine-id", &s) == 0) {
70 if (mount(RUN_MACHINEID, "/var/lib/dbus/machine-id", "none", MS_BIND, "mode=444,gid=0"))
71 errExit("mount");
72 }
73 }
2574
2675 // return 0 if file not found, 1 if found
2776 static int check_dir_or_file(const char *name) {
4141 // don't copy it if we already have the file
4242 if (stat(fname, &s) == 0)
4343 return;
44 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat
45 fprintf(stderr, "Error: invalid %s file\n", fname);
46 exit(1);
47 }
4448 if (stat("/etc/skel/.zshrc", &s) == 0) {
45 if (copy_file("/etc/skel/.zshrc", fname, u, g, 0644) == 0) {
46 fs_logger("clone /etc/skel/.zshrc");
47 }
48 }
49 else { //
50 FILE *fp = fopen(fname, "w");
51 if (fp) {
52 fprintf(fp, "\n");
53 SET_PERMS_STREAM(fp, u, g, S_IRUSR | S_IWUSR);
54 fclose(fp);
55 fs_logger2("touch", fname);
56 }
49 copy_file_as_user("/etc/skel/.zshrc", fname, u, g, 0644); // regular user
50 fs_logger("clone /etc/skel/.zshrc");
51 }
52 else {
53 touch_file_as_user(fname, u, g, 0644);
54 fs_logger2("touch", fname);
5755 }
5856 free(fname);
5957 }
6664 // don't copy it if we already have the file
6765 if (stat(fname, &s) == 0)
6866 return;
67 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat
68 fprintf(stderr, "Error: invalid %s file\n", fname);
69 exit(1);
70 }
6971 if (stat("/etc/skel/.cshrc", &s) == 0) {
70 if (copy_file("/etc/skel/.cshrc", fname, u, g, 0644) == 0) {
71 fs_logger("clone /etc/skel/.cshrc");
72 }
73 }
74 else { //
75 /* coverity[toctou] */
76 FILE *fp = fopen(fname, "w");
77 if (fp) {
78 fprintf(fp, "\n");
79 SET_PERMS_STREAM(fp, u, g, S_IRUSR | S_IWUSR);
80 fclose(fp);
81 fs_logger2("touch", fname);
82 }
72 copy_file_as_user("/etc/skel/.cshrc", fname, u, g, 0644); // regular user
73 fs_logger("clone /etc/skel/.cshrc");
74 }
75 else {
76 touch_file_as_user(fname, u, g, 0644);
77 fs_logger2("touch", fname);
8378 }
8479 free(fname);
8580 }
9287 // don't copy it if we already have the file
9388 if (stat(fname, &s) == 0)
9489 return;
90 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat
91 fprintf(stderr, "Error: invalid %s file\n", fname);
92 exit(1);
93 }
9594 if (stat("/etc/skel/.bashrc", &s) == 0) {
96 if (copy_file("/etc/skel/.bashrc", fname, u, g, 0644) == 0) {
97 fs_logger("clone /etc/skel/.bashrc");
98 }
95 copy_file_as_user("/etc/skel/.bashrc", fname, u, g, 0644); // regular user
96 fs_logger("clone /etc/skel/.bashrc");
9997 }
10098 free(fname);
10199 }
107105
108106 char *src;
109107 char *dest = RUN_XAUTHORITY_FILE;
110 // create an empty file
108 // create an empty file as root, and change ownership to user
111109 FILE *fp = fopen(dest, "w");
112110 if (fp) {
113111 fprintf(fp, "\n");
125123 return 0;
126124 }
127125
128 pid_t child = fork();
129 if (child < 0)
130 errExit("fork");
131 if (child == 0) {
132 // drop privileges
133 drop_privs(0);
134
135 // copy, set permissions and ownership
136 int rv = copy_file(src, dest, getuid(), getgid(), 0600);
137 if (rv)
138 fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n");
139 else {
140 fs_logger2("clone", dest);
141 }
142 _exit(0);
143 }
144 // wait for the child to finish
145 waitpid(child, NULL, 0);
126 copy_file_as_user(src, dest, getuid(), getgid(), 0600); // regular user
127 fs_logger2("clone", dest);
146128 return 1; // file copied
147129 }
148130
155137
156138 char *src;
157139 char *dest = RUN_ASOUNDRC_FILE;
158 // create an empty file
140 // create an empty file as root, and change ownership to user
159141 FILE *fp = fopen(dest, "w");
160142 if (fp) {
161143 fprintf(fp, "\n");
183165 free(rp);
184166 }
185167
186 pid_t child = fork();
187 if (child < 0)
188 errExit("fork");
189 if (child == 0) {
190 // drop privileges
191 drop_privs(0);
192
193 // copy, set permissions and ownership
194 int rv = copy_file(src, dest, getuid(), getgid(), 0644);
195 if (rv)
196 fprintf(stderr, "Warning: cannot transfer .asoundrc in private home directory\n");
197 else {
198 fs_logger2("clone", dest);
199 }
200 _exit(0);
201 }
202 // wait for the child to finish
203 waitpid(child, NULL, 0);
168 copy_file_as_user(src, dest, getuid(), getgid(), 0644); // regular user
169 fs_logger2("clone", dest);
204170 return 1; // file copied
205171 }
206172
220186 exit(1);
221187 }
222188
223 pid_t child = fork();
224 if (child < 0)
225 errExit("fork");
226 if (child == 0) {
227 // drop privileges
228 drop_privs(0);
229
230 // copy, set permissions and ownership
231 int rv = copy_file(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR);
232 if (rv)
233 fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n");
234 else {
235 fs_logger2("clone", dest);
236 }
237 _exit(0);
238 }
239 // wait for the child to finish
240 waitpid(child, NULL, 0);
189 copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); // regular user
190 fs_logger2("clone", dest);
241191
242192 // delete the temporary file
243193 unlink(src);
256206 exit(1);
257207 }
258208
259 pid_t child = fork();
260 if (child < 0)
261 errExit("fork");
262 if (child == 0) {
263 // drop privileges
264 drop_privs(0);
265
266 // copy, set permissions and ownership
267 int rv = copy_file(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR);
268 if (rv)
269 fprintf(stderr, "Warning: cannot transfer .asoundrc in private home directory\n");
270 else {
271 fs_logger2("clone", dest);
272 }
273 _exit(0);
274 }
275 // wait for the child to finish
276 waitpid(child, NULL, 0);
209 copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); // regular user
210 fs_logger2("clone", dest);
277211
278212 // delete the temporary file
279213 unlink(src);
478412 size_cnt += s.st_size;
479413
480414 if(ftype == FTW_F)
481 copy_file(path, dest, firejail_uid, firejail_gid, s.st_mode);
415 copy_file(path, dest, firejail_uid, firejail_gid, s.st_mode); // already a regular user
482416 else if (ftype == FTW_D) {
483417 if (mkdir(dest, s.st_mode) == -1)
484418 errExit("mkdir");
107107 }
108108
109109 // create file
110 pid_t child = fork();
111 if (child < 0)
112 errExit("fork");
113 if (child == 0) {
114 // drop privileges
115 drop_privs(0);
116
117 FILE *fp = fopen(expanded, "w");
118 if (!fp)
119 fprintf(stderr, "Warning: cannot create %s file\n", expanded);
120 else {
121 int fd = fileno(fp);
122 if (fd == -1)
123 errExit("fileno");
124 int rv = fchmod(fd, 0600);
125 (void) rv;
126 fclose(fp);
127 }
128 _exit(0);
129 }
130 // wait for the child to finish
131 waitpid(child, NULL, 0);
110 touch_file_as_user(expanded, getuid(), getgid(), 0600);
132111
133112 doexit:
134113 free(expanded);
355355 drop_privs(0);
356356
357357 // copy the file
358 if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600))
358 if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600)) // already a regular user
359359 _exit(1);
360360 _exit(0);
361361 }
378378 drop_privs(0);
379379
380380 // copy the file
381 if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600))
381 if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600)) // aleady a regular user
382382 _exit(1);
383383 _exit(0);
384384 }
421421 drop_privs(0);
422422
423423 // copy the file
424 if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600))
424 if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600)) // already regular user
425425 _exit(1);
426426 _exit(0);
427427 }
450450 drop_privs(0);
451451
452452 // copy the file
453 if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600))
453 if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600)) // already a regular user
454454 _exit(1);
455455 _exit(0);
456456 }
109109 int arg_x11_block = 0; // block X11
110110 int arg_x11_xorg = 0; // use X11 security extention
111111 int arg_allusers = 0; // all user home directories visible
112 int arg_machineid = 0; // preserve /etc/machine-id
112113
113114 int login_shell = 0;
114115
16291630 fprintf(stderr, "Error: invalid chroot directory\n");
16301631 exit(1);
16311632 }
1632 free(rpath);
1633 cfg.chrootdir = rpath;
16331634
16341635 // check chroot directory structure
1635 if (fs_check_chroot_dir(cfg.chrootdir)) {
1636 fprintf(stderr, "Error: invalid chroot\n");
1637 exit(1);
1638 }
1636 fs_check_chroot_dir(cfg.chrootdir);
16391637 }
16401638 else {
16411639 fprintf(stderr, "Error: --chroot feature is disabled in Firejail configuration file\n");
16521650 }
16531651 else if (strcmp(argv[i], "--writable-var") == 0) {
16541652 arg_writable_var = 1;
1653 }
1654 else if (strcmp(argv[i], "--machine-id") == 0) {
1655 arg_machineid = 1;
16551656 }
16561657 else if (strcmp(argv[i], "--private") == 0) {
16571658 arg_private = 1;
641641 return 0;
642642 }
643643
644 if (strcmp(ptr, "machine-id") == 0) {
645 arg_machineid = 1;
646 return 0;
647 }
644648 // writable-var
645649 if (strcmp(ptr, "writable-var") == 0) {
646650 arg_writable_var = 1;
965969 // open profile file:
966970 FILE *fp = fopen(fname, "r");
967971 if (fp == NULL) {
972 // if the file ends in ".local", do not exit
973 char *ptr = strstr(fname, ".local");
974 if (ptr && strlen(ptr) == 6)
975 return;
976
968977 fprintf(stderr, "Error: cannot open profile file %s\n", fname);
969978 exit(1);
970979 }
116116 char *pulsecfg = NULL;
117117 if (asprintf(&pulsecfg, "%s/client.conf", RUN_PULSE_DIR) == -1)
118118 errExit("asprintf");
119 if (copy_file("/etc/pulse/client.conf", pulsecfg, -1, -1, 0644))
119 if (copy_file("/etc/pulse/client.conf", pulsecfg, -1, -1, 0644)) // root needed
120120 errExit("copy_file");
121121 FILE *fp = fopen(pulsecfg, "a+");
122122 if (!fp)
121121 printf(" --ls=name|pid dir_or_filename - list files in sandbox container.\n\n");
122122 #ifdef HAVE_NETWORK
123123 printf(" --mac=xx:xx:xx:xx:xx:xx - set interface MAC address.\n\n");
124 #endif
125 printf(" --machine-id - preserve /etc/machine-id\n");
126 #ifdef HAVE_NETWORK
124127 printf(" --mtu=number - set interface MTU.\n\n");
125128 #endif
126129 printf(" --name=name - set sandbox name.\n\n");
2727 #include <grp.h>
2828 #include <sys/ioctl.h>
2929 #include <termios.h>
30 #include <sys/wait.h>
3031
3132 #define MAX_GROUPS 1024
3233 // drop privileges
218219 return 0;
219220 }
220221
222 // return -1 if error, 0 if no error
223 void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) {
224 pid_t child = fork();
225 if (child < 0)
226 errExit("fork");
227 if (child == 0) {
228 // drop privileges
229 drop_privs(0);
230
231 // copy, set permissions and ownership
232 int rv = copy_file(srcname, destname, uid, gid, mode); // already a regular user
233 if (rv)
234 fprintf(stderr, "Warning: cannot copy %s\n", srcname);
235 _exit(0);
236 }
237 // wait for the child to finish
238 waitpid(child, NULL, 0);
239 }
240
241 // return -1 if error, 0 if no error
242 void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode) {
243 pid_t child = fork();
244 if (child < 0)
245 errExit("fork");
246 if (child == 0) {
247 // drop privileges
248 drop_privs(0);
249
250 FILE *fp = fopen(fname, "w");
251 if (fp) {
252 fprintf(fp, "\n");
253 SET_PERMS_STREAM(fp, uid, gid, mode);
254 fclose(fp);
255 }
256 _exit(0);
257 }
258 // wait for the child to finish
259 waitpid(child, NULL, 0);
260 }
221261
222262 // return 1 if the file is a directory
223263 int is_dir(const char *fname) {
650650 struct stat s;
651651 if (stat(dest, &s) == -1) {
652652 // create an .Xauthority file
653 FILE *fp = fopen(dest, "w");
654 if (!fp)
655 errExit("fopen");
656 SET_PERMS_STREAM(fp, getuid(), getgid(), 0600);
657 fclose(fp);
653 touch_file_as_user(dest, getuid(), getgid(), 0600);
658654 }
659655
660656 // check xauth utility is present in the system
662658 fprintf(stderr, "Error: cannot find /usr/bin/xauth executable\n");
663659 exit(1);
664660 }
661
662 // temporarily mount a tempfs on top of /tmp directory
663 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
664 errExit("mounting /tmp");
665665
666666 // create a temporary .Xauthority file
667667 char tmpfname[] = "/tmp/.tmpXauth-XXXXXX";
670670 fprintf(stderr, "Error: cannot create .Xauthority file\n");
671671 exit(1);
672672 }
673 if (fchown(fd, getuid(), getgid()) == -1)
674 errExit("chown");
673675 close(fd);
674 if (chown(tmpfname, getuid(), getgid()) == -1)
675 errExit("chown");
676676
677677 pid_t child = fork();
678678 if (child < 0)
709709
710710 // move the temporary file in RUN_XAUTHORITY_SEC_FILE in order to have it deleted
711711 // automatically when the sandbox is closed
712 if (copy_file(tmpfname, RUN_XAUTHORITY_SEC_FILE, getuid(), getgid(), 0600)) {
712 if (copy_file(tmpfname, RUN_XAUTHORITY_SEC_FILE, getuid(), getgid(), 0600)) { // root needed
713713 fprintf(stderr, "asdfdsfError: cannot create the new .Xauthority file\n");
714714 exit(1);
715715 }
729729 if (chmod(dest, 0600) == -1)
730730 errExit("chmod");
731731 free(dest);
732
733 // unmount /tmp
734 umount("/tmp");
732735 #endif
733736 }
8484 file in user home directory.
8585
8686 Example: "include ${HOME}/myprofiles/profile1" will load "~/myprofiles/profile1" file.
87
88 If the file is not found, and the file name does not end in ".local", the sandbox exist immediately
89 with an error printed on stderr. ".local" files can be used to customize the global configuration
90 in /etc/firejail directory. These files are not overwritten during software install.
8791
8892 .TP
8993 \fBnoblacklist file_name
434438 .TP
435439 \fBmac address
436440 Assign MAC addresses to the last network interface defined by a net command.
441
442 .TP
443 \fBmachine-id
444 Preserve id number in /etc/machine-id file. By default a new random id is generated inside the sandbox.
437445
438446 .TP
439447 \fBmtu number
667667 $ firejail \-\-net=eth0 \-\-mac=00:11:22:33:44:55 firefox
668668
669669 .TP
670 \fB\-\-machine-id
671 Preserve id number in /etc/machine-id file. By default a new random id is generated inside the sandbox.
672 .br
673
674 .br
675 Example:
676 .br
677 $ firejail \-\-machine-id
678
679 .TP
670680 \fB\-\-mtu=number
671681 Assign a MTU value to the last network interface defined by a \-\-net option.
672682 .br