From a274ad13bb5a0fcf7b42ab13955be6e042301cf4 Mon Sep 17 00:00:00 2001 From: smitsohu Date: Tue, 23 Feb 2021 22:08:46 +0100 Subject: add PATH_FCOPY to private-lib automatically restore 45304621a6c600d8e30e98bfbef05149caaf56c5, but now run fldd as root user. This became necessary because in the meantime read permission on helper executables was removed. Puts infrastructure in place to add other helper binaries to private-lib as well, should the need arise. --- src/firejail/fs_lib.c | 52 ++++++++++++++++++++++----------------------- src/firejail/fs_lib2.c | 57 +++++++++++++++++++++++++++++++++++++++++++++----- src/firejail/sbox.c | 7 ++++--- 3 files changed, 82 insertions(+), 34 deletions(-) diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c index a7f5b0bfc..9bf17b981 100644 --- a/src/firejail/fs_lib.c +++ b/src/firejail/fs_lib.c @@ -28,6 +28,7 @@ #define MAXBUF 4096 extern void fslib_install_stdc(void); +extern void fslib_install_firejail(void); extern void fslib_install_system(void); static int lib_cnt = 0; @@ -141,14 +142,11 @@ void fslib_duplicate(const char *full_path) { // requires full path for lib // it could be a library or an executable // lib is not copied, only libraries used by it -void fslib_copy_libs(const char *full_path) { - assert(full_path); - if (arg_debug || arg_debug_private_lib) - printf(" fslib_copy_libs %s\n", full_path); - +static void fslib_copy_libs(const char *full_path, unsigned mask) { // if library/executable does not exist or the user does not have read access to it // print a warning and exit the function. - if (access(full_path, R_OK)) { + if (((mask & SBOX_USER) && access(full_path, R_OK)) || + ((mask & SBOX_ROOT) && access(full_path, F_OK))) { if (arg_debug || arg_debug_private_lib) printf("cannot find %s for private-lib, skipping...\n", full_path); return; @@ -157,13 +155,15 @@ void fslib_copy_libs(const char *full_path) { // create an empty RUN_LIB_FILE and allow the user to write to it unlink(RUN_LIB_FILE); // in case is there create_empty_file_as_root(RUN_LIB_FILE, 0644); - if (chown(RUN_LIB_FILE, getuid(), getgid())) - errExit("chown"); + if (mask & SBOX_USER) { + if (chown(RUN_LIB_FILE, getuid(), getgid())) + errExit("chown"); + } // run fldd to extract the list of files if (arg_debug || arg_debug_private_lib) printf(" running fldd %s\n", full_path); - sbox_run(SBOX_USER | SBOX_SECCOMP | SBOX_CAPS_NONE, 3, PATH_FLDD, full_path, RUN_LIB_FILE); + sbox_run(mask | SBOX_SECCOMP | SBOX_CAPS_NONE, 3, PATH_FLDD, full_path, RUN_LIB_FILE); // open the list of libraries and install them on by one FILE *fp = fopen(RUN_LIB_FILE, "r"); @@ -182,6 +182,19 @@ void fslib_copy_libs(const char *full_path) { unlink(RUN_LIB_FILE); } +void fslib_copy_libs_parse_as_root(const char *full_path) { + assert(full_path); + if (arg_debug || arg_debug_private_lib) + printf(" fslib_copy_libs_parse_as_root %s\n", full_path); + fslib_copy_libs(full_path, SBOX_ROOT); +} + +void fslib_copy_libs_parse_as_user(const char *full_path) { + assert(full_path); + if (arg_debug || arg_debug_private_lib) + printf(" fslib_copy_libs_parse_as_user %s\n", full_path); + fslib_copy_libs(full_path, SBOX_USER); +} void fslib_copy_dir(const char *full_path) { assert(full_path); @@ -236,7 +249,7 @@ static void load_library(const char *fname) { access(fname, X_OK) != 0) // don't duplicate executables, just install the libraries fslib_duplicate(fname); - fslib_copy_libs(fname); + fslib_copy_libs_parse_as_user(fname); } } } @@ -379,25 +392,12 @@ void fs_private_lib(void) { printf("Installing standard C library\n"); fslib_install_stdc(); - // start timetrace - timetrace_start(); - - // bring in firejail executable libraries in case we are redirected here by a firejail symlink from /usr/local/bin/firejail + // install other libraries needed by firejail if (arg_debug || arg_debug_private_lib) printf("Installing Firejail libraries\n"); - fslib_install_list(PATH_FIREJAIL); - - // bring in firejail directory - fslib_install_list(LIBDIR "/firejail"); - - // bring in dhclient libraries - if (any_dhcp()) { - if (arg_debug || arg_debug_private_lib) - printf("Installing dhclient libraries\n"); - fslib_install_list(RUN_MNT_DIR "/dhclient"); - } - fmessage("Firejail libraries installed in %0.2f ms\n", timetrace_end()); + fslib_install_firejail(); + // start timetrace timetrace_start(); // copy the libs in the new lib directory for the main exe diff --git a/src/firejail/fs_lib2.c b/src/firejail/fs_lib2.c index 30e993438..d46cfed86 100644 --- a/src/firejail/fs_lib2.c +++ b/src/firejail/fs_lib2.c @@ -22,7 +22,8 @@ #include extern void fslib_duplicate(const char *full_path); -extern void fslib_copy_libs(const char *full_path); +extern void fslib_copy_libs_parse_as_user(const char *full_path); +extern void fslib_copy_libs_parse_as_root(const char *full_path); extern void fslib_copy_dir(const char *full_path); //*************************************************************** @@ -123,6 +124,52 @@ void fslib_install_stdc(void) { fmessage("Standard C library installed in %0.2f ms\n", timetrace_end()); } +//*************************************************************** +// Firejail libraries +//*************************************************************** + +static void fdir(void) { + fslib_copy_dir(LIBDIR "/firejail"); + + // executables and libraries from firejail directory + static const char * const fbin[] = { + PATH_FCOPY, // currently sufficient to find all needed libraries + // PATH_FSECCOMP, + // PATH_FSEC_OPTIMIZE, + // PATH_FSEC_PRINT, + // RUN_FIREJAIL_LIB_DIR "/libtrace.so", + // RUN_FIREJAIL_LIB_DIR "/libtracelog.so", + // RUN_FIREJAIL_LIB_DIR "/libpostexecseccomp.so", + NULL, + }; + + // need to run fldd as root user, unprivileged users have no read permission on executables + int i; + for (i = 0; fbin[i]; i++) + fslib_copy_libs_parse_as_root(fbin[i]); +} + +void fslib_install_firejail(void) { + timetrace_start(); + // bring in firejail executable libraries, in case we are redirected here + // by a firejail symlink from /usr/local/bin/firejail + fslib_copy_libs_parse_as_user(PATH_FIREJAIL); + + // bring in firejail directory + fdir(); + + // bring in dhclient libraries + if (any_dhcp()) + fslib_copy_libs_parse_as_user(RUN_MNT_DIR "/dhclient"); + +#ifdef HAVE_X11 + // bring in xauth libraries + if (arg_x11_xorg) + fslib_copy_libs_parse_as_user("/usr/bin/xauth"); +#endif + + fmessage("Firejail libraries installed in %0.2f ms\n", timetrace_end()); +} //*************************************************************** // various system libraries @@ -268,7 +315,7 @@ void fslib_install_system(void) { if (asprintf(&name, "/usr/lib/x86_64-linux-gnu/%s", ptr->dir1) == -1) errExit("asprintf"); if (access(name, R_OK) == 0) { - fslib_copy_libs(name); + fslib_copy_libs_parse_as_user(name); fslib_copy_dir(name); } else { @@ -277,7 +324,7 @@ void fslib_install_system(void) { if (asprintf(&name, "/usr/lib64/%s", ptr->dir1) == -1) errExit("asprintf"); if (access(name, R_OK) == 0) { - fslib_copy_libs(name); + fslib_copy_libs_parse_as_user(name); fslib_copy_dir(name); } } @@ -288,7 +335,7 @@ void fslib_install_system(void) { if (asprintf(&name, "/usr/lib/x86_64-linux-gnu/%s", ptr->dir2) == -1) errExit("asprintf"); if (access(name, R_OK) == 0) { - fslib_copy_libs(name); + fslib_copy_libs_parse_as_user(name); fslib_copy_dir(name); } else { @@ -297,7 +344,7 @@ void fslib_install_system(void) { if (asprintf(&name, "/usr/lib64/%s", ptr->dir2) == -1) errExit("asprintf"); if (access(name, R_OK) == 0) { - fslib_copy_libs(name); + fslib_copy_libs_parse_as_user(name); fslib_copy_dir(name); } } diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c index 933c93b0d..f9c41f661 100644 --- a/src/firejail/sbox.c +++ b/src/firejail/sbox.c @@ -203,15 +203,16 @@ static int __attribute__((noreturn)) sbox_do_exec_v(unsigned filtermask, char * } } - if (filtermask & SBOX_ROOT) { + if (filtermask & SBOX_USER) + drop_privs(1); + else if (filtermask & SBOX_ROOT) { // elevate privileges in order to get grsecurity working if (setreuid(0, 0)) errExit("setreuid"); if (setregid(0, 0)) errExit("setregid"); } - else if (filtermask & SBOX_USER) - drop_privs(1); + else assert(0); if (arg[0]) { // get rid of scan-build warning int fd = open(arg[0], O_PATH | O_CLOEXEC); -- cgit v1.2.3-54-g00ecf