void fs_build_mnt_dir(void) { struct stat s; fs_build_firejail_dir(); // create /run/firejail/mnt directory if (stat(RUN_MNT_DIR, &s)) { if (arg_debug) printf("Creating %s directory\n", RUN_MNT_DIR); /* coverity[toctou] */ int rv = mkdir(RUN_MNT_DIR, 0755); if (rv == -1) errExit("mkdir"); if (chown(RUN_MNT_DIR, 0, 0) < 0) errExit("chown"); if (chmod(RUN_MNT_DIR, 0755) < 0) errExit("chmod"); } // ... and mount tmpfs on top of it if (!tmpfs_mounted) { // mount tmpfs on top of /run/firejail/mnt if (arg_debug) printf("Mounting tmpfs on %s directory\n", RUN_MNT_DIR); if (mount("tmpfs", RUN_MNT_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) errExit("mounting /tmp/firejail/mnt"); tmpfs_mounted = 1; } }
static char *create_empty_dir(void) { struct stat s; fs_build_firejail_dir(); if (stat(RO_DIR, &s)) { /* coverity[toctou] */ int rv = mkdir(RO_DIR, S_IRUSR | S_IXUSR); if (rv == -1) errExit("mkdir"); if (chown(RO_DIR, 0, 0) < 0) errExit("chown"); } return RO_DIR; }
// build /tmp/firejail/overlay directory void fs_build_overlay_dir(void) { struct stat s; fs_build_firejail_dir(); // create /tmp/firejail directory if (stat(OVERLAY_DIR, &s)) { if (arg_debug) printf("Creating %s directory\n", MNT_DIR); /* coverity[toctou] */ int rv = mkdir(OVERLAY_DIR, S_IRWXU | S_IRWXG | S_IRWXO); if (rv == -1) errExit("mkdir"); if (chown(OVERLAY_DIR, 0, 0) < 0) errExit("chown"); if (chmod(OVERLAY_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) errExit("chmod"); } }
static char *create_empty_file(void) { struct stat s; fs_build_firejail_dir(); if (stat(RO_FILE, &s)) { /* coverity[toctou] */ FILE *fp = fopen(RO_FILE, "w"); if (!fp) errExit("fopen"); fclose(fp); if (chown(RO_FILE, 0, 0) < 0) errExit("chown"); if (chmod(RO_FILE, S_IRUSR) < 0) errExit("chown"); } return RO_FILE; }
static void disable_file(OPERATION op, const char *filename) { assert(filename); assert(op <OPERATION_MAX); last_disable = UNSUCCESSFUL; // rebuild /run/firejail directory in case tmpfs was mounted on top of /run fs_build_firejail_dir(); // Resolve all symlinks char* fname = realpath(filename, NULL); if (fname == NULL && errno != EACCES) { if (arg_debug) printf("Warning (realpath): %s is an invalid file, skipping...\n", filename); return; } if (fname == NULL && errno == EACCES) { if (arg_debug) printf("Debug: no access to file %s, forcing mount\n", filename); // realpath and stat funtions will fail on FUSE filesystems // they don't seem to like a uid of 0 // force mounting int rv = mount(RUN_RO_DIR, filename, "none", MS_BIND, "mode=400,gid=0"); if (rv == 0) last_disable = SUCCESSFUL; else { rv = mount(RUN_RO_FILE, filename, "none", MS_BIND, "mode=400,gid=0"); if (rv == 0) last_disable = SUCCESSFUL; } if (last_disable == SUCCESSFUL) { if (arg_debug) printf("Disable %s\n", filename); if (op == BLACKLIST_FILE) fs_logger2("blacklist", filename); else fs_logger2("blacklist-nolog", filename); } else { if (arg_debug) printf("Warning (blacklisting): %s is an invalid file, skipping...\n", filename); } return; } // if the file is not present, do nothing struct stat s; if (fname == NULL) return; if (stat(fname, &s) == -1) { if (arg_debug) printf("Warning: %s does not exist, skipping...\n", fname); free(fname); return; } // modify the file if (op == BLACKLIST_FILE || op == BLACKLIST_NOLOG) { // some distros put all executables under /usr/bin and make /bin a symbolic link if ((strcmp(fname, "/bin") == 0 || strcmp(fname, "/usr/bin") == 0) && is_link(filename) && S_ISDIR(s.st_mode)) fprintf(stderr, "Warning: %s directory link was not blacklisted\n", filename); else { if (arg_debug) printf("Disable %s\n", fname); else if (arg_debug_blacklists) { printf("Disable %s", fname); if (op == BLACKLIST_FILE) printf("\n"); else printf(" - no logging\n"); } if (S_ISDIR(s.st_mode)) { if (mount(RUN_RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0) errExit("disable file"); } else { if (mount(RUN_RO_FILE, fname, "none", MS_BIND, "mode=400,gid=0") < 0) errExit("disable file"); } last_disable = SUCCESSFUL; if (op == BLACKLIST_FILE) fs_logger2("blacklist", fname); else fs_logger2("blacklist-nolog", fname); } } else if (op == MOUNT_READONLY) { if (arg_debug) printf("Mounting read-only %s\n", fname); fs_rdonly(fname); // todo: last_disable = SUCCESSFUL; } else if (op == MOUNT_TMPFS) { if (S_ISDIR(s.st_mode)) { if (arg_debug) printf("Mounting tmpfs on %s\n", fname); // preserve owner and mode for the directory if (mount("tmpfs", fname, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, 0) < 0) errExit("mounting tmpfs"); /* coverity[toctou] */ if (chown(fname, s.st_uid, s.st_gid) == -1) errExit("mounting tmpfs chmod"); last_disable = SUCCESSFUL; fs_logger2("mount tmpfs on", fname); } else printf("Warning: %s is not a directory; cannot mount a tmpfs on top of it.\n", fname); } else assert(0); free(fname); }