diff options
author | netblue30 <netblue30@yahoo.com> | 2015-10-10 14:57:44 -0400 |
---|---|---|
committer | netblue30 <netblue30@yahoo.com> | 2015-10-10 14:57:44 -0400 |
commit | 9be68f1b643c497163842aa1b3fa820c089d8b5f (patch) | |
tree | bbc9955c3ffd647a9f6c799567f782bd7a10dcbf | |
parent | added shell none in firefox profile (diff) | |
download | firejail-9be68f1b643c497163842aa1b3fa820c089d8b5f.tar.gz firejail-9be68f1b643c497163842aa1b3fa820c089d8b5f.tar.zst firejail-9be68f1b643c497163842aa1b3fa820c089d8b5f.zip |
--private-bin
-rw-r--r-- | src/firejail/firejail.h | 3 | ||||
-rw-r--r-- | src/firejail/fs_bin.c | 217 | ||||
-rw-r--r-- | src/firejail/main.c | 9 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 2 |
4 files changed, 230 insertions, 1 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 2dd70c7f4..27e49ea38 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #define MNT_DIR "/tmp/firejail/mnt" | 28 | #define MNT_DIR "/tmp/firejail/mnt" |
29 | #define HOME_DIR "/tmp/firejail/mnt/home" | 29 | #define HOME_DIR "/tmp/firejail/mnt/home" |
30 | #define ETC_DIR "/tmp/firejail/mnt/etc" | 30 | #define ETC_DIR "/tmp/firejail/mnt/etc" |
31 | #define BIN_DIR "/tmp/firejail/mnt/bin" | ||
31 | #define WHITELIST_HOME_DIR "/tmp/firejail/mnt/whome" | 32 | #define WHITELIST_HOME_DIR "/tmp/firejail/mnt/whome" |
32 | #define DEFAULT_USER_PROFILE "generic" | 33 | #define DEFAULT_USER_PROFILE "generic" |
33 | #define DEFAULT_ROOT_PROFILE "server" | 34 | #define DEFAULT_ROOT_PROFILE "server" |
@@ -82,6 +83,7 @@ typedef struct config_t { | |||
82 | char *home_private; // private home directory | 83 | char *home_private; // private home directory |
83 | char *home_private_keep; // keep list for private home directory | 84 | char *home_private_keep; // keep list for private home directory |
84 | char *etc_private_keep; // keep list for private etc directory | 85 | char *etc_private_keep; // keep list for private etc directory |
86 | char *bin_private_keep; // keep list for private etc directory | ||
85 | char *cwd; // current working directory | 87 | char *cwd; // current working directory |
86 | char *overlay_dir; | 88 | char *overlay_dir; |
87 | 89 | ||
@@ -169,6 +171,7 @@ extern int arg_doubledash; // double dash | |||
169 | extern int arg_shell_none; // run the program directly without a shell | 171 | extern int arg_shell_none; // run the program directly without a shell |
170 | extern int arg_private_dev; // private dev directory | 172 | extern int arg_private_dev; // private dev directory |
171 | extern int arg_private_etc; // private etc directory | 173 | extern int arg_private_etc; // private etc directory |
174 | extern int arg_private_bin; // private bin directory | ||
172 | extern int arg_scan; // arp-scan all interfaces | 175 | extern int arg_scan; // arp-scan all interfaces |
173 | extern int arg_whitelist; // whitelist commad | 176 | extern int arg_whitelist; // whitelist commad |
174 | 177 | ||
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c new file mode 100644 index 000000000..4b3292b6c --- /dev/null +++ b/src/firejail/fs_bin.c | |||
@@ -0,0 +1,217 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014, 2015 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include "firejail.h" | ||
21 | #include <sys/mount.h> | ||
22 | #include <sys/stat.h> | ||
23 | #include <sys/types.h> | ||
24 | #include <sys/wait.h> | ||
25 | #include <unistd.h> | ||
26 | |||
27 | static char *paths[] = { | ||
28 | "/bin", | ||
29 | "/sbin", | ||
30 | "/usr/bin", | ||
31 | "/usr/sbin", | ||
32 | NULL | ||
33 | }; | ||
34 | |||
35 | // return 1 if found, 0 if not found | ||
36 | static char *check_dir_or_file(const char *name) { | ||
37 | assert(name); | ||
38 | struct stat s; | ||
39 | char *fname = NULL; | ||
40 | |||
41 | int i = 0; | ||
42 | while (paths[i]) { | ||
43 | if (asprintf(&fname, "%s/%s", paths[i], name) == -1) | ||
44 | errExit("asprintf"); | ||
45 | if (arg_debug) | ||
46 | printf("Checking %s/%s\n", paths[i], name); | ||
47 | if (stat(fname, &s) == 0) | ||
48 | break; // file found | ||
49 | |||
50 | free(fname); | ||
51 | fname = NULL; | ||
52 | i++; | ||
53 | } | ||
54 | |||
55 | if (!fname) | ||
56 | return NULL; | ||
57 | |||
58 | free(fname); | ||
59 | return paths[i]; | ||
60 | } | ||
61 | |||
62 | void fs_check_bin_list(void) { | ||
63 | if (strstr(cfg.bin_private_keep, "..")) { | ||
64 | fprintf(stderr, "Error: invalid private bin list\n"); | ||
65 | exit(1); | ||
66 | } | ||
67 | |||
68 | char *dlist = strdup(cfg.bin_private_keep); | ||
69 | if (!dlist) | ||
70 | errExit("strdup"); | ||
71 | |||
72 | // create a new list removing files not found | ||
73 | char *newlist = malloc(strlen(dlist) + 1 + 1); // +',' + '\0' | ||
74 | if (!newlist) | ||
75 | errExit("malloc"); | ||
76 | *newlist = '\0'; | ||
77 | char *newlistptr = newlist; | ||
78 | |||
79 | // check the first file | ||
80 | char *ptr = strtok(dlist, ","); | ||
81 | int notfound = 0; | ||
82 | if (check_dir_or_file(ptr)) { | ||
83 | // file found, copy the name in the new list | ||
84 | strcpy(newlistptr, ptr); | ||
85 | strcat(newlistptr, ","); | ||
86 | newlistptr += strlen(newlistptr); | ||
87 | } | ||
88 | else | ||
89 | notfound = 1; | ||
90 | |||
91 | // check the rest of the list | ||
92 | while ((ptr = strtok(NULL, ",")) != NULL) { | ||
93 | if (check_dir_or_file(ptr)) { | ||
94 | // file found, copy the name in the new list | ||
95 | strcpy(newlistptr, ptr); | ||
96 | strcat(newlistptr, ","); | ||
97 | newlistptr += strlen(newlistptr); | ||
98 | } | ||
99 | else | ||
100 | notfound = 1; | ||
101 | } | ||
102 | printf("here %d: newlist #%s#\n", __LINE__, newlist); | ||
103 | |||
104 | if (*newlist == '\0') { | ||
105 | fprintf(stderr, "Warning: no --private-bin list executable found, option disabled\n"); | ||
106 | cfg.bin_private_keep = NULL; | ||
107 | arg_private_bin = 0; | ||
108 | free(newlist); | ||
109 | } | ||
110 | else { | ||
111 | ptr = strrchr(newlist, ','); | ||
112 | assert(ptr); | ||
113 | *ptr = '\0'; | ||
114 | if (notfound) | ||
115 | fprintf(stderr, "Warning: not all executables from --private-bin list were found. The current list is %s\n", newlist); | ||
116 | |||
117 | cfg.bin_private_keep = newlist; | ||
118 | } | ||
119 | |||
120 | free(dlist); | ||
121 | } | ||
122 | |||
123 | static void duplicate(char *fname) { | ||
124 | char *cmd; | ||
125 | char *path = check_dir_or_file(fname); | ||
126 | if (!path) | ||
127 | return; | ||
128 | |||
129 | // expand path, just in case this is a symbolic link | ||
130 | char *full_path; | ||
131 | if (asprintf(&full_path, "%s/%s", path, fname) == -1) | ||
132 | errExit("asprintf"); | ||
133 | |||
134 | char *actual_path = realpath(full_path, NULL); | ||
135 | if (actual_path) { | ||
136 | // copy the file | ||
137 | if (asprintf(&cmd, "cp -a %s %s/%s", actual_path, BIN_DIR, fname) == -1) | ||
138 | errExit("asprintf"); | ||
139 | if (arg_debug) | ||
140 | printf("%s\n", cmd); | ||
141 | if (system(cmd)) | ||
142 | errExit("system cp -a"); | ||
143 | free(cmd); | ||
144 | free(actual_path); | ||
145 | } | ||
146 | |||
147 | free(full_path); | ||
148 | } | ||
149 | |||
150 | |||
151 | void fs_private_bin_list(void) { | ||
152 | char *private_list = cfg.bin_private_keep; | ||
153 | assert(private_list); | ||
154 | |||
155 | // check bin paths | ||
156 | int i = 0; | ||
157 | while (paths[i]) { | ||
158 | struct stat s; | ||
159 | if (stat(paths[i], &s) == -1) { | ||
160 | fprintf(stderr, "Error: cannot find %s directory\n", paths[i]); | ||
161 | exit(1); | ||
162 | } | ||
163 | i++; | ||
164 | } | ||
165 | |||
166 | // create /tmp/firejail/mnt/bin directory | ||
167 | fs_build_mnt_dir(); | ||
168 | int rv = mkdir(BIN_DIR, S_IRWXU | S_IRWXG | S_IRWXO); | ||
169 | if (rv == -1) | ||
170 | errExit("mkdir"); | ||
171 | if (chown(BIN_DIR, 0, 0) < 0) | ||
172 | errExit("chown"); | ||
173 | if (chmod(BIN_DIR, 0755) < 0) | ||
174 | errExit("chmod"); | ||
175 | |||
176 | // copy the list of files in the new etc directory | ||
177 | // using a new child process without root privileges | ||
178 | pid_t child = fork(); | ||
179 | if (child < 0) | ||
180 | errExit("fork"); | ||
181 | if (child == 0) { | ||
182 | if (arg_debug) | ||
183 | printf("Copying files in the new home:\n"); | ||
184 | |||
185 | // elevate privileges - files in the new /bin directory belong to root | ||
186 | if (setreuid(0, 0) < 0) | ||
187 | errExit("setreuid"); | ||
188 | if (setregid(0, 0) < 0) | ||
189 | errExit("setregid"); | ||
190 | |||
191 | // copy the list of files in the new home directory | ||
192 | char *dlist = strdup(private_list); | ||
193 | if (!dlist) | ||
194 | errExit("strdup"); | ||
195 | |||
196 | char *ptr = strtok(dlist, ","); | ||
197 | duplicate(ptr); | ||
198 | |||
199 | while ((ptr = strtok(NULL, ",")) != NULL) | ||
200 | duplicate(ptr); | ||
201 | free(dlist); | ||
202 | exit(0); | ||
203 | } | ||
204 | // wait for the child to finish | ||
205 | waitpid(child, NULL, 0); | ||
206 | |||
207 | // moun-bind | ||
208 | i = 0; | ||
209 | while (paths[i]) { | ||
210 | if (arg_debug) | ||
211 | printf("Mount-bind %s on top of %s\n", BIN_DIR, paths[i]); | ||
212 | if (mount(BIN_DIR, paths[i], NULL, MS_BIND|MS_REC, NULL) < 0) | ||
213 | errExit("mount bind"); | ||
214 | i++; | ||
215 | } | ||
216 | } | ||
217 | |||
diff --git a/src/firejail/main.c b/src/firejail/main.c index a7eda3906..616b26894 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -82,6 +82,7 @@ int arg_doubledash = 0; // double dash | |||
82 | int arg_shell_none = 0; // run the program directly without a shell | 82 | int arg_shell_none = 0; // run the program directly without a shell |
83 | int arg_private_dev = 0; // private dev directory | 83 | int arg_private_dev = 0; // private dev directory |
84 | int arg_private_etc = 0; // private etc directory | 84 | int arg_private_etc = 0; // private etc directory |
85 | int arg_private_bin = 0; // private bin directory | ||
85 | int arg_scan = 0; // arp-scan all interfaces | 86 | int arg_scan = 0; // arp-scan all interfaces |
86 | int arg_whitelist = 0; // whitelist commad | 87 | int arg_whitelist = 0; // whitelist commad |
87 | 88 | ||
@@ -764,6 +765,12 @@ int main(int argc, char **argv) { | |||
764 | fs_check_etc_list(); | 765 | fs_check_etc_list(); |
765 | arg_private_etc = 1; | 766 | arg_private_etc = 1; |
766 | } | 767 | } |
768 | else if (strncmp(argv[i], "--private-bin=", 14) == 0) { | ||
769 | // extract private etc dirname | ||
770 | cfg.bin_private_keep = argv[i] + 14; | ||
771 | fs_check_bin_list(); | ||
772 | arg_private_bin = 1; | ||
773 | } | ||
767 | 774 | ||
768 | 775 | ||
769 | 776 | ||
@@ -1029,7 +1036,7 @@ int main(int argc, char **argv) { | |||
1029 | } | 1036 | } |
1030 | cfg.shell = argv[i] + 8; | 1037 | cfg.shell = argv[i] + 8; |
1031 | 1038 | ||
1032 | if (is_dir(cfg.shell) || is_link(cfg.shell) || strstr(cfg.shell, "..")) { | 1039 | if (is_dir(cfg.shell) || strstr(cfg.shell, "..")) { |
1033 | fprintf(stderr, "Error: invalid shell\n"); | 1040 | fprintf(stderr, "Error: invalid shell\n"); |
1034 | exit(1); | 1041 | exit(1); |
1035 | } | 1042 | } |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index eca4c2282..d3f92e51b 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -257,6 +257,8 @@ int sandbox(void* sandbox_arg) { | |||
257 | fs_private_dev(); | 257 | fs_private_dev(); |
258 | if (arg_private_etc) | 258 | if (arg_private_etc) |
259 | fs_private_etc_list(); | 259 | fs_private_etc_list(); |
260 | if (arg_private_bin) | ||
261 | fs_private_bin_list(); | ||
260 | 262 | ||
261 | //**************************** | 263 | //**************************** |
262 | // install trace | 264 | // install trace |