diff options
-rw-r--r-- | src/firejail/firejail.h | 2 | ||||
-rw-r--r-- | src/firejail/fs_hostname.c | 52 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 11 | ||||
-rw-r--r-- | src/include/rundefs.h | 1 | ||||
-rwxr-xr-x | test/private-etc/hostname.exp | 130 | ||||
-rw-r--r-- | test/private-etc/hosts-file | 2 | ||||
-rwxr-xr-x | test/private-etc/private-etc.sh | 3 |
7 files changed, 188 insertions, 13 deletions
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); | |||
660 | void fs_trace(void); | 660 | void fs_trace(void); |
661 | 661 | ||
662 | // fs_hostname.c | 662 | // fs_hostname.c |
663 | void fs_hostname(const char *hostname); | 663 | void fs_hostname(void); |
664 | char *fs_check_hosts_file(const char *fname); | 664 | char *fs_check_hosts_file(const char *fname); |
665 | void fs_store_hosts_file(void); | 665 | void fs_store_hosts_file(void); |
666 | void fs_mount_hosts_file(void); | 666 | 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 @@ | |||
24 | #include <dirent.h> | 24 | #include <dirent.h> |
25 | #include <fcntl.h> | 25 | #include <fcntl.h> |
26 | 26 | ||
27 | void fs_hostname(const char *hostname) { | 27 | // build a random host name |
28 | static char *random_hostname(void) { | ||
29 | char vowels[] = { 'a', 'e', 'i', 'o', 'u'}; | ||
30 | char consonants[] = {'b', 'c', 'c', 'c', 'g', 'h', 'h', 'h', 'h', 'h', | ||
31 | 'j', 'j', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'm', 'm', 'm', 'm', 'n', 'n', 'n', 'n', 'n', | ||
32 | 'r', 'r', 's', 's', 's', 's', 's', 's', 's', 's', 't', 't', 't', 't', | ||
33 | 'w', 'y', 'y', 'y', 'y', 'z', 'z'}; | ||
34 | char *ending[] = {"hiko", "hiko", "suke", "suke", "suke", "shi", "shi", "ro", "ro", | ||
35 | "rou", "hito", "hito","ka"}; | ||
36 | |||
37 | char *name = malloc(20); | ||
38 | if (!name) | ||
39 | errExit("malloc"); | ||
40 | |||
41 | int i = 0; | ||
42 | name[i++] = consonants[rand() % sizeof(consonants)]; | ||
43 | name[i++] = vowels[rand() % sizeof(vowels)]; | ||
44 | name[i++] = consonants[rand() % sizeof(consonants)]; | ||
45 | name[i++] = vowels[rand() % sizeof(vowels)]; | ||
46 | if (rand() % 2) { | ||
47 | name[i++] = consonants[rand() % sizeof(consonants)]; | ||
48 | name[i++] = vowels[rand() % sizeof(vowels)]; | ||
49 | } | ||
50 | char *ptr = ending[rand() % (sizeof(ending) / sizeof(char *))]; | ||
51 | strcpy(name + i, ptr); | ||
52 | return name; | ||
53 | } | ||
54 | |||
55 | void fs_hostname(void) { | ||
56 | const char *hostname = (cfg.hostname)? cfg.hostname: random_hostname(); | ||
28 | struct stat s; | 57 | struct stat s; |
29 | 58 | ||
30 | // create a new /etc/hostname | 59 | // create a new /etc/hostname |
@@ -33,6 +62,14 @@ void fs_hostname(const char *hostname) { | |||
33 | printf("Creating a new /etc/hostname file\n"); | 62 | printf("Creating a new /etc/hostname file\n"); |
34 | 63 | ||
35 | create_empty_file_as_root(RUN_HOSTNAME_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | 64 | create_empty_file_as_root(RUN_HOSTNAME_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); |
65 | FILE *fp = fopen(RUN_HOSTNAME_FILE, "we"); | ||
66 | if (!fp) { | ||
67 | fclose(fp); | ||
68 | goto errexit; | ||
69 | } | ||
70 | fprintf(fp, "%s\n", hostname); | ||
71 | SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | ||
72 | fclose(fp); | ||
36 | 73 | ||
37 | // bind-mount the file on top of /etc/hostname | 74 | // bind-mount the file on top of /etc/hostname |
38 | if (mount(RUN_HOSTNAME_FILE, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0) | 75 | if (mount(RUN_HOSTNAME_FILE, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0) |
@@ -41,12 +78,12 @@ void fs_hostname(const char *hostname) { | |||
41 | } | 78 | } |
42 | 79 | ||
43 | // create a new /etc/hosts | 80 | // create a new /etc/hosts |
44 | if (cfg.hosts_file == NULL && stat("/etc/hosts", &s) == 0) { | 81 | if (stat(RUN_HOSTS_FILE2, &s) == 0) { |
45 | if (arg_debug) | 82 | if (arg_debug) |
46 | printf("Creating a new /etc/hosts file\n"); | 83 | printf("Creating a new /etc/hosts file\n"); |
47 | // copy /etc/host into our new file, and modify it on the fly | 84 | // copy /etc/host into our new file, and modify it on the fly |
48 | /* coverity[toctou] */ | 85 | /* coverity[toctou] */ |
49 | FILE *fp1 = fopen("/etc/hosts", "re"); | 86 | FILE *fp1 = fopen(RUN_HOSTS_FILE2, "re"); |
50 | if (!fp1) | 87 | if (!fp1) |
51 | goto errexit; | 88 | goto errexit; |
52 | 89 | ||
@@ -67,7 +104,7 @@ void fs_hostname(const char *hostname) { | |||
67 | // copy line | 104 | // copy line |
68 | if (strstr(buf, "127.0.0.1") && done == 0) { | 105 | if (strstr(buf, "127.0.0.1") && done == 0) { |
69 | done = 1; | 106 | done = 1; |
70 | fprintf(fp2, "%s %s\n", buf, hostname); | 107 | fprintf(fp2, "127.0.0.1 %s\n", hostname); |
71 | } | 108 | } |
72 | else | 109 | else |
73 | fprintf(fp2, "%s\n", buf); | 110 | fprintf(fp2, "%s\n", buf); |
@@ -83,7 +120,7 @@ void fs_hostname(const char *hostname) { | |||
83 | return; | 120 | return; |
84 | 121 | ||
85 | errexit: | 122 | errexit: |
86 | fprintf(stderr, "Error: cannot create hostname file\n"); | 123 | fprintf(stderr, "Error: cannot create /etc/hostname and /etc/hosts files\n"); |
87 | exit(1); | 124 | exit(1); |
88 | } | 125 | } |
89 | 126 | ||
@@ -103,7 +140,10 @@ errexit: | |||
103 | } | 140 | } |
104 | 141 | ||
105 | void fs_store_hosts_file(void) { | 142 | void fs_store_hosts_file(void) { |
106 | copy_file_from_user_to_root(cfg.hosts_file, RUN_HOSTS_FILE, 0, 0, 0644); // root needed | 143 | if (cfg.hosts_file) |
144 | copy_file_from_user_to_root(cfg.hosts_file, RUN_HOSTS_FILE2, 0, 0, 0644); // root needed | ||
145 | else | ||
146 | copy_file_from_user_to_root("/etc/hosts", RUN_HOSTS_FILE2, 0, 0, 0644); // root needed | ||
107 | } | 147 | } |
108 | 148 | ||
109 | void fs_mount_hosts_file(void) { | 149 | 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) { | |||
848 | fs_trace_touch_or_store_preload(); | 848 | fs_trace_touch_or_store_preload(); |
849 | 849 | ||
850 | // store hosts file | 850 | // store hosts file |
851 | if (cfg.hosts_file) | 851 | fs_store_hosts_file(); |
852 | fs_store_hosts_file(); | ||
853 | 852 | ||
854 | //**************************** | 853 | //**************************** |
855 | // configure filesystem | 854 | // configure filesystem |
@@ -986,11 +985,11 @@ int sandbox(void* sandbox_arg) { | |||
986 | //**************************** | 985 | //**************************** |
987 | // hosts and hostname | 986 | // hosts and hostname |
988 | //**************************** | 987 | //**************************** |
989 | if (cfg.hostname) | 988 | // if (cfg.hostname) |
990 | fs_hostname(cfg.hostname); | 989 | fs_hostname(); |
991 | 990 | ||
992 | if (cfg.hosts_file) | 991 | // if (cfg.hosts_file) |
993 | fs_mount_hosts_file(); | 992 | // fs_mount_hosts_file(); |
994 | 993 | ||
995 | //**************************** | 994 | //**************************** |
996 | // /etc overrides from the network namespace | 995 | // /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 @@ | |||
89 | #define RUN_ASOUNDRC_FILE RUN_MNT_DIR "/.asoundrc" | 89 | #define RUN_ASOUNDRC_FILE RUN_MNT_DIR "/.asoundrc" |
90 | #define RUN_HOSTNAME_FILE RUN_MNT_DIR "/hostname" | 90 | #define RUN_HOSTNAME_FILE RUN_MNT_DIR "/hostname" |
91 | #define RUN_HOSTS_FILE RUN_MNT_DIR "/hosts" | 91 | #define RUN_HOSTS_FILE RUN_MNT_DIR "/hosts" |
92 | #define RUN_HOSTS_FILE2 RUN_MNT_DIR "/hosts2" | ||
92 | #define RUN_MACHINEID RUN_MNT_DIR "/machine-id" | 93 | #define RUN_MACHINEID RUN_MNT_DIR "/machine-id" |
93 | #define RUN_LDPRELOAD_FILE RUN_MNT_DIR "/ld.so.preload" | 94 | #define RUN_LDPRELOAD_FILE RUN_MNT_DIR "/ld.so.preload" |
94 | #define RUN_UTMP_FILE RUN_MNT_DIR "/utmp" | 95 | #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 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2023 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "firejail --hostname=foo cat /etc/hostname\r" | ||
11 | expect { | ||
12 | timeout {puts "TESTING ERROR 0\n";exit} | ||
13 | "Child process initialized" | ||
14 | } | ||
15 | expect { | ||
16 | timeout {puts "TESTING ERROR 0.1\n";exit} | ||
17 | "foo" | ||
18 | } | ||
19 | sleep 1 | ||
20 | |||
21 | send -- "firejail --hostname=foo --private-etc cat /etc/hostname\r" | ||
22 | expect { | ||
23 | timeout {puts "TESTING ERROR 1\n";exit} | ||
24 | "Child process initialized" | ||
25 | } | ||
26 | expect { | ||
27 | timeout {puts "TESTING ERROR 1.1\n";exit} | ||
28 | "foo" | ||
29 | } | ||
30 | sleep 1 | ||
31 | |||
32 | send -- "firejail --hosts-file=hosts-file cat /etc/hosts\r" | ||
33 | expect { | ||
34 | timeout {puts "TESTING ERROR 2\n";exit} | ||
35 | "Child process initialized" | ||
36 | } | ||
37 | expect { | ||
38 | timeout {puts "TESTING ERROR 2.1\n";exit} | ||
39 | "blablabla" | ||
40 | } | ||
41 | sleep 1 | ||
42 | |||
43 | send -- "firejail --hosts-file=hosts-file --private-etc cat /etc/hosts\r" | ||
44 | expect { | ||
45 | timeout {puts "TESTING ERROR 3\n";exit} | ||
46 | "Child process initialized" | ||
47 | } | ||
48 | expect { | ||
49 | timeout {puts "TESTING ERROR 3.1\n";exit} | ||
50 | "blablabla" | ||
51 | } | ||
52 | sleep 1 | ||
53 | |||
54 | send -- "firejail --hosts-file=hosts-file --hostname=foo cat /etc/hosts\r" | ||
55 | expect { | ||
56 | timeout {puts "TESTING ERROR 4\n";exit} | ||
57 | "Child process initialized" | ||
58 | } | ||
59 | expect { | ||
60 | timeout {puts "TESTING ERROR 4.1\n";exit} | ||
61 | "foo" | ||
62 | } | ||
63 | expect { | ||
64 | timeout {puts "TESTING ERROR 4.2\n";exit} | ||
65 | "blablabla" | ||
66 | } | ||
67 | sleep 1 | ||
68 | |||
69 | send -- "firejail --hosts-file=hosts-file --hostname=foo --private-etc cat /etc/hosts\r" | ||
70 | expect { | ||
71 | timeout {puts "TESTING ERROR 5\n";exit} | ||
72 | "Child process initialized" | ||
73 | } | ||
74 | expect { | ||
75 | timeout {puts "TESTING ERROR 5.1\n";exit} | ||
76 | "foo" | ||
77 | } | ||
78 | expect { | ||
79 | timeout {puts "TESTING ERROR 5.2\n";exit} | ||
80 | "blablabla" | ||
81 | } | ||
82 | sleep 1 | ||
83 | |||
84 | # ping test | ||
85 | send -- "firejail --hostname=foo --private-etc ping -c 3 foo\r" | ||
86 | expect { | ||
87 | timeout {puts "TESTING ERROR 6\n";exit} | ||
88 | "3 packets transmitted, 3 received" | ||
89 | } | ||
90 | sleep 1 | ||
91 | |||
92 | send -- "firejail --hosts-file=hosts-file --private-etc ping -c 3 blablabla\r" | ||
93 | expect { | ||
94 | timeout {puts "TESTING ERROR 7\n";exit} | ||
95 | "3 packets transmitted, 3 received" | ||
96 | } | ||
97 | sleep 1 | ||
98 | |||
99 | # random hostname | ||
100 | send -- "firejail cat /etc/hostname\r" | ||
101 | expect { | ||
102 | timeout {puts "TESTING ERROR 8\n";exit} | ||
103 | "Child process initialized" | ||
104 | } | ||
105 | expect { | ||
106 | timeout {puts "TESTING ERROR 8.1\n";exit} | ||
107 | "hiko" {puts "1"} | ||
108 | "suke" {puts "2"} | ||
109 | "shi" {puts "3"} | ||
110 | "ro" {puts "4"} | ||
111 | "hito" {puts "5"} | ||
112 | "ka" {puts "6"} | ||
113 | } | ||
114 | sleep 1 | ||
115 | |||
116 | # run /bin/hostname | ||
117 | send -- "firejail --noblacklist=/usr/bin/hostname --noblacklist=/bin/hostname --hostname=foo /usr/bin/hostname\r" | ||
118 | expect { | ||
119 | timeout {puts "TESTING ERROR 9\n";exit} | ||
120 | "Child process initialized" | ||
121 | } | ||
122 | expect { | ||
123 | timeout {puts "TESTING ERROR 9.1\n";exit} | ||
124 | "foo" | ||
125 | } | ||
126 | |||
127 | |||
128 | after 500 | ||
129 | puts "all done\n" | ||
130 | |||
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 @@ | |||
1 | 127.0.0.1 debian | ||
2 | 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)" | |||
18 | 18 | ||
19 | echo "TESTING: etc-cleanup (test/private-etc/etc-cleanup.exp)" | 19 | echo "TESTING: etc-cleanup (test/private-etc/etc-cleanup.exp)" |
20 | ./etc-cleanup.exp | 20 | ./etc-cleanup.exp |
21 | |||
22 | echo "TESTING: hostname (test/private-etc/hostname.exp)" | ||
23 | ./hostname.exp | ||