From c86cae2d08da10eaec01964654c505387ee51eac Mon Sep 17 00:00:00 2001 From: rusty-snake <41237666+rusty-snake@users.noreply.github.com> Date: Sat, 4 Sep 2021 19:08:32 +0200 Subject: Add new condition ALLOW_TRAY --- src/firejail/checkcfg.c | 2 ++ src/firejail/firejail.h | 1 + src/firejail/profile.c | 5 +++++ src/man/firejail-profile.txt | 2 +- 4 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index 06e6f0ccb..e5d837bbb 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c @@ -58,6 +58,7 @@ int checkcfg(int val) { cfg_val[CFG_XPRA_ATTACH] = 0; cfg_val[CFG_SECCOMP_ERROR_ACTION] = -1; cfg_val[CFG_BROWSER_ALLOW_DRM] = 0; + cfg_val[CFG_ALLOW_TRAY] = 0; // open configuration file const char *fname = SYSCONFDIR "/firejail.config"; @@ -122,6 +123,7 @@ int checkcfg(int val) { PARSE_YESNO(CFG_XPRA_ATTACH, "xpra-attach") PARSE_YESNO(CFG_BROWSER_DISABLE_U2F, "browser-disable-u2f") PARSE_YESNO(CFG_BROWSER_ALLOW_DRM, "browser-allow-drm") + PARSE_YESNO(CFG_ALLOW_TRAY, "allow-tray") #undef PARSE_YESNO // netfilter diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 2a7d88575..46985d89e 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -801,6 +801,7 @@ enum { CFG_NAME_CHANGE, CFG_SECCOMP_ERROR_ACTION, // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv + CFG_ALLOW_TRAY, CFG_MAX // this should always be the last entry }; extern char *xephyr_screen; diff --git a/src/firejail/profile.c b/src/firejail/profile.c index b7c7185a6..7c7c7a025 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -175,6 +175,10 @@ static int check_allow_drm(void) { return checkcfg(CFG_BROWSER_ALLOW_DRM) != 0; } +static int check_allow_tray(void) { + return checkcfg(CFG_ALLOW_TRAY) != 0; +} + Cond conditionals[] = { {"HAS_APPIMAGE", check_appimage}, {"HAS_NET", check_netoptions}, @@ -184,6 +188,7 @@ Cond conditionals[] = { {"HAS_X11", check_x11}, {"BROWSER_DISABLE_U2F", check_disable_u2f}, {"BROWSER_ALLOW_DRM", check_allow_drm}, + {"ALLOW_TRAY", check_allow_tray}, { NULL, NULL } }; diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index 6280026e6..adb79234b 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt @@ -174,7 +174,7 @@ Example: "?HAS_APPIMAGE: allow ${HOME}/special/appimage/dir" This example will load the profile line only if the \-\-appimage option has been specified on the command line. -Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND, HAS_PRIVATE and HAS_X11. The conditionals BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM +Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND, HAS_PRIVATE and HAS_X11. The conditionals ALLOW_TRAY, BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM can be enabled or disabled globally in Firejail's configuration file. The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. -- cgit v1.2.3-70-g09d2 From 5805c1c8fd440b69a96bd9e205c09a178a13e6ba Mon Sep 17 00:00:00 2001 From: dm9pZCAq <46228973+dm9pZCAq@users.noreply.github.com> Date: Mon, 27 Sep 2021 21:52:56 +0300 Subject: fix compilation on musl (#4578) --- src/firejail/env.c | 1 + src/firejail/main.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/firejail/env.c b/src/firejail/env.c index ad16de037..4c0d729a1 100644 --- a/src/firejail/env.c +++ b/src/firejail/env.c @@ -22,6 +22,7 @@ #include #include #include +#include typedef struct env_t { struct env_t *next; diff --git a/src/firejail/main.c b/src/firejail/main.c index 81d148257..2db17f4af 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -32,7 +32,7 @@ #include #include #include -//#include +#include #include #include #include -- cgit v1.2.3-70-g09d2 From 9e18bf8a10a3b9b948c15853ad716cf8e3673fcf Mon Sep 17 00:00:00 2001 From: smitsohu Date: Wed, 29 Sep 2021 15:49:52 +0200 Subject: add more EUID improvements --- src/fcopy/main.c | 3 ++- src/firejail/fs.c | 12 ++++----- src/firejail/fs_dev.c | 2 ++ src/firejail/fs_home.c | 11 ++++++--- src/firejail/fs_whitelist.c | 59 +++++++++++++++++++-------------------------- src/firejail/sandbox.c | 2 ++ src/firejail/selinux.c | 21 +++++++++++++++- src/firejail/util.c | 14 ++--------- 8 files changed, 65 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/fcopy/main.c b/src/fcopy/main.c index 31810de9a..f279af89f 100644 --- a/src/fcopy/main.c +++ b/src/fcopy/main.c @@ -88,7 +88,8 @@ static void selinux_relabel_path(const char *path, const char *inside_path) { if (arg_debug) printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); - setfilecon_raw(procfs_path, fcon); + if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug) + printf("Cannot relabel %s: %s\n", path, strerror(errno)); } freecon(fcon); close: diff --git a/src/firejail/fs.c b/src/firejail/fs.c index dd4c2139d..6d01b5e5d 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c @@ -200,8 +200,6 @@ static void disable_file(OPERATION op, const char *filename) { } fs_tmpfs(fname, uid); - EUID_USER(); // fs_tmpfs returns with EUID 0 - selinux_relabel_path(fname, fname); } else @@ -282,6 +280,8 @@ static void globbing(OPERATION op, const char *pattern, const char *noblacklist[ // blacklist files or directories by mounting empty files on top of them void fs_blacklist(void) { + EUID_ASSERT(); + ProfileEntry *entry = cfg.profile; if (!entry) return; @@ -293,7 +293,6 @@ void fs_blacklist(void) { if (noblacklist == NULL) errExit("failed allocating memory for noblacklist entries"); - EUID_USER(); while (entry) { OPERATION op = OPERATION_MAX; char *ptr; @@ -469,8 +468,6 @@ void fs_blacklist(void) { for (i = 0; i < noblacklist_c; i++) free(noblacklist[i]); free(noblacklist); - - EUID_ROOT(); } //*********************************************** @@ -479,7 +476,7 @@ void fs_blacklist(void) { // mount a writable tmpfs on directory; requires a resolved path void fs_tmpfs(const char *dir, unsigned check_owner) { - EUID_USER(); + EUID_ASSERT(); assert(dir); if (arg_debug) printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no"); @@ -504,12 +501,13 @@ void fs_tmpfs(const char *dir, unsigned check_owner) { errExit("fstatvfs"); unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND|MS_REMOUNT); // mount via the symbolic link in /proc/self/fd - EUID_ROOT(); char *proc; if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) errExit("asprintf"); + EUID_ROOT(); if (mount("tmpfs", proc, "tmpfs", flags|MS_NOSUID|MS_NODEV, options) < 0) errExit("mounting tmpfs"); + EUID_USER(); // check the last mount operation MountData *mdata = get_last_mount(); if (strcmp(mdata->fstype, "tmpfs") != 0 || strcmp(mdata->dir, dir) != 0) diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c index 8cc3ecc62..a43b18344 100644 --- a/src/firejail/fs_dev.c +++ b/src/firejail/fs_dev.c @@ -330,8 +330,10 @@ void fs_dev_disable_sound(void) { } // disable all jack sockets in /dev/shm + EUID_USER(); glob_t globbuf; int globerr = glob("/dev/shm/jack*", GLOB_NOSORT, NULL, &globbuf); + EUID_ROOT(); if (globerr) return; diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index 0ed476063..590337da1 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c @@ -395,14 +395,16 @@ void fs_private(void) { } if (chown(homedir, u, g) < 0) errExit("chown"); - fs_logger2("mkdir", homedir); fs_logger2("tmpfs", homedir); } - else + else { // mask user home directory // the directory should be owned by the current user + EUID_USER(); fs_tmpfs(homedir, 1); + EUID_ROOT(); + } selinux_relabel_path(homedir, homedir); } @@ -564,12 +566,13 @@ void fs_private_home_list(void) { int xflag = store_xauthority(); int aflag = store_asoundrc(); - // create /run/firejail/mnt/home directory EUID_ROOT(); + // create /run/firejail/mnt/home directory mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); selinux_relabel_path(RUN_HOME_DIR, homedir); - fs_logger_print(); // save the current log + // save the current log + fs_logger_print(); EUID_USER(); // copy the list of files in the new home directory diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 943f275de..7afebed1f 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c @@ -105,6 +105,7 @@ static int whitelist_mkpath(const char* path, mode_t mode) { } static void whitelist_file(int dirfd, const char *relpath, const char *path) { + EUID_ASSERT(); assert(relpath && path); // open mount source, using a file descriptor that refers to the @@ -130,12 +131,9 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) { } // create mount target as root, except if inside home or run/user/$UID directory - int userprivs = 0; - if ((strncmp(path, cfg.homedir, homedir_len) == 0 && path[homedir_len] == '/') || - (strncmp(path, runuser, runuser_len) == 0 && path[runuser_len] == '/')) { - EUID_USER(); - userprivs = 1; - } + if ((strncmp(path, cfg.homedir, homedir_len) != 0 || path[homedir_len] != '/') && + (strncmp(path, runuser, runuser_len) != 0 || path[runuser_len] != '/')) + EUID_ROOT(); // create path of the mount target int fd2 = whitelist_mkpath(path, 0755); @@ -146,8 +144,7 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) { if (arg_debug || arg_debug_whitelists) printf("Debug %d: skip whitelist %s\n", __LINE__, path); close(fd); - if (userprivs) - EUID_ROOT(); + EUID_USER(); return; } @@ -166,8 +163,7 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) { } close(fd); close(fd2); - if (userprivs) - EUID_ROOT(); + EUID_USER(); return; } fd3 = openat(fd2, file, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); @@ -184,19 +180,17 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) { } close(fd); close(fd2); - if (userprivs) - EUID_ROOT(); + EUID_USER(); return; } - close(fd2); - if (userprivs) - EUID_ROOT(); if (arg_debug || arg_debug_whitelists) printf("Whitelisting %s\n", path); + EUID_ROOT(); if (bind_mount_by_fd(fd, fd3)) errExit("mount bind"); + EUID_USER(); // check the last mount operation MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found #ifdef TEST_MOUNTINFO @@ -219,22 +213,19 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) { } static void whitelist_symlink(const char *link, const char *target) { + EUID_ASSERT(); assert(link && target); // create files as root, except if inside home or run/user/$UID directory - int userprivs = 0; - if ((strncmp(link, cfg.homedir, homedir_len) == 0 && link[homedir_len] == '/') || - (strncmp(link, runuser, runuser_len) == 0 && link[runuser_len] == '/')) { - EUID_USER(); - userprivs = 1; - } + if ((strncmp(link, cfg.homedir, homedir_len) != 0 || link[homedir_len] != '/') && + (strncmp(link, runuser, runuser_len) != 0 || link[runuser_len] != '/')) + EUID_ROOT(); int fd = whitelist_mkpath(link, 0755); if (fd == -1) { if (arg_debug || arg_debug_whitelists) printf("Debug %d: cannot create symbolic link %s\n", __LINE__, link); - if (userprivs) - EUID_ROOT(); + EUID_USER(); return; } @@ -252,8 +243,7 @@ static void whitelist_symlink(const char *link, const char *target) { printf("Created symbolic link %s -> %s\n", link, target); close(fd); - if (userprivs) - EUID_ROOT(); + EUID_USER(); } static void globbing(const char *pattern) { @@ -330,10 +320,11 @@ static void tmpfs_topdirs(const TopDir *topdirs) { // init tmpfs if (strcmp(topdirs[i].path, "/run") == 0) { // restore /run/firejail directory - if (mkdir(RUN_FIREJAIL_DIR, 0755) == -1) - errExit("mkdir"); + EUID_ROOT(); + mkdir_attr(RUN_FIREJAIL_DIR, 0755, 0, 0); if (bind_mount_fd_to_path(fd, RUN_FIREJAIL_DIR)) errExit("mount bind"); + EUID_USER(); close(fd); fs_logger2("whitelist", RUN_FIREJAIL_DIR); @@ -351,12 +342,14 @@ static void tmpfs_topdirs(const TopDir *topdirs) { errExit("asprintf"); if (strcmp(env, pamtmpdir) == 0) { // create empty user-owned /tmp/user/$UID directory + EUID_ROOT(); mkdir_attr("/tmp/user", 0711, 0, 0); selinux_relabel_path("/tmp/user", "/tmp/user"); fs_logger("mkdir /tmp/user"); mkdir_attr(pamtmpdir, 0700, getuid(), 0); selinux_relabel_path(pamtmpdir, pamtmpdir); fs_logger2("mkdir", pamtmpdir); + EUID_USER(); } free(pamtmpdir); } @@ -374,11 +367,8 @@ static void tmpfs_topdirs(const TopDir *topdirs) { } // user home directory - if (tmpfs_home) { - EUID_USER(); + if (tmpfs_home) fs_private(); // checks owner if outside /home - EUID_ROOT(); - } // /run/user/$UID directory if (tmpfs_runuser) { @@ -402,6 +392,7 @@ static int reject_topdir(const char *dir) { // keep track of whitelist top level directories by adding them to an array // open each directory static TopDir *add_topdir(const char *dir, TopDir *topdirs, const char *path) { + EUID_ASSERT(); assert(dir && path); // /proc and /sys are not allowed @@ -516,6 +507,8 @@ static char *extract_topdir(const char *path) { } void fs_whitelist(void) { + EUID_ASSERT(); + ProfileEntry *entry = cfg.profile; if (!entry) return; @@ -536,7 +529,6 @@ void fs_whitelist(void) { errExit("calloc"); // verify whitelist files, extract symbolic links, etc. - EUID_USER(); while (entry) { int nowhitelist_flag = 0; @@ -630,7 +622,7 @@ void fs_whitelist(void) { if (!fname) { if (arg_debug || arg_debug_whitelists) { printf("Removed path: %s\n", entry->data); - printf("\texpanded: %s\n", new_name); + printf("\tnew_name: %s\n", new_name); printf("\trealpath: (null)\n"); printf("\t%s\n", strerror(errno)); } @@ -712,7 +704,6 @@ void fs_whitelist(void) { free(nowhitelist); // mount tmpfs on all top level directories - EUID_ROOT(); tmpfs_topdirs(topdirs); // go through profile rules again, and interpret whitelist commands diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 995827fb7..83e50aee2 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -1004,10 +1004,12 @@ int sandbox(void* sandbox_arg) { // apply the profile file //**************************** // apply all whitelist commands ... + EUID_USER(); fs_whitelist(); // ... followed by blacklist commands fs_blacklist(); // mkdir and mkfile are processed all over again + EUID_ROOT(); //**************************** // nosound/no3d/notv/novideo and fix for pulseaudio 7.0 diff --git a/src/firejail/selinux.c b/src/firejail/selinux.c index 6969e7a3d..fa59882ed 100644 --- a/src/firejail/selinux.c +++ b/src/firejail/selinux.c @@ -21,6 +21,7 @@ #include "firejail.h" #include #include +#include #include #ifndef O_PATH @@ -57,7 +58,17 @@ void selinux_relabel_path(const char *path, const char *inside_path) /* Open the file as O_PATH, to pin it while we determine and adjust the label * Defeat symlink races by not allowing symbolic links */ + int called_as_root = 0; + if (geteuid() == 0) + called_as_root = 1; + if (called_as_root) + EUID_USER(); + fd = safer_openat(-1, path, O_NOFOLLOW|O_CLOEXEC|O_PATH); + + if (called_as_root) + EUID_ROOT(); + if (fd < 0) return; if (fstat(fd, &st) < 0) @@ -68,8 +79,16 @@ void selinux_relabel_path(const char *path, const char *inside_path) if (arg_debug) printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); - setfilecon_raw(procfs_path, fcon); + if (!called_as_root) + EUID_ROOT(); + + if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug) + printf("Cannot relabel %s: %s\n", path, strerror(errno)); + + if (!called_as_root) + EUID_USER(); } + freecon(fcon); close: close(fd); diff --git a/src/firejail/util.c b/src/firejail/util.c index 094a68c60..f0df45eb2 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -459,31 +459,21 @@ int is_dir(const char *fname) { if (*fname == '\0') return 0; - int called_as_root = 0; - if (geteuid() == 0) - called_as_root = 1; - - if (called_as_root) - EUID_USER(); - // if fname doesn't end in '/', add one int rv; struct stat s; if (fname[strlen(fname) - 1] == '/') - rv = stat(fname, &s); + rv = stat_as_user(fname, &s); else { char *tmp; if (asprintf(&tmp, "%s/", fname) == -1) { fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__); errExit("asprintf"); } - rv = stat(tmp, &s); + rv = stat_as_user(tmp, &s); free(tmp); } - if (called_as_root) - EUID_ROOT(); - if (rv == -1) return 0; -- cgit v1.2.3-70-g09d2 From 94ab0ec71b3c550ff8ce0d6458d3257a3d3d1ed7 Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Mon, 4 Oct 2021 02:14:07 -0300 Subject: Add codium.profile as a redirect to vscodium.profile Both base names are valid: $ grep '^NAME' /etc/os-release NAME="Artix Linux" $ pacman -Q vscodium-bin vscodium-bin 1.60.2-2 $ pacman -Qlq vscodium-bin | grep -v -e '/$' -e /resources/ | grep /bin/ /usr/bin/codium /usr/bin/vscodium /usr/share/vscodium-bin/bin/codium Note: The first two paths are symlinks to the third one. Fixes #3871. --- etc/profile-a-l/codium.profile | 10 ++++++++++ src/firecfg/firecfg.config | 1 + 2 files changed, 11 insertions(+) create mode 100644 etc/profile-a-l/codium.profile (limited to 'src') diff --git a/etc/profile-a-l/codium.profile b/etc/profile-a-l/codium.profile new file mode 100644 index 000000000..9ff87ed8a --- /dev/null +++ b/etc/profile-a-l/codium.profile @@ -0,0 +1,10 @@ +# Firejail profile alias for VSCodium +# This file is overwritten after every install/update +# Persistent local customizations +include codium.local +# Persistent global definitions +# added by included profile +#include globals.local + +# Redirect +include vscodium.profile diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config index a544e25f2..aad22ec7a 100644 --- a/src/firecfg/firecfg.config +++ b/src/firecfg/firecfg.config @@ -151,6 +151,7 @@ clocks cmus code code-oss +codium cola colorful com.github.bleakgrey.tootle -- cgit v1.2.3-70-g09d2 From 84d5469a40bdc65aa5607d11a9060bb710bfd9b9 Mon Sep 17 00:00:00 2001 From: smitsohu Date: Tue, 5 Oct 2021 16:21:09 +0200 Subject: simplify recursive remounting --- src/firejail/firejail.h | 2 +- src/firejail/fs.c | 38 +++++++++++++++++--------------------- src/firejail/mountinfo.c | 40 ++++++++++++---------------------------- 3 files changed, 30 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 2a7d88575..e1ba8f48a 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -563,7 +563,7 @@ typedef struct { // mountinfo.c MountData *get_last_mount(void); -int get_mount_id(const char *path); +int get_mount_id(int fd); char **build_mount_array(const int mount_id, const char *path); // fs_var.c diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 6d01b5e5d..3144156a3 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c @@ -633,34 +633,30 @@ out: } // remount recursively; requires a resolved path -static void fs_remount_rec(const char *dir, OPERATION op) { +static void fs_remount_rec(const char *path, OPERATION op) { EUID_ASSERT(); - assert(dir); + assert(op < OPERATION_MAX); + assert(path); - struct stat s; - if (stat(dir, &s) != 0) - return; - if (!S_ISDIR(s.st_mode)) { - // no need to search in /proc/self/mountinfo for submounts if not a directory - fs_remount_simple(dir, op); + // no need to search /proc/self/mountinfo for submounts if not a directory + int fd = open(path, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); + if (fd < 0) { + fs_remount_simple(path, op); return; } - // get mount point of the directory - int mountid = get_mount_id(dir); - if (mountid == -1) - return; - if (mountid == -2) { - // falling back to a simple remount on old kernels - static int mount_warning = 0; - if (!mount_warning) { - fwarning("read-only, read-write and noexec options are not applied recursively\n"); - mount_warning = 1; - } - fs_remount_simple(dir, op); + + // get mount id of the directory + int mountid = get_mount_id(fd); + close(fd); + if (mountid < 0) { + // falling back to a simple remount + fwarning("%s %s not applied recursively\n", opstr[op], path); + fs_remount_simple(path, op); return; } + // build array with all mount points that need to get remounted - char **arr = build_mount_array(mountid, dir); + char **arr = build_mount_array(mountid, path); assert(arr); // remount char **tmp = arr; diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c index 64a94bd84..f1eb9c924 100644 --- a/src/firejail/mountinfo.c +++ b/src/firejail/mountinfo.c @@ -151,47 +151,31 @@ MountData *get_last_mount(void) { return &mdata; } -// Extract the mount id from /proc/self/fdinfo and return it. -int get_mount_id(const char *path) { - EUID_ASSERT(); - assert(path); - - int fd = open(path, O_PATH|O_CLOEXEC); - if (fd == -1) - return -1; +// Needs kernel 3.15 or better +int get_mount_id(int fd) { + int rv = -1; - char *fdinfo; - if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1) + char *proc; + if (asprintf(&proc, "/proc/self/fdinfo/%d", fd) == -1) errExit("asprintf"); EUID_ROOT(); - FILE *fp = fopen(fdinfo, "re"); + FILE *fp = fopen(proc, "re"); EUID_USER(); - free(fdinfo); if (!fp) goto errexit; - // read the file char buf[MAX_BUF]; - if (fgets(buf, MAX_BUF, fp) == NULL) - goto errexit; - do { + while (fgets(buf, MAX_BUF, fp)) { if (strncmp(buf, "mnt_id:", 7) == 0) { - char *ptr = buf + 7; - while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) { - ptr++; - } - if (*ptr == '\0') + if (sscanf(buf + 7, "%d", &rv) != 1) goto errexit; - fclose(fp); - close(fd); - return atoi(ptr); + break; } - } while (fgets(buf, MAX_BUF, fp)); + } - // fallback, kernels older than 3.15 don't expose the mount id in this place + free(proc); fclose(fp); - close(fd); - return -2; + return rv; errexit: fprintf(stderr, "Error: cannot read proc file\n"); -- cgit v1.2.3-70-g09d2 From 2247f58f52802a9726fd6991d61ae1d3cdac07b6 Mon Sep 17 00:00:00 2001 From: smitsohu Date: Wed, 29 Sep 2021 17:44:53 +0200 Subject: trace, tracelog: don't truncate /etc/ld.so.preload --- src/firejail/firejail.h | 3 ++- src/firejail/fs_trace.c | 31 +++++++++++++++++++------------ src/firejail/sandbox.c | 11 +++++++---- 3 files changed, 28 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 2a7d88575..bcc7e6ed1 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -621,7 +621,8 @@ void caps_print_filter(pid_t pid) __attribute__((noreturn)); void caps_drop_dac_override(void); // fs_trace.c -void fs_trace_preload(void); +void fs_trace_touch_preload(void); +void fs_trace_touch_or_store_preload(void); void fs_tracefile(void); void fs_trace(void); diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c index 475a391ec..718786cdc 100644 --- a/src/firejail/fs_trace.c +++ b/src/firejail/fs_trace.c @@ -26,19 +26,26 @@ #include #include -void fs_trace_preload(void) { +// create an empty /etc/ld.so.preload +void fs_trace_touch_preload(void) { + create_empty_file_as_root("/etc/ld.so.preload", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +} + +void fs_trace_touch_or_store_preload(void) { struct stat s; - // create an empty /etc/ld.so.preload - if (stat("/etc/ld.so.preload", &s)) { - if (arg_debug) - printf("Creating an empty /etc/ld.so.preload file\n"); - FILE *fp = fopen("/etc/ld.so.preload", "wxe"); - if (!fp) - errExit("fopen"); - SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); - fclose(fp); - fs_logger("touch /etc/ld.so.preload"); + if (stat("/etc/ld.so.preload", &s) != 0) { + fs_trace_touch_preload(); + return; + } + + if (s.st_size == 0) + return; + + // create a copy of /etc/ld.so.preload + if (copy_file("/etc/ld.so.preload", RUN_LDPRELOAD_FILE, 0, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) { + fprintf(stderr, "Error: cannot copy /etc/ld.so.preload file\n"); + exit(1); } } @@ -83,7 +90,7 @@ void fs_trace(void) { if (arg_debug) printf("Create the new ld.so.preload file\n"); - FILE *fp = fopen(RUN_LDPRELOAD_FILE, "we"); + FILE *fp = fopen(RUN_LDPRELOAD_FILE, "ae"); if (!fp) errExit("fopen"); const char *prefix = RUN_FIREJAIL_LIB_DIR; diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 995827fb7..7a1ce737b 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -798,7 +798,7 @@ int sandbox(void* sandbox_arg) { // trace pre-install if (need_preload) - fs_trace_preload(); + fs_trace_touch_or_store_preload(); // store hosts file if (cfg.hosts_file) @@ -814,8 +814,11 @@ int sandbox(void* sandbox_arg) { //**************************** // trace pre-install, this time inside chroot //**************************** - if (need_preload) - fs_trace_preload(); + if (need_preload) { + int rv = unlink(RUN_LDPRELOAD_FILE); + (void) rv; + fs_trace_touch_or_store_preload(); + } } else #endif @@ -992,7 +995,7 @@ int sandbox(void* sandbox_arg) { // create /etc/ld.so.preload file again if (need_preload) - fs_trace_preload(); + fs_trace_touch_preload(); // openSUSE configuration is split between /etc and /usr/etc // process private-etc a second time -- cgit v1.2.3-70-g09d2 From 5c39051c2b07d6f4854eca69c37f95066d9fb10f Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Tue, 5 Oct 2021 19:02:33 -0300 Subject: build_profile.c: fix typo of "begins" Added on commit 9af2c1472 ("Better debug handling."). --- src/fbuilder/build_profile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/fbuilder/build_profile.c b/src/fbuilder/build_profile.c index 0b9a99739..c945d7253 100644 --- a/src/fbuilder/build_profile.c +++ b/src/fbuilder/build_profile.c @@ -92,7 +92,7 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { if (fp == stdout) - printf("--- Built profile beings after this line ---\n"); + printf("--- Built profile begins after this line ---\n"); fprintf(fp, "# Save this file as \"application.profile\" (change \"application\" with the\n"); fprintf(fp, "# program name) in ~/.config/firejail directory. Firejail will find it\n"); fprintf(fp, "# automatically every time you sandbox your application.\n#\n"); -- cgit v1.2.3-70-g09d2 From a78d014660d8a1daaea95f11da399c2e2305cc63 Mon Sep 17 00:00:00 2001 From: smitsohu Date: Tue, 5 Oct 2021 18:11:50 +0200 Subject: mountinfo: get mount id from failed call to name_to_handle_at Enables recursive remounting on very old kernels, which has some relevance for SailfishOS community ports. --- src/firejail/mountinfo.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c index f1eb9c924..304f80eee 100644 --- a/src/firejail/mountinfo.c +++ b/src/firejail/mountinfo.c @@ -19,6 +19,7 @@ */ #include "firejail.h" +#include #include #ifndef O_PATH @@ -151,8 +152,35 @@ MountData *get_last_mount(void) { return &mdata; } -// Needs kernel 3.15 or better -int get_mount_id(int fd) { +// Returns mount id, or -1 if fd refers to a procfs or sysfs file +static int get_mount_id_from_handle(int fd) { + EUID_ASSERT(); + + char *proc; + if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) + errExit("asprintf"); + struct file_handle *fh = malloc(sizeof *fh); + if (!fh) + errExit("malloc"); + fh->handle_bytes = 0; + + int rv = -1; + int tmp; + if (name_to_handle_at(-1, proc, fh, &tmp, AT_SYMLINK_FOLLOW) != -1) { + fprintf(stderr, "Error: unexpected result from name_to_handle_at\n"); + exit(1); + } + if (errno == EOVERFLOW && fh->handle_bytes) + rv = tmp; + + free(proc); + free(fh); + return rv; +} + +// Returns mount id, or -1 on kernels < 3.15 +static int get_mount_id_from_fdinfo(int fd) { + EUID_ASSERT(); int rv = -1; char *proc; @@ -182,6 +210,13 @@ errexit: exit(1); } +int get_mount_id(int fd) { + int rv = get_mount_id_from_fdinfo(fd); + if (rv < 0) + rv = get_mount_id_from_handle(fd); + return rv; +} + // Check /proc/self/mountinfo if path contains any mounts points. // Returns an array that can be iterated over for recursive remounting. char **build_mount_array(const int mount_id, const char *path) { -- cgit v1.2.3-70-g09d2 From a7e4b9b9b20bc62985e03435e2eee41dd62e0318 Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Tue, 5 Oct 2021 17:54:03 -0300 Subject: Revert "allow/deny fbuilder" This reverts commit 4438f14f2892b5c88d158ae8fad0a80a2eebfd44. Also, partially revert related commit e4307b409 ("fix whitelist/allow in make test-utils") to keep the tests working. The profiles are being generated using aliases, which are not used on the profiles in the repository. So generate them using the normal commands for consistency. See also commit dd13595b8 ("Revert "allow/deny help and man pages"") / PR #4502. Relates to #4410. Misc: I noticed this on issue #4592. --- src/fbuilder/build_fs.c | 8 ++++---- src/fbuilder/build_home.c | 4 ++-- test/utils/build.exp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/fbuilder/build_fs.c b/src/fbuilder/build_fs.c index 019c3ac5a..8700e0ba1 100644 --- a/src/fbuilder/build_fs.c +++ b/src/fbuilder/build_fs.c @@ -182,12 +182,12 @@ static void var_callback(char *ptr) { void build_var(const char *fname, FILE *fp) { assert(fname); - var_skip = filedb_load_whitelist(var_skip, "whitelist-var-common.inc", "allow /var/"); + var_skip = filedb_load_whitelist(var_skip, "whitelist-var-common.inc", "whitelist /var/"); process_files(fname, "/var", var_callback); // always whitelist /var if (var_out) - filedb_print(var_out, "allow /var/", fp); + filedb_print(var_out, "whitelist /var/", fp); fprintf(fp, "include whitelist-var-common.inc\n"); } @@ -222,12 +222,12 @@ static void share_callback(char *ptr) { void build_share(const char *fname, FILE *fp) { assert(fname); - share_skip = filedb_load_whitelist(share_skip, "whitelist-usr-share-common.inc", "allow /usr/share/"); + share_skip = filedb_load_whitelist(share_skip, "whitelist-usr-share-common.inc", "whitelist /usr/share/"); process_files(fname, "/usr/share", share_callback); // always whitelist /usr/share if (share_out) - filedb_print(share_out, "allow /usr/share/", fp); + filedb_print(share_out, "whitelist /usr/share/", fp); fprintf(fp, "include whitelist-usr-share-common.inc\n"); } diff --git a/src/fbuilder/build_home.c b/src/fbuilder/build_home.c index c85474779..0fe0ffef6 100644 --- a/src/fbuilder/build_home.c +++ b/src/fbuilder/build_home.c @@ -140,7 +140,7 @@ void build_home(const char *fname, FILE *fp) { assert(fname); // load whitelist common - db_skip = filedb_load_whitelist(db_skip, "whitelist-common.inc", "allow ${HOME}/"); + db_skip = filedb_load_whitelist(db_skip, "whitelist-common.inc", "whitelist ${HOME}/"); // find user home directory struct passwd *pw = getpwuid(getuid()); @@ -168,7 +168,7 @@ void build_home(const char *fname, FILE *fp) { // print the out list if any if (db_out) { - filedb_print(db_out, "allow ${HOME}/", fp); + filedb_print(db_out, "whitelist ${HOME}/", fp); fprintf(fp, "include whitelist-common.inc\n"); } else diff --git a/test/utils/build.exp b/test/utils/build.exp index 104ac037c..b9733c137 100755 --- a/test/utils/build.exp +++ b/test/utils/build.exp @@ -13,7 +13,7 @@ after 100 send -- "firejail --build cat ~/_firejail-test-file\r" expect { timeout {puts "TESTING ERROR 0\n";exit} - "allow $\{HOME\}/_firejail-test-file" + "whitelist $\{HOME\}/_firejail-test-file" } expect { timeout {puts "TESTING ERROR 1\n";exit} -- cgit v1.2.3-70-g09d2 From a68fc0a040da498b3c01b6b9a281024c2dafe193 Mon Sep 17 00:00:00 2001 From: smitsohu Date: Fri, 8 Oct 2021 00:48:14 +0200 Subject: profile parsing fixes results from a systematic search for strncmp calls with a suspicious (non-fitting) integer literal as third argument --- src/firejail/profile.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 059100fcb..2daa968f7 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -630,7 +630,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { #endif return 0; } - else if (strncmp(ptr, "netns ", 6) == 0) { + else if (strncmp(ptr, "netns ", 6) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { arg_netns = ptr + 6; @@ -981,10 +981,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { warning_feature_disabled("seccomp"); return 0; } - if (strncmp(ptr, "seccomp.32.drop ", 13) == 0) { + if (strncmp(ptr, "seccomp.32.drop ", 16) == 0) { if (checkcfg(CFG_SECCOMP)) { arg_seccomp32 = 1; - cfg.seccomp_list_drop32 = seccomp_check_list(ptr + 13); + cfg.seccomp_list_drop32 = seccomp_check_list(ptr + 16); } else warning_feature_disabled("seccomp"); @@ -1001,10 +1001,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { warning_feature_disabled("seccomp"); return 0; } - if (strncmp(ptr, "seccomp.32.keep ", 13) == 0) { + if (strncmp(ptr, "seccomp.32.keep ", 16) == 0) { if (checkcfg(CFG_SECCOMP)) { arg_seccomp32 = 1; - cfg.seccomp_list_keep32 = seccomp_check_list(ptr + 13); + cfg.seccomp_list_keep32 = seccomp_check_list(ptr + 16); } else warning_feature_disabled("seccomp"); -- cgit v1.2.3-70-g09d2