// private mode (--private): // mount tmpfs over /home/user, // tmpfs on top of /root in nonroot mode, // set skel files, // restore .Xauthority void fs_private(void) { char *homedir = cfg.homedir; assert(homedir); uid_t u = getuid(); gid_t g = getgid(); int xflag = store_xauthority(); // mask /home if (arg_debug) printf("Mounting a new /home directory\n"); if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) errExit("mounting home directory"); // mask /root if (arg_debug) printf("Mounting a new /root directory\n"); if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0) errExit("mounting home directory"); if (u != 0) { // create /home/user if (arg_debug) printf("Create a new user directory\n"); int rv = mkdir(homedir, S_IRWXU); if (rv == -1) errExit("mkdir"); if (chown(homedir, u, g) < 0) errExit("chown"); } skel(homedir, u, g); if (xflag) copy_xauthority(); }
// private mode (--private-home=list): // mount homedir on top of /home/user, // tmpfs on top of /root in nonroot mode, // tmpfs on top of /tmp in root mode, // set skel files, // restore .Xauthority void fs_private_home_list(void) { char *homedir = cfg.homedir; char *private_list = cfg.home_private_keep; assert(homedir); assert(private_list); int xflag = store_xauthority(); int aflag = store_asoundrc(); uid_t uid = getuid(); gid_t gid = getgid(); // create /run/firejail/mnt/home directory mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); fs_logger_print(); // save the current log if (arg_debug) printf("Copying files in the new home:\n"); // copy the list of files in the new home directory char *dlist = strdup(cfg.home_private_keep); if (!dlist) errExit("strdup"); char *ptr = strtok(dlist, ","); duplicate(ptr); while ((ptr = strtok(NULL, ",")) != NULL) duplicate(ptr); fs_logger_print(); // save the current log free(dlist); if (arg_debug) printf("Mount-bind %s on top of %s\n", RUN_HOME_DIR, homedir); if (mount(RUN_HOME_DIR, homedir, NULL, MS_BIND|MS_REC, NULL) < 0) errExit("mount bind"); if (uid != 0) { // mask /root if (arg_debug) printf("Mounting a new /root directory\n"); if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0) errExit("mounting home directory"); } else { // mask /home if (arg_debug) printf("Mounting a new /home directory\n"); if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) errExit("mounting home directory"); } skel(homedir, uid, gid); if (xflag) copy_xauthority(); if (aflag) copy_asoundrc(); }
// private mode (--private=homedir): // mount homedir on top of /home/user, // tmpfs on top of /root in nonroot mode, // set skel files, // restore .Xauthority void fs_private_homedir(void) { char *homedir = cfg.homedir; char *private_homedir = cfg.home_private; assert(homedir); assert(private_homedir); int xflag = store_xauthority(); int aflag = store_asoundrc(); uid_t u = getuid(); gid_t g = getgid(); struct stat s; if (stat(homedir, &s) == -1) { fprintf(stderr, "Error: cannot find user home directory\n"); exit(1); } // mount bind private_homedir on top of homedir if (arg_debug) printf("Mount-bind %s on top of %s\n", private_homedir, homedir); if (mount(private_homedir, homedir, NULL, MS_NOSUID | MS_NODEV | MS_BIND | MS_REC, NULL) < 0) errExit("mount bind"); fs_logger3("mount-bind", private_homedir, cfg.homedir); fs_logger2("whitelist", cfg.homedir); // preserve mode and ownership // if (chown(homedir, s.st_uid, s.st_gid) == -1) // errExit("mount-bind chown"); // if (chmod(homedir, s.st_mode) == -1) // errExit("mount-bind chmod"); if (u != 0) { // mask /root if (arg_debug) printf("Mounting a new /root directory\n"); if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0) errExit("mounting home directory"); fs_logger("tmpfs /root"); } else { // mask /home if (arg_debug) printf("Mounting a new /home directory\n"); if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) errExit("mounting home directory"); fs_logger("tmpfs /home"); } skel(homedir, u, g); if (xflag) copy_xauthority(); if (aflag) copy_asoundrc(); }
// private mode (--private=homedir): // mount homedir on top of /home/user, // tmpfs on top of /root in nonroot mode, // tmpfs on top of /tmp in root mode, // set skel files, // restore .Xauthority void fs_private_homedir(void) { char *homedir = cfg.homedir; char *private_homedir = cfg.home_private; assert(homedir); assert(private_homedir); int xflag = store_xauthority(); uid_t u = getuid(); gid_t g = getgid(); struct stat s; if (stat(homedir, &s) == -1) { exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: cannot find user home directory\n"); exit(1); } // mount bind private_homedir on top of homedir if (arg_debug) printf("Mount-bind %s on top of %s\n", private_homedir, homedir); if (mount(private_homedir, homedir, NULL, MS_BIND|MS_REC, NULL) < 0) errExit("mount bind"); // preserve mode and ownership // if (chown(homedir, s.st_uid, s.st_gid) == -1) // errExit("mount-bind chown"); // if (chmod(homedir, s.st_mode) == -1) // errExit("mount-bind chmod"); if (u != 0) { // mask /root if (arg_debug) printf("Mounting a new /root directory\n"); if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0) errExit("mounting home directory"); } else { // mask /home if (arg_debug) printf("Mounting a new /home directory\n"); if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) errExit("mounting home directory"); // mask /tmp only in root mode; KDE keeps all kind of sockets in /tmp! if (arg_debug) printf("Mounting a new /tmp directory\n"); if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0) errExit("mounting tmp directory"); } skel(homedir, u, g); if (xflag) copy_xauthority(); }
// private mode (--private-home=list): // mount homedir on top of /home/user, // tmpfs on top of /root in nonroot mode, // tmpfs on top of /tmp in root mode, // set skel files, // restore .Xauthority void fs_private_home_list(void) { char *homedir = cfg.homedir; char *private_list = cfg.home_private_keep; assert(homedir); assert(private_list); int xflag = store_xauthority(); uid_t u = getuid(); gid_t g = getgid(); struct stat s; if (stat(homedir, &s) == -1) { exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: cannot find user home directory\n"); exit(1); } // create /tmp/firejail/mnt/home directory fs_build_mnt_dir(); int rv = mkdir(HOME_DIR, S_IRWXU | S_IRWXG | S_IRWXO); if (rv == -1) errExit("mkdir"); if (chown(HOME_DIR, u, g) < 0) errExit("chown"); if (chmod(HOME_DIR, 0755) < 0) errExit("chmod"); // copy the list of files in the new home directory // using a new child process without root privileges pid_t child = fork(); if (child < 0) errExit("fork"); if (child == 0) { if (arg_debug) printf("Copying files in the new home:\n"); // drop privileges if (setgroups(0, NULL) < 0) errExit("setgroups"); if (setgid(getgid()) < 0) errExit("setgid/getgid"); if (setuid(getuid()) < 0) errExit("setuid/getuid"); // copy the list of files in the new home directory char *dlist = strdup(cfg.home_private_keep); if (!dlist) errExit("strdup"); char *ptr = strtok(dlist, ","); duplicate(ptr); while ((ptr = strtok(NULL, ",")) != NULL) duplicate(ptr); free(dlist); exit(0); } // wait for the child to finish waitpid(child, NULL, 0); // mount bind private_homedir on top of homedir char *newhome; if (asprintf(&newhome, "%s%s", HOME_DIR, cfg.homedir) == -1) errExit("asprintf"); if (arg_debug) printf("Mount-bind %s on top of %s\n", newhome, homedir); if (mount(newhome, homedir, NULL, MS_BIND|MS_REC, NULL) < 0) errExit("mount bind"); // preserve mode and ownership // if (chown(homedir, s.st_uid, s.st_gid) == -1) // errExit("mount-bind chown"); // if (chmod(homedir, s.st_mode) == -1) // errExit("mount-bind chmod"); if (u != 0) { // mask /root if (arg_debug) printf("Mounting a new /root directory\n"); if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0) errExit("mounting home directory"); } else { // mask /home if (arg_debug) printf("Mounting a new /home directory\n"); if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) errExit("mounting home directory"); // mask /tmp only in root mode; KDE keeps all kind of sockets in /tmp! if (arg_debug) printf("Mounting a new /tmp directory\n"); if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0) errExit("mounting tmp directory"); } skel(homedir, u, g); if (xflag) copy_xauthority(); }