From b0f49116fb026fe08fc30c495c637c42ed3195ad Mon Sep 17 00:00:00 2001 From: ಚಿರಾಗ್ ನಟರಾಜ್ Date: Thu, 16 Aug 2018 09:42:58 -0400 Subject: Generate temporary filenames instead of using a fixed one (fixes #2083) --- src/fbuilder/build_bin.c | 36 ++++++++++------ src/fbuilder/build_fs.c | 100 +++++++++++++++++++++++++------------------ src/fbuilder/build_home.c | 37 +++++++++------- src/fbuilder/build_profile.c | 99 +++++++++++++++++++++++++++++------------- src/fbuilder/build_seccomp.c | 22 ++++++---- src/fbuilder/fbuilder.h | 21 ++++----- 6 files changed, 197 insertions(+), 118 deletions(-) diff --git a/src/fbuilder/build_bin.c b/src/fbuilder/build_bin.c index 1230fb780..602610750 100644 --- a/src/fbuilder/build_bin.c +++ b/src/fbuilder/build_bin.c @@ -21,15 +21,16 @@ static FileDB *bin_out = NULL; -static void process_bin(const char *fname) { +static void process_bin(char *fname, FILE *fp) { assert(fname); + assert(fp); // process trace file - FILE *fp = fopen(fname, "r"); - if (!fp) { - fprintf(stderr, "Error: cannot open %s\n", fname); - exit(1); - } + /* FILE *fp = fdopen(fd, "r"); */ + /* if (!fp) { */ + /* fprintf(stderr, "Error: cannot open %s\n", fname); */ + /* exit(1); */ + /* } */ char buf[MAX_BUF]; while (fgets(buf, MAX_BUF, fp)) { @@ -90,16 +91,18 @@ static void process_bin(const char *fname) { bin_out = filedb_add(bin_out, ptr); } - fclose(fp); + /* fclose(fp); */ } // process fname, fname.1, fname.2, fname.3, fname.4, fname.5 -void build_bin(const char *fname, FILE *fp) { +void build_bin(char *fname, FILE *fp, FILE *fpo) { assert(fname); + assert(fp); + assert(fpo); // run fname - process_bin(fname); + process_bin(fname, fp); // run all the rest struct stat s; @@ -109,18 +112,23 @@ void build_bin(const char *fname, FILE *fp) { if (asprintf(&newname, "%s.%d", fname, i) == -1) errExit("asprintf"); if (stat(newname, &s) == 0) - process_bin(newname); + { + int nfd = open(newname, O_RDONLY); + FILE *nfp = fdopen(nfd, "r"); + process_bin(newname, nfp); + fclose(nfp); + } free(newname); } if (bin_out) { - fprintf(fp, "private-bin "); + fprintf(fpo, "private-bin "); FileDB *ptr = bin_out; while (ptr) { - fprintf(fp, "%s,", ptr->fname); + fprintf(fpo, "%s,", ptr->fname); ptr = ptr->next; } - fprintf(fp, "\n"); - fprintf(fp, "# private-lib\n"); + fprintf(fpo, "\n"); + fprintf(fpo, "# private-lib\n"); } } diff --git a/src/fbuilder/build_fs.c b/src/fbuilder/build_fs.c index 771dc94cb..5ef47979e 100644 --- a/src/fbuilder/build_fs.c +++ b/src/fbuilder/build_fs.c @@ -21,19 +21,20 @@ #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 *)) { +static void process_file(char *fname, FILE *fp, const char *dir, void (*callback)(char *)) { assert(fname); + assert(fp); 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); - } + /* FILE *fp = fdopen(fd, "r"); */ + /* if (!fp) { */ + /* fprintf(stderr, "Error: cannot open %s\n", fname); */ + /* exit(1); */ + /* } */ char buf[MAX_BUF]; while (fgets(buf, MAX_BUF, fp)) { @@ -82,17 +83,18 @@ static void process_file(const char *fname, const char *dir, void (*callback)(ch callback(ptr); } - fclose(fp); + /* 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 *)) { +static void process_files(char *fname, FILE *fp, const char *dir, void (*callback)(char *)) { assert(fname); + assert(fp); assert(dir); assert(callback); // run fname - process_file(fname, dir, callback); + process_file(fname, fp, dir, callback); // run all the rest struct stat s; @@ -101,8 +103,12 @@ static void process_files(const char *fname, const char *dir, void (*callback)(c char *newname; if (asprintf(&newname, "%s.%d", fname, i) == -1) errExit("asprintf"); - if (stat(newname, &s) == 0) - process_file(newname, dir, callback); + if (stat(newname, &s) == 0) { + int nfd = open(newname, O_RDONLY); + FILE *nfp = fdopen(nfd, "r"); + process_file(newname, nfp, dir, callback); + fclose(nfp); + } free(newname); } } @@ -125,21 +131,23 @@ static void etc_callback(char *ptr) { etc_out = filedb_add(etc_out, ptr); } -void build_etc(const char *fname, FILE *fp) { +void build_etc(char *fname, FILE *fp, FILE *fpo) { assert(fname); + assert(fp); + assert(fpo); - process_files(fname, "/etc", etc_callback); + process_files(fname, fp, "/etc", etc_callback); - fprintf(fp, "private-etc "); + fprintf(fpo, "private-etc "); if (etc_out == NULL) - fprintf(fp, "none\n"); + fprintf(fpo, "none\n"); else { FileDB *ptr = etc_out; while (ptr) { - fprintf(fp, "%s,", ptr->fname); + fprintf(fpo, "%s,", ptr->fname); ptr = ptr->next; } - fprintf(fp, "\n"); + fprintf(fpo, "\n"); } } @@ -160,15 +168,17 @@ static void var_callback(char *ptr) { var_out = filedb_add(var_out, ptr); } -void build_var(const char *fname, FILE *fp) { +void build_var(char *fname, FILE *fp, FILE *fpo) { assert(fname); + assert(fp); + assert(fpo); - process_files(fname, "/var", var_callback); + process_files(fname, fp, "/var", var_callback); if (var_out == NULL) - fprintf(fp, "blacklist /var\n"); + fprintf(fpo, "blacklist /var\n"); else - filedb_print(var_out, "whitelist ", fp); + filedb_print(var_out, "whitelist ", fpo); } @@ -197,15 +207,17 @@ static void share_callback(char *ptr) { share_out = filedb_add(share_out, ptr); } -void build_share(const char *fname, FILE *fp) { +void build_share(char *fname, FILE *fp, FILE *fpo) { assert(fname); + assert(fp); + assert(fpo); - process_files(fname, "/usr/share", share_callback); + process_files(fname, fp, "/usr/share", share_callback); if (share_out == NULL) - fprintf(fp, "blacklist /usr/share\n"); + fprintf(fpo, "blacklist /usr/share\n"); else - filedb_print(share_out, "whitelist ", fp); + filedb_print(share_out, "whitelist ", fpo); } //******************************************* @@ -216,21 +228,23 @@ static void tmp_callback(char *ptr) { filedb_add(tmp_out, ptr); } -void build_tmp(const char *fname, FILE *fp) { +void build_tmp(char *fname, FILE *fp, FILE *fpo) { assert(fname); + assert(fp); + assert(fpo); - process_files(fname, "/tmp", tmp_callback); + process_files(fname, fp, "/tmp", tmp_callback); if (tmp_out == NULL) - fprintf(fp, "private-tmp\n"); + fprintf(fpo, "private-tmp\n"); else { - fprintf(fp, "\n"); - fprintf(fp, "# private-tmp\n"); - fprintf(fp, "# File accessed in /tmp directory:\n"); - fprintf(fp, "# "); + fprintf(fpo, "\n"); + fprintf(fpo, "# private-tmp\n"); + fprintf(fpo, "# File accessed in /tmp directory:\n"); + fprintf(fpo, "# "); FileDB *ptr = tmp_out; while (ptr) { - fprintf(fp, "%s,", ptr->fname); + fprintf(fpo, "%s,", ptr->fname); ptr = ptr->next; } printf("\n"); @@ -294,24 +308,26 @@ static void dev_callback(char *ptr) { filedb_add(dev_out, ptr); } -void build_dev(const char *fname, FILE *fp) { +void build_dev(char *fname, FILE *fp, FILE *fpo) { assert(fname); + assert(fp); + assert(fpo); - process_files(fname, "/dev", dev_callback); + process_files(fname, fp, "/dev", dev_callback); if (dev_out == NULL) - fprintf(fp, "private-dev\n"); + fprintf(fpo, "private-dev\n"); else { - fprintf(fp, "\n"); - fprintf(fp, "# private-dev\n"); - fprintf(fp, "# This is the list of devices accessed (on top of regular private-dev devices:\n"); - fprintf(fp, "# "); + fprintf(fpo, "\n"); + fprintf(fpo, "# private-dev\n"); + fprintf(fpo, "# This is the list of devices accessed (on top of regular private-dev devices:\n"); + fprintf(fpo, "# "); FileDB *ptr = dev_out; while (ptr) { - fprintf(fp, "%s,", ptr->fname); + fprintf(fpo, "%s,", ptr->fname); ptr = ptr->next; } - fprintf(fp, "\n"); + fprintf(fpo, "\n"); } } diff --git a/src/fbuilder/build_home.c b/src/fbuilder/build_home.c index 7470a8d10..d97b6b33a 100644 --- a/src/fbuilder/build_home.c +++ b/src/fbuilder/build_home.c @@ -47,17 +47,18 @@ static void load_whitelist_common(void) { fclose(fp); } -void process_home(const char *fname, char *home, int home_len) { +void process_home(char *fname, FILE *fp, char *home, int home_len) { assert(fname); + assert(fp); 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); - } + /* FILE *fp = fdopen(fd, "r"); */ + /* if (!fp) { */ + /* fprintf(stderr, "Error: cannot open %s\n", fname); */ + /* exit(1); */ + /* } */ char buf[MAX_BUF]; while (fgets(buf, MAX_BUF, fp)) { @@ -153,13 +154,15 @@ void process_home(const char *fname, char *home, int home_len) { free(dir); } - fclose(fp); + /* fclose(fp); */ } // process fname, fname.1, fname.2, fname.3, fname.4, fname.5 -void build_home(const char *fname, FILE *fp) { +void build_home(char *fname, FILE *fp, FILE *fpo) { assert(fname); + assert(fp); + assert(fpo); // load whitelist common load_whitelist_common(); @@ -174,7 +177,7 @@ void build_home(const char *fname, FILE *fp) { int home_len = strlen(home); // run fname - process_home(fname, home, home_len); + process_home(fname, fp, home, home_len); // run all the rest struct stat s; @@ -183,17 +186,21 @@ void build_home(const char *fname, FILE *fp) { char *newname; if (asprintf(&newname, "%s.%d", fname, i) == -1) errExit("asprintf"); - if (stat(newname, &s) == 0) - process_home(newname, home, home_len); + if (stat(newname, &s) == 0) { + int nfd = open(newname, O_RDONLY); + FILE *nfp = fdopen(nfd, "r"); + process_home(newname, nfp, home, home_len); + fclose(nfp); + } free(newname); } // print the out list if any if (db_out) { - filedb_print(db_out, "whitelist ~/", fp); - fprintf(fp, "include /etc/firejail/whitelist-common.inc\n"); + filedb_print(db_out, "whitelist ~/", fpo); + fprintf(fpo, "include /etc/firejail/whitelist-common.inc\n"); } else - fprintf(fp, "private\n"); + fprintf(fpo, "private\n"); -} \ No newline at end of file +} diff --git a/src/fbuilder/build_profile.c b/src/fbuilder/build_profile.c index 125487c41..0c65d3413 100644 --- a/src/fbuilder/build_profile.c +++ b/src/fbuilder/build_profile.c @@ -20,25 +20,24 @@ #include "fbuilder.h" #include -#include - -#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", - "--shell=none", - "/usr/bin/strace", // also used as a marker in build_profile() - "-c", - "-f", - "-o" STRACE_OUTPUT, -}; + +#define TRACE_OUTPUT "/tmp/firejail-trace.XXXXXX" +#define STRACE_OUTPUT "/tmp/firejail-strace.XXXXXX" + +/* static char *cmdlist[] = { */ +/* "/usr/bin/firejail", */ +/* "--quiet", */ +/* "--output=" TRACE_OUTPUT, */ +/* "--noprofile", */ +/* "--caps.drop=all", */ +/* "--nonewprivs", */ +/* "--trace", */ +/* "--shell=none", */ +/* "/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); @@ -64,7 +63,47 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { } // clean /tmp files - clear_tmp_files(); + /* clear_tmp_files(); */ + + char trace_output[] = "/tmp/firejail-trace.XXXXXX"; + char strace_output[] = "/tmp/firejail-strace.XXXXXX"; + + int tfile = mkstemp(trace_output); + int stfile = mkstemp(strace_output); + + if(tfile == -1 || stfile == -1) + errExit("mkstemp"); + + FILE *tp = fdopen(tfile, "r"); + + if (!tp) { + fprintf(stderr, "Error: cannot open %s\n", trace_output); + exit(1); + } + + char *output; + char *stroutput; + + if(asprintf(&output,"--output=%s",trace_output) == -1) + errExit("asprintf"); + + if(asprintf(&stroutput,"-o %s",strace_output) == -1) + errExit("asprintf"); + + char *cmdlist[] = { + "/usr/bin/firejail", + "--quiet", + output, + "--noprofile", + "--caps.drop=all", + "--nonewprivs", + "--trace", + "--shell=none", + "/usr/bin/strace", // also used as a marker in build_profile() + "-c", + "-f", + stroutput, + }; // detect strace int have_strace = 0; @@ -131,16 +170,16 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { fprintf(fp, "\n"); fprintf(fp, "### home directory whitelisting\n"); - build_home(TRACE_OUTPUT, fp); + build_home(trace_output, tp, fp); fprintf(fp, "\n"); fprintf(fp, "### filesystem\n"); - build_tmp(TRACE_OUTPUT, fp); - build_dev(TRACE_OUTPUT, fp); - build_etc(TRACE_OUTPUT, fp); - build_var(TRACE_OUTPUT, fp); - build_bin(TRACE_OUTPUT, fp); - build_share(TRACE_OUTPUT, fp); + build_tmp(trace_output, tp, fp); + build_dev(trace_output, tp, fp); + build_etc(trace_output, tp, fp); + build_var(trace_output, tp, fp); + build_bin(trace_output, tp, fp); + build_share(trace_output, tp, fp); fprintf(fp, "\n"); fprintf(fp, "### security filters\n"); @@ -148,7 +187,7 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { fprintf(fp, "nonewprivs\n"); fprintf(fp, "seccomp\n"); if (have_strace) - build_seccomp(STRACE_OUTPUT, fp); + build_seccomp(strace_output, stfile, fp); else { fprintf(fp, "# If you install strace on your system, Firejail will also create a\n"); fprintf(fp, "# whitelisted seccomp filter.\n"); @@ -156,11 +195,13 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { fprintf(fp, "\n"); fprintf(fp, "### network\n"); - build_protocol(TRACE_OUTPUT, fp); + build_protocol(trace_output, tfile, fp); fprintf(fp, "\n"); fprintf(fp, "### environment\n"); fprintf(fp, "shell none\n"); + + fclose(tp); } else { diff --git a/src/fbuilder/build_seccomp.c b/src/fbuilder/build_seccomp.c index fbc0e06f4..f275caf80 100644 --- a/src/fbuilder/build_seccomp.c +++ b/src/fbuilder/build_seccomp.c @@ -20,11 +20,12 @@ #include "fbuilder.h" -void build_seccomp(const char *fname, FILE *fp) { +void build_seccomp(char *fname, int fd, FILE *fp) { assert(fname); + assert(fd); assert(fp); - FILE *fp2 = fopen(fname, "r"); + FILE *fp2 = fdopen(fd, "r"); if (!fp2) { fprintf(stderr, "Error: cannot open %s\n", fname); exit(1); @@ -87,11 +88,12 @@ int inet = 0; int inet6 = 0; int netlink = 0; int packet = 0; -static void process_protocol(const char *fname) { +static void process_protocol(char *fname, int fd) { assert(fname); + assert(fd); // process trace file - FILE *fp = fopen(fname, "r"); + FILE *fp = fdopen(fd, "r"); if (!fp) { fprintf(stderr, "Error: cannot open %s\n", fname); exit(1); @@ -142,11 +144,13 @@ static void process_protocol(const char *fname) { // process fname, fname.1, fname.2, fname.3, fname.4, fname.5 -void build_protocol(const char *fname, FILE *fp) { +void build_protocol(char *fname, int fd, FILE *fp) { assert(fname); + assert(fd); + assert(fp); // run fname - process_protocol(fname); + process_protocol(fname, fd); // run all the rest struct stat s; @@ -155,8 +159,10 @@ void build_protocol(const char *fname, FILE *fp) { char *newname; if (asprintf(&newname, "%s.%d", fname, i) == -1) errExit("asprintf"); - if (stat(newname, &s) == 0) - process_protocol(newname); + if (stat(newname, &s) == 0) { + int nfd = open(newname, O_RDONLY); + process_protocol(newname, nfd); + } free(newname); } diff --git a/src/fbuilder/fbuilder.h b/src/fbuilder/fbuilder.h index 0a0fd42c9..480569027 100644 --- a/src/fbuilder/fbuilder.h +++ b/src/fbuilder/fbuilder.h @@ -25,6 +25,7 @@ #include #include #include +#include #define MAX_BUF 4096 @@ -35,21 +36,21 @@ extern int arg_debug; void build_profile(int argc, char **argv, int index, FILE *fp); // build_seccomp.c -void build_seccomp(const char *fname, FILE *fp); -void build_protocol(const char *fname, FILE *fp); +void build_seccomp(char *fname, int fd, FILE *fp); +void build_protocol(char *fname, int fd, FILE *fp); // build_fs.c -void build_etc(const char *fname, FILE *fp); -void build_var(const char *fname, FILE *fp); -void build_tmp(const char *fname, FILE *fp); -void build_dev(const char *fname, FILE *fp); -void build_share(const char *fname, FILE *fp); +void build_etc(char *fname, FILE *fp, FILE *fpo); +void build_var(char *fname, FILE *fp, FILE *fpo); +void build_tmp(char *fname, FILE *fp, FILE *fpo); +void build_dev(char *fname, FILE *fp, FILE *fpo); +void build_share(char *fname, FILE *fp, FILE *fpo); // build_bin.c -void build_bin(const char *fname, FILE *fp); +void build_bin(char *fname, FILE *fp, FILE *fpo); // build_home.c -void build_home(const char *fname, FILE *fp); +void build_home(char *fname, FILE *fp, FILE *fpo); // utils.c int is_dir(const char *fname); @@ -66,4 +67,4 @@ FileDB *filedb_add(FileDB *head, const char *fname); FileDB *filedb_find(FileDB *head, const char *fname); void filedb_print(FileDB *head, const char *prefix, FILE *fp); -#endif \ No newline at end of file +#endif -- cgit v1.2.3-54-g00ecf