Commit 280f37eb authored by netblue30's avatar netblue30

--build

parent 498bc172
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 src/fldd src/libpostexecseccomp
APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/fnet src/fseccomp src/fbuilder src/fcopy src/fldd src/libpostexecseccomp
MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5
SECCOMP_FILTERS = seccomp seccomp.debug seccomp.32 seccomp.64 seccomp.block_secondary seccomp.mdwx
......@@ -99,6 +99,7 @@ endif
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/.
install -c -m 0755 src/fbuilder/fbuilder $(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/.
......@@ -169,6 +170,7 @@ install-strip: all
strip src/fseccomp/fseccomp
strip src/fcopy/fcopy
strip src/fldd/fldd
strip src/fbuilder/fbuilder
$(MAKE) realinstall
uninstall:
......
......@@ -3823,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 src/fldd/Makefile src/libpostexecseccomp/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/fbuilder/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
......@@ -4541,6 +4541,7 @@ do
"src/libtrace/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtrace/Makefile" ;;
"src/libtracelog/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtracelog/Makefile" ;;
"src/firecfg/Makefile") CONFIG_FILES="$CONFIG_FILES src/firecfg/Makefile" ;;
"src/fbuilder/Makefile") CONFIG_FILES="$CONFIG_FILES src/fbuilder/Makefile" ;;
"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" ;;
......
......@@ -176,7 +176,7 @@ if test "$prefix" = /usr; then
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/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile \
src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile)
echo
......
......@@ -20,6 +20,7 @@ mkdir ~/.config/VirtualBox
mkdir ~/VirtualBox VMs
whitelist ~/.config/VirtualBox
whitelist ~/VirtualBox VMs
whitelist ${DOWNLOADS}
include /etc/firejail/whitelist-common.inc
caps.drop all
......
all: fbuilder
CC=@CC@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
sysconfdir=@sysconfdir@
VERSION=@PACKAGE_VERSION@
NAME=@PACKAGE_NAME@
HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
HAVE_SECCOMP=@HAVE_SECCOMP@
HAVE_CHROOT=@HAVE_CHROOT@
HAVE_BIND=@HAVE_BIND@
HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
HAVE_NETWORK=@HAVE_NETWORK@
HAVE_USERNS=@HAVE_USERNS@
HAVE_X11=@HAVE_X11@
HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
HAVE_WHITELIST=@HAVE_WHITELIST@
HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
HAVE_APPARMOR=@HAVE_APPARMOR@
HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
HAVE_GCOV=@HAVE_GCOV@
EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
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) -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
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
fbuilder: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
clean:; rm -f *.o fbuilder *.gcov *.gcda *.gcno
distclean: clean
rm -fr Makefile
/*
* Copyright (C) 2014-2017 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 "fbuilder.h"
// common file processing function, using the callback for each line in the file
static void process_file(const char *fname, const char *dir, void (*callback)(char *)) {
assert(fname);
assert(dir);
assert(callback);
int dir_len = strlen(dir);
// process trace file
FILE *fp = fopen(fname, "r");
if (!fp) {
fprintf(stderr, "Error: cannot open %s\n", fname);
exit(1);
}
char buf[MAX_BUF];
while (fgets(buf, MAX_BUF, fp)) {
// remove \n
char *ptr = strchr(buf, '\n');
if (ptr)
*ptr = '\0';
// parse line: 4:galculator:access /etc/fonts/conf.d:0
// number followed by :
ptr = buf;
if (!isdigit(*ptr))
continue;
while (isdigit(*ptr))
ptr++;
if (*ptr != ':')
continue;
ptr++;
// next :
ptr = strchr(ptr, ':');
if (!ptr)
continue;
ptr++;
if (strncmp(ptr, "access ", 7) == 0)
ptr += 7;
else if (strncmp(ptr, "fopen ", 6) == 0)
ptr += 6;
else if (strncmp(ptr, "fopen64 ", 8) == 0)
ptr += 8;
else if (strncmp(ptr, "open64 ", 7) == 0)
ptr += 7;
else if (strncmp(ptr, "open ", 5) == 0)
ptr += 5;
else
continue;
if (strncmp(ptr, dir, dir_len) != 0)
continue;
// end of filename
char *ptr2 = strchr(ptr, ':');
if (!ptr2)
continue;
*ptr2 = '\0';
callback(ptr);
}
fclose(fp);
}
// process fname, fname.1, fname.2, fname.3, fname.4, fname.5
static void process_files(const char *fname, const char *dir, void (*callback)(char *)) {
assert(fname);
assert(dir);
assert(callback);
// run fname
process_file(fname, dir, callback);
// run all the rest
struct stat s;
int i;
for (i = 1; i <= 5; i++) {
char *newname;
if (asprintf(&newname, "%s.%d", fname, i) == -1)
errExit("asprintf");
if (stat(newname, &s) == 0)
process_file(newname, dir, callback);
free(newname);
}
}
//*******************************************
// etc directory
//*******************************************
static FileDB *etc_out = NULL;
static void etc_callback(char *ptr) {
// skip firejail directory
if (strncmp(ptr, "/etc/firejail", 13) == 0)
return;
// add only top files and directories
ptr += 5; // skip "/etc/"
char *end = strchr(ptr, '/');
if (end)
*end = '\0';
etc_out = filedb_add(etc_out, ptr);
}
void build_etc(const char *fname) {
assert(fname);
process_files(fname, "/etc", etc_callback);
printf("private-etc ");
if (etc_out == NULL)
printf("none\n");
else {
FileDB *ptr = etc_out;
while (ptr) {
printf("%s,", ptr->fname);
ptr = ptr->next;
}
printf("\n");
}
}
//*******************************************
// var directory
//*******************************************
static FileDB *var_out = NULL;
static void var_callback(char *ptr) {
if (strncmp(ptr, "/var/lib/menu-xdg", 17) == 0)
var_out = filedb_add(var_out, "/var/lib/menu-xdg");
else if (strncmp(ptr, "/var/cache/fontconfig", 21) == 0)
var_out = filedb_add(var_out, "/var/cache/fontconfig");
else
var_out = filedb_add(var_out, ptr);
}
void build_var(const char *fname) {
assert(fname);
process_files(fname, "/var", var_callback);
if (var_out == NULL)
printf("blacklist /var\n");
else
filedb_print(var_out, "whitelist ");
}
//*******************************************
// tmp directory
//*******************************************
static FileDB *tmp_out = NULL;
static void tmp_callback(char *ptr) {
filedb_add(tmp_out, ptr);
}
void build_tmp(const char *fname) {
assert(fname);
process_files(fname, "/tmp", tmp_callback);
if (tmp_out == NULL)
printf("private-tmp\n");
else {
printf("\n");
printf("# private-tmp\n");
printf("# File accessed in /tmp directory:\n");
printf("# ");
FileDB *ptr = tmp_out;
while (ptr) {
printf("%s,", ptr->fname);
ptr = ptr->next;
}
printf("\n");
}
}
//*******************************************
// dev directory
//*******************************************
static char *dev_skip[] = {
"/dev/zero",
"/dev/null",
"/dev/full",
"/dev/random",
"/dev/urandom",
"/dev/tty",
"/dev/snd",
"/dev/dri",
"/dev/pts",
"/dev/nvidia0",
"/dev/nvidia1",
"/dev/nvidia2",
"/dev/nvidia3",
"/dev/nvidia4",
"/dev/nvidia5",
"/dev/nvidia6",
"/dev/nvidia7",
"/dev/nvidia8",
"/dev/nvidia9",
"/dev/nvidiactl",
"/dev/nvidia-modeset",
"/dev/nvidia-uvm",
"/dev/video0",
"/dev/video1",
"/dev/video2",
"/dev/video3",
"/dev/video4",
"/dev/video5",
"/dev/video6",
"/dev/video7",
"/dev/video8",
"/dev/video9",
"/dev/dvb",
"/dev/sr0",
NULL
};
static FileDB *dev_out = NULL;
static void dev_callback(char *ptr) {
// skip private-dev devices
int i = 0;
int found = 0;
while (dev_skip[i]) {
if (strcmp(ptr, dev_skip[i]) == 0) {
found = 1;
break;
}
i++;
}
if (!found)
filedb_add(dev_out, ptr);
}
void build_dev(const char *fname) {
assert(fname);
process_files(fname, "/tmp", tmp_callback);
if (dev_out == NULL)
printf("private-dev\n");
else {
printf("\n");
printf("# private-dev\n");
printf("# This is the list of devices accessed (on top of regular private-dev devices:\n");
printf("# ");
FileDB *ptr = dev_out;
while (ptr) {
printf("%s,", ptr->fname);
ptr = ptr->next;
}
printf("\n");
}
}
/*
* Copyright (C) 2014-2017 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 "fbuilder.h"
static FileDB *db_skip = NULL;
static FileDB *db_out = NULL;
static void load_whitelist_common(void) {
FILE *fp = fopen("/etc/firejail/whitelist-common.inc", "r");
if (!fp) {
fprintf(stderr, "Error: cannot open whitelist-common.inc\n");
exit(1);
}
char buf[MAX_BUF];
while (fgets(buf, MAX_BUF, fp)) {
if (strncmp(buf, "whitelist ~/", 12) != 0)
continue;
char *fn = buf + 12;
char *ptr = strchr(buf, '\n');
if (!ptr)
continue;
*ptr = '\0';
// add the file to skip list
db_skip = filedb_add(db_skip, fn);
}
fclose(fp);
}
void process_home(const char *fname, char *home, int home_len) {
assert(fname);
assert(home);
assert(home_len);
// process trace file
FILE *fp = fopen(fname, "r");
if (!fp) {
fprintf(stderr, "Error: cannot open %s\n", fname);
exit(1);
}
char buf[MAX_BUF];
while (fgets(buf, MAX_BUF, fp)) {
// remove \n
char *ptr = strchr(buf, '\n');
if (ptr)
*ptr = '\0';
// parse line: 4:galculator:access /etc/fonts/conf.d:0
// number followed by :
ptr = buf;
if (!isdigit(*ptr))
continue;
while (isdigit(*ptr))
ptr++;
if (*ptr != ':')
continue;
ptr++;
// next :
ptr = strchr(ptr, ':');
if (!ptr)
continue;
ptr++;
if (strncmp(ptr, "access /home", 12) == 0)
ptr += 7;
else if (strncmp(ptr, "fopen /home", 11) == 0)
ptr += 6;
else if (strncmp(ptr, "fopen64 /home", 13) == 0)
ptr += 8;
else if (strncmp(ptr, "open64 /home", 12) == 0)
ptr += 7;
else if (strncmp(ptr, "open /home", 10) == 0)
ptr += 5;
else
continue;
// end of filename
char *ptr2 = strchr(ptr, ':');
if (!ptr2)
continue;
*ptr2 = '\0';
// check home directory
if (strncmp(ptr, home, home_len) != 0)
continue;
if (strcmp(ptr, home) == 0)
continue;
ptr += home_len + 1;
// skip files handled automatically by firejail
if (strcmp(ptr, ".Xauthority") == 0 ||
strcmp(ptr, ".Xdefaults-debian") == 0 ||
strncmp(ptr, ".config/pulse/", 13) == 0 ||
strncmp(ptr, ".pulse/", 7) == 0 ||
strncmp(ptr, ".bash_hist", 10) == 0 ||
strcmp(ptr, ".bashrc") == 0)
continue;
// try to find the relevant directory for this file
char *dir = extract_dir(ptr);
char *toadd = (dir)? dir: ptr;
// skip some dot directories
if (strcmp(toadd, ".config") == 0 ||
strcmp(toadd, ".local") == 0 ||
strcmp(toadd, ".local/share") == 0 ||
strcmp(toadd, ".cache") == 0) {
if (dir)
free(dir);
continue;
}
// clean .cache entries
if (strncmp(toadd, ".cache/", 7) == 0) {
char *ptr2 = toadd + 7;
ptr2 = strchr(ptr2, '/');
if (ptr2)
*ptr2 = '\0';
}
// skip files and directories in whitelist-common.inc
if (filedb_find(db_skip, toadd)) {
if (dir)
free(dir);
continue;
}
// add the file to out list
db_out = filedb_add(db_out, toadd);
if (dir)
free(dir);
}
fclose(fp);
}
// process fname, fname.1, fname.2, fname.3, fname.4, fname.5
void build_home(const char *fname) {
assert(fname);
// load whitelist common
load_whitelist_common();
// find user home directory
struct passwd *pw = getpwuid(getuid());
if (!pw)
errExit("getpwuid");
char *home = pw->pw_dir;
if (!home)
errExit("getpwuid");
int home_len = strlen(home);
// run fname
process_home(fname, home, home_len);
// run all the rest
struct stat s;
int i;
for (i = 1; i <= 5; i++) {
char *newname;
if (asprintf(&newname, "%s.%d", fname, i) == -1)
errExit("asprintf");
if (stat(newname, &s) == 0)
process_home(newname, home, home_len);
free(newname);
}
// print the out list if any
if (db_out) {
filedb_print(db_out, "whitelist ~/");
printf("include /etc/firejail/whitelist-common.inc\n");
}
else
printf("private\n");
}
\ No newline at end of file
/*
* Copyright (C) 2014-2017 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 "fbuilder.h"
#include <sys/wait.h>
#include <fcntl.h>
#define TRACE_OUTPUT "/tmp/firejail-trace"
#define STRACE_OUTPUT "/tmp/firejail-strace"
static char *cmdlist[] = {
"/usr/bin/firejail",
"--quiet",
"--output=" TRACE_OUTPUT,
"--noprofile",
"--caps.drop=all",
"--nonewprivs",
"--trace",
"/usr/bin/strace", // also used as a marker in build_profile()
"-c",
"-f",
"-o" STRACE_OUTPUT,
};
static void clear_tmp_files(void) {
unlink(STRACE_OUTPUT);
unlink(TRACE_OUTPUT);
// run all the rest
int i;
for (i = 1; i <= 5; i++) {
char *newname;
if (asprintf(&newname, "%s.%d", TRACE_OUTPUT, i) == -1)
errExit("asprintf");
unlink(newname);
free(newname);
}
}
void build_profile(int argc, char **argv, int index) {
unlink("/tmp/strace-output");
// next index is the application name
if (index >= argc) {
fprintf(stderr, "Error: application name missing\n");
exit(1);
}
// clean /tmp files
clear_tmp_files();
// detect strace
int have_strace = 0;
if (access("/usr/bin/strace", X_OK) == 0)
have_strace = 1;
// calculate command length
int len = (int) sizeof(cmdlist) / sizeof(char*) + argc - index + 1;
if (arg_debug)
printf("command len %d + %d + 1\n", (int) (sizeof(cmdlist) / sizeof(char*)), argc - index);
char *cmd[len];
// build command
int i = 0;
for (i = 0; i < (int) sizeof(cmdlist) / sizeof(char*); i++) {
// skip strace if not installed
if (have_strace == 0 && strcmp(cmdlist[i], "/usr/bin/strace") == 0)
break;
cmd[i] = cmdlist[i];
}
int i2 = index;
for (; i < (len - 1); i++, i2++)
cmd[i] = argv[i2];
cmd[i] = NULL;
if (arg_debug) {
for (i = 0; i < len; i++)
printf("\t%s\n", cmd[i]);
}
// fork and execute
pid_t child = fork();
if (child == -1)
errExit("fork");
if (child == 0) {
int rv = execvp(cmd[0], cmd);
errExit("execv");
}
// wait for all processes to finish
int status;
if (waitpid(child, &status, 0) != child)
errExit("waitpid");
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
printf("\n\n\n");
printf("############################################\n");
printf("# %s profile\n", argv[index]);
printf("############################################\n");
printf("# Persistent global definitions\n");
printf("# include /etc/firejail/globals.local\n");
printf("\n");
printf("### basic blacklisting\n");
printf("include /etc/firejail/disable-common.inc\n");
printf("# include /etc/firejail/disable-devel.inc\n");
printf("include /etc/firejail/disable-passwdmgr.inc\n");
printf("# include /etc/firejail/disable-programs.inc\n");
printf("\n");
printf("### home directory whitelisting\n");
build_home(TRACE_OUTPUT);
printf("\n");
printf("### filesystem\n");
build_tmp(TRACE_OUTPUT);
build_dev(TRACE_OUTPUT);
build_etc(TRACE_OUTPUT);
build_var(TRACE_OUTPUT);
printf("\n");
printf("### security filters\n");
printf("caps.drop all\n");
printf("nonewprivs\n");
printf("seccomp\n");
if (have_strace)
build_seccomp(STRACE_OUTPUT);
else {
printf("# If you install strace on your system, Firejail will also create a\n");
printf("# whitelisted seccomp filter.\n");
}
printf("\n");
printf("### network\n");
build_protocol(TRACE_OUTPUT);
printf("\n");
printf("### environment\n");
printf("shell none\n");