From 7d11cf62ca175696c8f5998de42c510924c6dcc3 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Sun, 22 Jan 2017 10:26:05 -0500 Subject: --hosts-file option --- src/firejail/firejail.h | 4 ++++ src/firejail/fs_hostname.c | 55 ++++++++++++++++++++++++++++++++++++++++---- src/firejail/main.c | 3 +++ src/firejail/profile.c | 6 +++++ src/firejail/sandbox.c | 21 +++++++++++------ src/firejail/usage.c | 1 + src/man/firejail-profile.txt | 4 ++++ src/man/firejail.txt | 10 ++++++++ 8 files changed, 93 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 94e66920b..0f836f1db 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -213,6 +213,7 @@ typedef struct config_t { // networking char *name; // sandbox name char *hostname; // host name + char *hosts_file; // hosts file to be installed in the sandbox uint32_t defaultgw; // default gateway Bridge bridge0; Bridge bridge1; @@ -537,6 +538,9 @@ void fs_trace(void); // fs_hostname.c void fs_hostname(const char *hostname); void fs_resolvconf(void); +char *fs_check_hosts_fiile(const char *fname); +void fs_store_hosts_file(void); +void fs_mount_hosts_file(void); // rlimit.c void set_rlimits(void); diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c index b2e1b4a99..ac831f6b9 100644 --- a/src/firejail/fs_hostname.c +++ b/src/firejail/fs_hostname.c @@ -42,7 +42,7 @@ void fs_hostname(const char *hostname) { } // create a new /etc/hosts - if (stat("/etc/hosts", &s) == 0) { + if (cfg.hosts_file == NULL && stat("/etc/hosts", &s) == 0) { if (arg_debug) printf("Creating a new /etc/hosts file\n"); // copy /etc/host into our new file, and modify it on the fly @@ -79,9 +79,7 @@ void fs_hostname(const char *hostname) { fclose(fp2); // bind-mount the file on top of /etc/hostname - if (mount(RUN_HOSTS_FILE, "/etc/hosts", NULL, MS_BIND|MS_REC, NULL) < 0) - errExit("mount bind /etc/hosts"); - fs_logger("create /etc/hosts"); + fs_mount_hosts_file(); } return; @@ -129,4 +127,53 @@ void fs_resolvconf(void) { } } +char *fs_check_hosts_fiile(const char *fname) { + assert(fname); + invalid_filename(fname); + char *rv = expand_home(fname, cfg.homedir); + + // no a link + if (is_link(rv)) + goto errexit; + + // file owned by the user + struct stat s; + if (stat(rv, &s) == -1) + goto errexit; + if (s.st_uid != getuid()) + goto errexit; + + return rv; +errexit: + fprintf(stderr, "Error: invalid file %s\n", fname); + exit(1); +} + +void fs_store_hosts_file(void) { + copy_file(cfg.hosts_file, RUN_HOSTS_FILE, 0, 0, 0644); // root needed +} + +void fs_mount_hosts_file(void) { + // check /etc/hosts file + struct stat s; + if (stat("/etc/hosts", &s) == -1) + goto errexit; + // not a link + if (is_link("/etc/hosts")) + goto errexit; + // owned by root + if (s.st_uid != 0) + goto errexit; + + // bind-mount the file on top of /etc/hostname + if (mount(RUN_HOSTS_FILE, "/etc/hosts", NULL, MS_BIND|MS_REC, NULL) < 0) + errExit("mount bind /etc/hosts"); + fs_logger("create /etc/hosts"); + return; + +errexit: + fprintf(stderr, "Error: invalid /etc/hosts file\n"); + exit(1); +} + diff --git a/src/firejail/main.c b/src/firejail/main.c index 9c6b6e001..8fea98950 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -1947,6 +1947,9 @@ int main(int argc, char **argv) { return 1; } } + + else if (strncmp(argv[i], "--hosts-file=", 13) == 0) + cfg.hosts_file = fs_check_hosts_fiile(argv[i] + 13); #ifdef HAVE_NETWORK else if (strcmp(argv[i], "--netfilter") == 0) { diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 33b6eab91..2d49b60c0 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -602,6 +602,12 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { return 0; } + // hosts-file + if (strncmp(ptr, "hosts-file ", 11) == 0) { + cfg.hosts_file = fs_check_hosts_fiile(ptr + 11); + return 0; + } + // dns if (strncmp(ptr, "dns ", 4) == 0) { uint32_t dns; diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 69cb8331e..812112b51 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -587,6 +587,10 @@ int sandbox(void* sandbox_arg) { if (arg_trace || arg_tracelog || mask_x11_abstract_socket) fs_trace_preload(); + // store hosts file + if (cfg.hosts_file) + fs_store_hosts_file(); + //**************************** // configure filesystem //**************************** @@ -630,13 +634,6 @@ int sandbox(void* sandbox_arg) { #endif fs_basic_fs(); - //**************************** - // set hostname in /etc/hostname - //**************************** - if (cfg.hostname) { - fs_hostname(cfg.hostname); - } - //**************************** // private mode //**************************** @@ -735,6 +732,16 @@ int sandbox(void* sandbox_arg) { } } + + //**************************** + // hosts and hostname + //**************************** + if (cfg.hostname) + fs_hostname(cfg.hostname); + + if (cfg.hosts_file) + fs_mount_hosts_file(); + //**************************** // /etc overrides from the network namespace //**************************** diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 9f4dfd44c..6f16a5868 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -78,6 +78,7 @@ void usage(void) { printf(" --get=name|pid filename - get a file from sandbox container.\n"); printf(" --help, -? - this help screen.\n"); printf(" --hostname=name - set sandbox hostname.\n"); + printf(" --hosts-file=file - use file as /etc/hosts.\n"); printf(" --ignore=command - ignore command in profile files.\n"); #ifdef HAVE_NETWORK printf(" --interface=name - move interface in sandbox.\n"); diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index ecb8be139..034f1beac 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt @@ -391,6 +391,10 @@ Set a DNS server for the sandbox. Up to three DNS servers can be defined. \fBhostname name Set a hostname for the sandbox. +.TP +\fBhosts-file file +Use file as /etc/hosts. + .TP \fBip address Assign IP addresses to the last network interface defined by a net command. A diff --git a/src/man/firejail.txt b/src/man/firejail.txt index afd8e1e4e..b836fd738 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -468,6 +468,16 @@ Example: .br $ firejail \-\-hostname=officepc firefox +.TP +\fB\-\-hosts-file=file +Use file as /etc/hosts. +.br + +.br +Example: +.br +$ firejail \-\-hosts-file=~/myhosts firefox + .TP \fB\-\-ignore=command Ignore command in profile file. -- cgit v1.2.3-70-g09d2