From e4f9f36a47d5a0031bd181e77d9121fac1dd06ec Mon Sep 17 00:00:00 2001 From: netblue30 Date: Mon, 27 Feb 2023 17:50:02 -0500 Subject: random hostname by default; fix --hostname and --hosts-file --- src/firejail/firejail.h | 2 +- src/firejail/fs_hostname.c | 52 ++++++++++++++-- src/firejail/sandbox.c | 11 ++-- src/include/rundefs.h | 1 + test/private-etc/hostname.exp | 130 ++++++++++++++++++++++++++++++++++++++++ test/private-etc/hosts-file | 2 + test/private-etc/private-etc.sh | 3 + 7 files changed, 188 insertions(+), 13 deletions(-) create mode 100755 test/private-etc/hostname.exp create mode 100644 test/private-etc/hosts-file diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 824164c8a..5295393f0 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -660,7 +660,7 @@ void fs_tracefile(void); void fs_trace(void); // fs_hostname.c -void fs_hostname(const char *hostname); +void fs_hostname(void); char *fs_check_hosts_file(const char *fname); void fs_store_hosts_file(void); void fs_mount_hosts_file(void); diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c index bf4435310..32b314a8b 100644 --- a/src/firejail/fs_hostname.c +++ b/src/firejail/fs_hostname.c @@ -24,7 +24,36 @@ #include #include -void fs_hostname(const char *hostname) { +// build a random host name +static char *random_hostname(void) { + char vowels[] = { 'a', 'e', 'i', 'o', 'u'}; + char consonants[] = {'b', 'c', 'c', 'c', 'g', 'h', 'h', 'h', 'h', 'h', + 'j', 'j', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'm', 'm', 'm', 'm', 'n', 'n', 'n', 'n', 'n', + 'r', 'r', 's', 's', 's', 's', 's', 's', 's', 's', 't', 't', 't', 't', + 'w', 'y', 'y', 'y', 'y', 'z', 'z'}; + char *ending[] = {"hiko", "hiko", "suke", "suke", "suke", "shi", "shi", "ro", "ro", + "rou", "hito", "hito","ka"}; + + char *name = malloc(20); + if (!name) + errExit("malloc"); + + int i = 0; + name[i++] = consonants[rand() % sizeof(consonants)]; + name[i++] = vowels[rand() % sizeof(vowels)]; + name[i++] = consonants[rand() % sizeof(consonants)]; + name[i++] = vowels[rand() % sizeof(vowels)]; + if (rand() % 2) { + name[i++] = consonants[rand() % sizeof(consonants)]; + name[i++] = vowels[rand() % sizeof(vowels)]; + } + char *ptr = ending[rand() % (sizeof(ending) / sizeof(char *))]; + strcpy(name + i, ptr); + return name; +} + +void fs_hostname(void) { + const char *hostname = (cfg.hostname)? cfg.hostname: random_hostname(); struct stat s; // create a new /etc/hostname @@ -33,6 +62,14 @@ void fs_hostname(const char *hostname) { printf("Creating a new /etc/hostname file\n"); create_empty_file_as_root(RUN_HOSTNAME_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + FILE *fp = fopen(RUN_HOSTNAME_FILE, "we"); + if (!fp) { + fclose(fp); + goto errexit; + } + fprintf(fp, "%s\n", hostname); + SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + fclose(fp); // bind-mount the file on top of /etc/hostname if (mount(RUN_HOSTNAME_FILE, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0) @@ -41,12 +78,12 @@ void fs_hostname(const char *hostname) { } // create a new /etc/hosts - if (cfg.hosts_file == NULL && stat("/etc/hosts", &s) == 0) { + if (stat(RUN_HOSTS_FILE2, &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 /* coverity[toctou] */ - FILE *fp1 = fopen("/etc/hosts", "re"); + FILE *fp1 = fopen(RUN_HOSTS_FILE2, "re"); if (!fp1) goto errexit; @@ -67,7 +104,7 @@ void fs_hostname(const char *hostname) { // copy line if (strstr(buf, "127.0.0.1") && done == 0) { done = 1; - fprintf(fp2, "%s %s\n", buf, hostname); + fprintf(fp2, "127.0.0.1 %s\n", hostname); } else fprintf(fp2, "%s\n", buf); @@ -83,7 +120,7 @@ void fs_hostname(const char *hostname) { return; errexit: - fprintf(stderr, "Error: cannot create hostname file\n"); + fprintf(stderr, "Error: cannot create /etc/hostname and /etc/hosts files\n"); exit(1); } @@ -103,7 +140,10 @@ errexit: } void fs_store_hosts_file(void) { - copy_file_from_user_to_root(cfg.hosts_file, RUN_HOSTS_FILE, 0, 0, 0644); // root needed + if (cfg.hosts_file) + copy_file_from_user_to_root(cfg.hosts_file, RUN_HOSTS_FILE2, 0, 0, 0644); // root needed + else + copy_file_from_user_to_root("/etc/hosts", RUN_HOSTS_FILE2, 0, 0, 0644); // root needed } void fs_mount_hosts_file(void) { diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index a4109cc17..88de1fc5f 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -848,8 +848,7 @@ int sandbox(void* sandbox_arg) { fs_trace_touch_or_store_preload(); // store hosts file - if (cfg.hosts_file) - fs_store_hosts_file(); + fs_store_hosts_file(); //**************************** // configure filesystem @@ -986,11 +985,11 @@ int sandbox(void* sandbox_arg) { //**************************** // hosts and hostname //**************************** - if (cfg.hostname) - fs_hostname(cfg.hostname); +// if (cfg.hostname) + fs_hostname(); - if (cfg.hosts_file) - fs_mount_hosts_file(); +// if (cfg.hosts_file) +// fs_mount_hosts_file(); //**************************** // /etc overrides from the network namespace diff --git a/src/include/rundefs.h b/src/include/rundefs.h index af42b0984..7fc0f21f3 100644 --- a/src/include/rundefs.h +++ b/src/include/rundefs.h @@ -89,6 +89,7 @@ #define RUN_ASOUNDRC_FILE RUN_MNT_DIR "/.asoundrc" #define RUN_HOSTNAME_FILE RUN_MNT_DIR "/hostname" #define RUN_HOSTS_FILE RUN_MNT_DIR "/hosts" +#define RUN_HOSTS_FILE2 RUN_MNT_DIR "/hosts2" #define RUN_MACHINEID RUN_MNT_DIR "/machine-id" #define RUN_LDPRELOAD_FILE RUN_MNT_DIR "/ld.so.preload" #define RUN_UTMP_FILE RUN_MNT_DIR "/utmp" diff --git a/test/private-etc/hostname.exp b/test/private-etc/hostname.exp new file mode 100755 index 000000000..791445d49 --- /dev/null +++ b/test/private-etc/hostname.exp @@ -0,0 +1,130 @@ +#!/usr/bin/expect -f +# This file is part of Firejail project +# Copyright (C) 2014-2023 Firejail Authors +# License GPL v2 + +set timeout 10 +spawn $env(SHELL) +match_max 100000 + +send -- "firejail --hostname=foo cat /etc/hostname\r" +expect { + timeout {puts "TESTING ERROR 0\n";exit} + "Child process initialized" +} +expect { + timeout {puts "TESTING ERROR 0.1\n";exit} + "foo" +} +sleep 1 + +send -- "firejail --hostname=foo --private-etc cat /etc/hostname\r" +expect { + timeout {puts "TESTING ERROR 1\n";exit} + "Child process initialized" +} +expect { + timeout {puts "TESTING ERROR 1.1\n";exit} + "foo" +} +sleep 1 + +send -- "firejail --hosts-file=hosts-file cat /etc/hosts\r" +expect { + timeout {puts "TESTING ERROR 2\n";exit} + "Child process initialized" +} +expect { + timeout {puts "TESTING ERROR 2.1\n";exit} + "blablabla" +} +sleep 1 + +send -- "firejail --hosts-file=hosts-file --private-etc cat /etc/hosts\r" +expect { + timeout {puts "TESTING ERROR 3\n";exit} + "Child process initialized" +} +expect { + timeout {puts "TESTING ERROR 3.1\n";exit} + "blablabla" +} +sleep 1 + +send -- "firejail --hosts-file=hosts-file --hostname=foo cat /etc/hosts\r" +expect { + timeout {puts "TESTING ERROR 4\n";exit} + "Child process initialized" +} +expect { + timeout {puts "TESTING ERROR 4.1\n";exit} + "foo" +} +expect { + timeout {puts "TESTING ERROR 4.2\n";exit} + "blablabla" +} +sleep 1 + +send -- "firejail --hosts-file=hosts-file --hostname=foo --private-etc cat /etc/hosts\r" +expect { + timeout {puts "TESTING ERROR 5\n";exit} + "Child process initialized" +} +expect { + timeout {puts "TESTING ERROR 5.1\n";exit} + "foo" +} +expect { + timeout {puts "TESTING ERROR 5.2\n";exit} + "blablabla" +} +sleep 1 + +# ping test +send -- "firejail --hostname=foo --private-etc ping -c 3 foo\r" +expect { + timeout {puts "TESTING ERROR 6\n";exit} + "3 packets transmitted, 3 received" +} +sleep 1 + +send -- "firejail --hosts-file=hosts-file --private-etc ping -c 3 blablabla\r" +expect { + timeout {puts "TESTING ERROR 7\n";exit} + "3 packets transmitted, 3 received" +} +sleep 1 + +# random hostname +send -- "firejail cat /etc/hostname\r" +expect { + timeout {puts "TESTING ERROR 8\n";exit} + "Child process initialized" +} +expect { + timeout {puts "TESTING ERROR 8.1\n";exit} + "hiko" {puts "1"} + "suke" {puts "2"} + "shi" {puts "3"} + "ro" {puts "4"} + "hito" {puts "5"} + "ka" {puts "6"} +} +sleep 1 + +# run /bin/hostname +send -- "firejail --noblacklist=/usr/bin/hostname --noblacklist=/bin/hostname --hostname=foo /usr/bin/hostname\r" +expect { + timeout {puts "TESTING ERROR 9\n";exit} + "Child process initialized" +} +expect { + timeout {puts "TESTING ERROR 9.1\n";exit} + "foo" +} + + +after 500 +puts "all done\n" + diff --git a/test/private-etc/hosts-file b/test/private-etc/hosts-file new file mode 100644 index 000000000..1fb39596a --- /dev/null +++ b/test/private-etc/hosts-file @@ -0,0 +1,2 @@ +127.0.0.1 debian +127.5.5.5 blablabla diff --git a/test/private-etc/private-etc.sh b/test/private-etc/private-etc.sh index c46b684af..0dd61cb82 100755 --- a/test/private-etc/private-etc.sh +++ b/test/private-etc/private-etc.sh @@ -18,3 +18,6 @@ echo "TESTING: groups (test/private-etc/groups.exp)" echo "TESTING: etc-cleanup (test/private-etc/etc-cleanup.exp)" ./etc-cleanup.exp + +echo "TESTING: hostname (test/private-etc/hostname.exp)" +./hostname.exp -- cgit v1.2.3-54-g00ecf