mirror of
https://github.com/netblue30/firejail.git
synced 2026-05-15 14:16:14 -06:00
private-lib: split fldd as a separate application
This commit is contained in:
parent
dfb8b5e5b9
commit
0823eebfb6
6 changed files with 54 additions and 127 deletions
|
|
@ -1,6 +1,6 @@
|
|||
all: apps man filters
|
||||
MYLIBS = src/lib
|
||||
APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/fnet src/fseccomp src/fcopy
|
||||
APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/fnet src/fseccomp src/fcopy src/fldd
|
||||
MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5
|
||||
SECCOMP_FILTERS = seccomp seccomp.i386 seccomp.amd64
|
||||
|
||||
|
|
@ -96,6 +96,7 @@ endif
|
|||
install -c -m 0755 src/faudit/faudit $(DESTDIR)/$(libdir)/firejail/.
|
||||
install -c -m 0755 src/fnet/fnet $(DESTDIR)/$(libdir)/firejail/.
|
||||
install -c -m 0755 src/fcopy/fcopy $(DESTDIR)/$(libdir)/firejail/.
|
||||
install -c -m 0755 src/fldd/fldd $(DESTDIR)/$(libdir)/firejail/.
|
||||
ifeq ($(HAVE_SECCOMP),-DHAVE_SECCOMP)
|
||||
install -c -m 0755 src/fseccomp/fseccomp $(DESTDIR)/$(libdir)/firejail/.
|
||||
install -c -m 0644 seccomp $(DESTDIR)/$(libdir)/firejail/.
|
||||
|
|
|
|||
3
README
3
README
|
|
@ -36,6 +36,7 @@ Committers
|
|||
- Fred-Barclay (https://github.com/Fred-Barclay)
|
||||
- Reiner Herrmann (https://github.com/reinerh)
|
||||
- startx2017 (https://github.com/startx2017) - 0.9.38-LTS and *bugfixes branches maintainer
|
||||
- Topi Miettinen (https://github.com/topimiettinen)
|
||||
- netblue30 (netblue30@yahoo.com)
|
||||
|
||||
|
||||
|
|
@ -462,6 +463,8 @@ Topi Miettinen (https://github.com/topimiettinen)
|
|||
- improve mount handling, fix /run/user handling
|
||||
- /proc/sys can be nosuid,noexec,nodev
|
||||
- seccomp default list update
|
||||
- improve loading of seccomp filter and memory-deny-write-execute feature
|
||||
- private-lib feature
|
||||
valoq (https://github.com/valoq)
|
||||
- lots of profile fixes
|
||||
- added support for /srv in --whitelist feature
|
||||
|
|
|
|||
17
configure
vendored
17
configure
vendored
|
|
@ -676,6 +676,7 @@ infodir
|
|||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
|
|
@ -763,6 +764,7 @@ datadir='${datarootdir}'
|
|||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
|
|
@ -1015,6 +1017,15 @@ do
|
|||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
|
|
@ -1152,7 +1163,7 @@ fi
|
|||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir
|
||||
libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
|
|
@ -1305,6 +1316,7 @@ Fine tuning of the installation directories:
|
|||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
|
|
@ -3811,7 +3823,7 @@ if test "$prefix" = /usr; then
|
|||
sysconfdir="/etc"
|
||||
fi
|
||||
|
||||
ac_config_files="$ac_config_files Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
|
|
@ -4532,6 +4544,7 @@ do
|
|||
"src/ftee/Makefile") CONFIG_FILES="$CONFIG_FILES src/ftee/Makefile" ;;
|
||||
"src/faudit/Makefile") CONFIG_FILES="$CONFIG_FILES src/faudit/Makefile" ;;
|
||||
"src/fseccomp/Makefile") CONFIG_FILES="$CONFIG_FILES src/fseccomp/Makefile" ;;
|
||||
"src/fldd/Makefile") CONFIG_FILES="$CONFIG_FILES src/fldd/Makefile" ;;
|
||||
|
||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ fi
|
|||
|
||||
AC_OUTPUT(Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile \
|
||||
src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile \
|
||||
src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile)
|
||||
src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile)
|
||||
|
||||
echo
|
||||
echo "Configuration options:"
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#define RUN_BIN_DIR "/run/firejail/mnt/bin"
|
||||
#define RUN_PULSE_DIR "/run/firejail/mnt/pulse"
|
||||
#define RUN_LIB_DIR "/run/firejail/mnt/lib"
|
||||
#define RUN_LIB_FILE "/run/firejail/mnt/libfiles"
|
||||
|
||||
#define RUN_SECCOMP_PROTOCOL "/run/firejail/mnt/seccomp.protocol" // protocol filter
|
||||
#define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp" // configured filter
|
||||
|
|
@ -739,6 +740,7 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
|
|||
#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp")
|
||||
#define PATH_FCOPY (LIBDIR "/firejail/fcopy")
|
||||
#define SBOX_STDIN_FILE "/run/firejail/mnt/sbox_stdin"
|
||||
#define PATH_FLDD (LIBDIR "/firejail/fldd")
|
||||
|
||||
// bitmapped filters for sbox_run
|
||||
#define SBOX_ROOT (1 << 0) // run the sandbox as root
|
||||
|
|
|
|||
|
|
@ -18,156 +18,60 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include "firejail.h"
|
||||
#include <elf.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __LP64__
|
||||
#define Elf_Ehdr Elf64_Ehdr
|
||||
#define Elf_Phdr Elf64_Phdr
|
||||
#define Elf_Shdr Elf64_Shdr
|
||||
#define Elf_Dyn Elf64_Dyn
|
||||
#else
|
||||
#define Elf_Ehdr Elf32_Ehdr
|
||||
#define Elf_Phdr Elf32_Phdr
|
||||
#define Elf_Shdr Elf32_Shdr
|
||||
#define Elf_Dyn Elf32_Dyn
|
||||
#endif
|
||||
|
||||
static const char * const lib_paths[] = {
|
||||
"/lib",
|
||||
"/lib/x86_64-linux-gnu",
|
||||
"/lib64",
|
||||
"/usr/lib",
|
||||
"/usr/lib/x86_64-linux-gnu",
|
||||
LIBDIR,
|
||||
"/usr/local/lib",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void copy_libs_for_lib(const char *lib, const char *private_run_dir);
|
||||
|
||||
static void duplicate(const char *fname, const char *private_run_dir) {
|
||||
if (arg_debug)
|
||||
printf("copying %s to private %s\n", fname, private_run_dir);
|
||||
sbox_run(SBOX_ROOT| SBOX_SECCOMP, 4, PATH_FCOPY, "--follow-link", fname, private_run_dir);
|
||||
}
|
||||
|
||||
static void copy_libs_for_exe(const char *exe, const char *private_run_dir) {
|
||||
if (arg_debug)
|
||||
printf("copy libs for %s\n", exe);
|
||||
int f;
|
||||
f = open(exe, O_RDONLY);
|
||||
if (f < 0)
|
||||
return;
|
||||
struct stat s;
|
||||
char *base = NULL;
|
||||
if (fstat(f, &s) == -1)
|
||||
goto error_close;
|
||||
base = mmap(0, s.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, f, 0);
|
||||
if (base == MAP_FAILED)
|
||||
goto error_close;
|
||||
static void copy_libs(const char *exe, const char *dir, const char *file) {
|
||||
// create an empty RUN_LIB_FILE and allow the user to write to it
|
||||
unlink(file); // in case is there
|
||||
create_empty_file_as_root(file, 0644);
|
||||
if (chown(file, getuid(), getgid()))
|
||||
errExit("chown");
|
||||
|
||||
// run fldd to extact the list of file
|
||||
sbox_run(SBOX_USER | SBOX_SECCOMP | SBOX_CAPS_NONE, 3, PATH_FLDD, exe, file);
|
||||
|
||||
// open the list of libraries and install them on by one
|
||||
FILE *fp = fopen(file, "r");
|
||||
if (!fp)
|
||||
errExit("fopen");
|
||||
|
||||
Elf_Ehdr *ebuf = (Elf_Ehdr *)base;
|
||||
if (strncmp((const char *)ebuf->e_ident, ELFMAG, SELFMAG) != 0)
|
||||
goto close;
|
||||
|
||||
Elf_Phdr *pbuf = (Elf_Phdr *)(base + sizeof(*ebuf));
|
||||
while (ebuf->e_phnum-- > 0) {
|
||||
switch (pbuf->p_type) {
|
||||
case PT_INTERP:
|
||||
// dynamic loader ld-linux.so
|
||||
duplicate(base + pbuf->p_offset, private_run_dir);
|
||||
break;
|
||||
}
|
||||
pbuf++;
|
||||
#define MAXBUF 4096
|
||||
char buf[MAXBUF];
|
||||
while (fgets(buf, MAXBUF, fp)) {
|
||||
// remove \n
|
||||
char *ptr = strchr(buf, '\n');
|
||||
if (ptr)
|
||||
*ptr = '\0';
|
||||
duplicate(buf, dir);
|
||||
}
|
||||
|
||||
Elf_Shdr *sbuf = (Elf_Shdr *)(base + ebuf->e_shoff);
|
||||
|
||||
// Find strings section
|
||||
char *strbase = NULL;
|
||||
int sections = ebuf->e_shnum;
|
||||
while (sections-- > 0) {
|
||||
if (sbuf->sh_type == SHT_STRTAB) {
|
||||
strbase = base + sbuf->sh_offset;
|
||||
break;
|
||||
}
|
||||
sbuf++;
|
||||
}
|
||||
if (strbase == NULL)
|
||||
goto error_close;
|
||||
|
||||
// Find dynamic section
|
||||
sections = ebuf->e_shnum;
|
||||
while (sections-- > 0) {
|
||||
if (sbuf->sh_type == SHT_DYNAMIC) {
|
||||
// Find DT_NEEDED tags
|
||||
Elf_Dyn *dbuf = (Elf_Dyn *)(base + sbuf->sh_offset);
|
||||
while (sbuf->sh_size >= sizeof(*dbuf)) {
|
||||
if (dbuf->d_tag == DT_NEEDED) {
|
||||
const char *lib = strbase + dbuf->d_un.d_ptr;
|
||||
copy_libs_for_lib(lib, private_run_dir);
|
||||
}
|
||||
sbuf->sh_size -= sizeof(*dbuf);
|
||||
dbuf++;
|
||||
}
|
||||
}
|
||||
sbuf++;
|
||||
}
|
||||
goto close;
|
||||
|
||||
error_close:
|
||||
perror("copy libs");
|
||||
close:
|
||||
if (base)
|
||||
munmap(base, s.st_size);
|
||||
close(f);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void copy_libs_for_lib(const char *lib, const char *private_run_dir) {
|
||||
int i;
|
||||
for (i = 0; lib_paths[i]; i++) {
|
||||
char *fname;
|
||||
if (asprintf(&fname, "%s/%s", lib_paths[i], lib) == -1)
|
||||
errExit("asprintf");
|
||||
if (access(fname, R_OK) == 0) {
|
||||
char *dst;
|
||||
if (asprintf(&dst, "%s/%s", private_run_dir, lib) == -1)
|
||||
errExit("asprintf");
|
||||
|
||||
if (access(dst, R_OK) != 0) {
|
||||
duplicate(fname, private_run_dir);
|
||||
// libs may need other libs
|
||||
copy_libs_for_exe(fname, private_run_dir);
|
||||
}
|
||||
free(dst);
|
||||
free(fname);
|
||||
return;
|
||||
}
|
||||
free(fname);
|
||||
}
|
||||
errExit("library not found");
|
||||
}
|
||||
|
||||
void fs_private_lib(void) {
|
||||
char *private_list = cfg.lib_private_keep;
|
||||
// char *private_list = cfg.lib_private_keep;
|
||||
|
||||
// create /run/firejail/mnt/lib directory
|
||||
mkdir_attr(RUN_LIB_DIR, 0755, 0, 0);
|
||||
|
||||
// copy the libs in the new lib directory for the main exe
|
||||
if (cfg.original_program_index > 0)
|
||||
copy_libs_for_exe(cfg.original_argv[cfg.original_program_index], RUN_LIB_DIR);
|
||||
copy_libs(cfg.original_argv[cfg.original_program_index], RUN_LIB_DIR, RUN_LIB_FILE);
|
||||
|
||||
// for the shell
|
||||
if (!arg_shell_none)
|
||||
copy_libs_for_exe(cfg.shell, RUN_LIB_DIR);
|
||||
copy_libs(cfg.shell, RUN_LIB_DIR, RUN_LIB_FILE);
|
||||
|
||||
#if 0 // TODO - work in progress
|
||||
// for the listed libs
|
||||
if (private_list && *private_list != '\0') {
|
||||
if (arg_debug)
|
||||
|
|
@ -185,6 +89,7 @@ void fs_private_lib(void) {
|
|||
free(dlist);
|
||||
fs_logger_print();
|
||||
}
|
||||
#endif
|
||||
|
||||
// for our trace and tracelog libs
|
||||
if (arg_trace)
|
||||
|
|
@ -194,14 +99,17 @@ void fs_private_lib(void) {
|
|||
|
||||
if (arg_debug)
|
||||
printf("Mount-bind %s on top of /lib /lib64 /usr/lib\n", RUN_LIB_DIR);
|
||||
|
||||
if (mount(RUN_LIB_DIR, "/lib", NULL, MS_BIND|MS_REC, NULL) < 0 ||
|
||||
mount(NULL, "/lib", NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0)
|
||||
errExit("mount bind");
|
||||
fs_logger("mount /lib");
|
||||
|
||||
if (mount(RUN_LIB_DIR, "/lib64", NULL, MS_BIND|MS_REC, NULL) < 0 ||
|
||||
mount(NULL, "/lib64", NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0)
|
||||
errExit("mount bind");
|
||||
fs_logger("mount /lib64");
|
||||
|
||||
if (mount(RUN_LIB_DIR, "/usr/lib", NULL, MS_BIND|MS_REC, NULL) < 0 ||
|
||||
mount(NULL, "/usr/lib", NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0)
|
||||
errExit("mount bind");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue