Skip to content

Commit

Permalink
private-lib bug: 32 bit libraries being copied instead of 64 bit vers…
Browse files Browse the repository at this point in the history
…ions; splitting common code for firejail and fldd in a common static library
  • Loading branch information
startx2017 committed Mar 12, 2018
1 parent 2e17082 commit 14b5746
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 60 deletions.
4 changes: 2 additions & 2 deletions src/firejail/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/pid.h ../include/seccomp.h ../include/syscall.h
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@

firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o
$(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS)
firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o ../lib/ldd_utils.o
$(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/ldd_utils.o $(LIBS) $(EXTRA_LDFLAGS)

clean:; rm -f *.o firejail firejail.1 firejail.1.gz *.gcov *.gcda *.gcno

Expand Down
47 changes: 27 additions & 20 deletions src/firejail/fs_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,14 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "firejail.h"
#include "../include/ldd_utils.h"
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#define MAXBUF 4096

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
}; // Note: this array is duplicated in src/fldd/main.c

extern void fslib_install_stdc(void);
extern void fslib_install_system(void);

Expand All @@ -47,9 +37,9 @@ static void report_duplication(const char *full_path) {
if (fname && *(++fname) != '\0') {
// report the file on all bin paths
int i = 0;
while (lib_paths[i]) {
while (default_lib_paths[i]) {
char *p;
if (asprintf(&p, "%s/%s", lib_paths[i], fname) == -1)
if (asprintf(&p, "%s/%s", default_lib_paths[i], fname) == -1)
errExit("asprintf");
fs_logger2("clone", p);
free(p);
Expand Down Expand Up @@ -194,19 +184,24 @@ static char *valid_file(const char *lib) {

// find the library
int i;
for (i = 0; lib_paths[i]; i++) {
for (i = 0; default_lib_paths[i]; i++) {
char *fname;
if (asprintf(&fname, "%s/%s", lib_paths[i], lib) == -1)
if (asprintf(&fname, "%s/%s", default_lib_paths[i], lib) == -1)
errExit("asprintf");

// existing file owned by root, read access
struct stat s;
if (stat(fname, &s) == 0 && s.st_uid == 0 && !access(fname, R_OK)) {
return fname;
if (is_dir(fname))
return fname;
// for regular libraries check if it is 64bit
if (is_lib_64(fname))
return fname;
// if not 64bit, continue searching
}
free(fname);
}

printf("not found %s\n", lib);
fwarning("%s library not found, skipping...\n", lib);
return NULL;
}
Expand Down Expand Up @@ -268,25 +263,33 @@ void fs_private_lib(void) {
mkdir_attr(RUN_LIB_DIR, 0755, 0, 0);

// install standard C libraries
if (arg_debug || arg_debug_private_lib)
printf("*** Installing standard C library\n");
fslib_install_stdc();

// start timetrace
timetrace_start();

// copy the libs in the new lib directory for the main exe
if (cfg.original_program_index > 0)
if (cfg.original_program_index > 0) {
if (arg_debug || arg_debug_private_lib)
printf("*** Installing sandboxed program libraries\n");
fslib_copy_libs(cfg.original_argv[cfg.original_program_index]);
}

// for the shell
if (!arg_shell_none) {
if (arg_debug || arg_debug_private_lib)
printf("*** Installing shell libraries\n");
fslib_copy_libs(cfg.shell);
// a shell is useless without ls command
fslib_copy_libs("/bin/ls");
}

// for the listed libs
// for the listed libs and directories
if (private_list && *private_list != '\0') {
if (arg_debug || arg_debug_private_lib)
printf("Copying extra files (%s) in the new lib directory\n", private_list);
printf("*** Processing private-lib files (%s)\n", private_list);

char *dlist = strdup(private_list);
if (!dlist)
Expand Down Expand Up @@ -322,6 +325,8 @@ void fs_private_lib(void) {

// for private-bin files
if (arg_private_bin) {
if (arg_debug || arg_debug_private_lib)
printf("*** Processing private-bin files\n");
FILE *fp = fopen(RUN_LIB_BIN, "r");
if (fp) {
char buf[MAXBUF];
Expand Down Expand Up @@ -368,6 +373,8 @@ void fs_private_lib(void) {
fmessage("Program libraries installed in %0.2f ms\n", timetrace_end());

// install the reset of the system libraries
if (arg_debug || arg_debug_private_lib)
printf("*** Installing system libraries\n");
fslib_install_system();

fmessage("Installed %d libraries and %d directories\n", lib_cnt, dir_cnt);
Expand Down
6 changes: 3 additions & 3 deletions src/fldd/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ BINOBJS = $(foreach file, $(OBJS), $file)
CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread

%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h
%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h ../include/ldd_utils.h
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@

fldd: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
fldd: $(OBJS) ../lib/ldd_utils.o
$(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/ldd_utils.o $(LIBS) $(EXTRA_LDFLAGS)

clean:; rm -f *.o fldd *.gcov *.gcda *.gcno

Expand Down
55 changes: 21 additions & 34 deletions src/fldd/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
*/

#include "../include/common.h"
#include "../include/ldd_utils.h"

#include <elf.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/mount.h>
Expand All @@ -29,36 +29,10 @@
#include <unistd.h>
#include <dirent.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 int arg_quiet = 0;
static void copy_libs_for_lib(const char *lib);

static const char * const default_lib_paths[] = {
"/lib",
"/lib/x86_64-linux-gnu",
"/lib64",
"/usr/lib",
"/usr/lib/x86_64-linux-gnu",
LIBDIR,
"/usr/local/lib",
"/usr/lib/x86_64-linux-gnu/mesa", // libGL.so is sometimes a symlink into this directory
"/usr/lib/x86_64-linux-gnu/mesa-egl", // libGL.so is sometimes a symlink into this directory
// "/usr/lib/x86_64-linux-gnu/plasma-discover",
NULL
};


typedef struct storage_t {
struct storage_t *next;
const char *name;
Expand Down Expand Up @@ -107,7 +81,8 @@ static bool ptr_ok(const void *ptr, const void *base, const void *end, const cha
return r;
}

static void copy_libs_for_exe(const char *exe) {

static void parse_elf(const char *exe) {
int f;
f = open(exe, O_RDONLY);
if (f < 0) {
Expand All @@ -132,6 +107,12 @@ static void copy_libs_for_exe(const char *exe) {
fprintf(stderr, "Warning fldd: %s is not an ELF executable or library\n", exe);
goto close;
}
//unsigned char elfclass = ebuf->e_ident[EI_CLASS];
//if (elfclass == ELFCLASS32)
//printf("%s 32bit\n", exe);
//else if (elfclass == ELFCLASS64)
//printf("%s 64bit\n", exe);


Elf_Phdr *pbuf = (Elf_Phdr *)(base + sizeof(*ebuf));
while (ebuf->e_phnum-- > 0 && ptr_ok(pbuf, base, end, "pbuf")) {
Expand Down Expand Up @@ -227,11 +208,11 @@ static void copy_libs_for_lib(const char *lib) {
char *fname;
if (asprintf(&fname, "%s/%s", lib_path->name, lib) == -1)
errExit("asprintf");
if (access(fname, R_OK) == 0) {
if (access(fname, R_OK) == 0 && is_lib_64(fname)) {
if (!storage_find(libs, fname)) {
storage_add(&libs, fname);
// libs may need other libs
copy_libs_for_exe(fname);
parse_elf(fname);
}
free(fname);
return;
Expand Down Expand Up @@ -270,9 +251,9 @@ static void walk_directory(const char *dirname) {

// check regular so library
char *ptr = strstr(entry->d_name, ".so");
if (ptr) {
if (ptr && is_lib_64(path)) {
if (*(ptr + 3) == '\0' || *(ptr + 3) == '.') {
copy_libs_for_exe(path);
parse_elf(path);
free(path);
continue;
}
Expand Down Expand Up @@ -356,8 +337,14 @@ printf("\n");
errExit("stat");
if (S_ISDIR(s.st_mode))
walk_directory(argv[1]);
else
copy_libs_for_exe(argv[1]);
else {
if (is_lib_64(argv[1]))
parse_elf(argv[1]);
else {
fprintf(stderr, "Error fldd: %s is not a 64bit program/library\n", argv[1]);
exit(1);
}
}


// print libraries and exit
Expand Down
46 changes: 46 additions & 0 deletions src/include/ldd_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2014-2018 Firejail Authors
*
* This file is part of firejail project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#ifndef LDD_UTILS_H
#define LDD_UTILS_H

#include "../include/common.h"
#include <elf.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

extern const char * const default_lib_paths[];

// return 1 if this is a 64 bit program/library
int is_lib_64(const char *exe);



#endif
2 changes: 1 addition & 1 deletion src/lib/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ H_FILE_LIST = $(sort $(wildcard *.[h]))
C_FILE_LIST = $(sort $(wildcard *.c))
OBJS = $(C_FILE_LIST:.c=.o)
BINOBJS = $(foreach file, $(OBJS), $file)
CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security
CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DLIBDIR='"$(libdir)"' $(HAVE_GCOV) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security
LDFLAGS:=-pic -Wl,-z,relro -Wl,-z,now

all: $(OBJS)
Expand Down
62 changes: 62 additions & 0 deletions src/lib/ldd_utils.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2014-2018 Firejail Authors
*
* This file is part of firejail project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "../include/ldd_utils.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

const char * const default_lib_paths[] = {
"/lib",
"/lib/x86_64-linux-gnu",
"/lib64",
"/usr/lib",
"/usr/lib/x86_64-linux-gnu",
LIBDIR,
"/usr/local/lib",
"/usr/lib/x86_64-linux-gnu/mesa", // libGL.so is sometimes a symlink into this directory
"/usr/lib/x86_64-linux-gnu/mesa-egl", // libGL.so is sometimes a symlink into this directory
// "/usr/lib/x86_64-linux-gnu/plasma-discover",
NULL
};

// return 1 if this is a 64 bit program/library
int is_lib_64(const char *exe) {
int retval = 0;
int fd = open(exe, O_RDONLY);
if (fd < 0)
return 0;

unsigned char buf[EI_NIDENT];
ssize_t len = 0;
while (len < EI_NIDENT) {
ssize_t sz = read(fd, buf, EI_NIDENT);
if (sz <= 0)
goto doexit;
len += sz;
}

if (buf[EI_CLASS] == ELFCLASS64)
retval = 1;

doexit:
close(fd);
return retval;
}

0 comments on commit 14b5746

Please sign in to comment.