diff options
Diffstat (limited to 'src/firejail/fs_lib2.c')
-rw-r--r-- | src/firejail/fs_lib2.c | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/src/firejail/fs_lib2.c b/src/firejail/fs_lib2.c new file mode 100644 index 000000000..4c2c15ebd --- /dev/null +++ b/src/firejail/fs_lib2.c | |||
@@ -0,0 +1,311 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 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 <dirent.h> | ||
22 | #include <sys/stat.h> | ||
23 | |||
24 | extern void fslib_duplicate(const char *full_path); | ||
25 | extern void fslib_copy_libs(const char *full_path); | ||
26 | extern void fslib_copy_dir(const char *full_path); | ||
27 | |||
28 | //*************************************************************** | ||
29 | // Standard C library | ||
30 | //*************************************************************** | ||
31 | // standard libc libraries based on Debian's libc6 package | ||
32 | // selinux seems to be linked in most command line utilities | ||
33 | // locale (/usr/lib/locale) - without it, the program will default to "C" locale | ||
34 | typedef struct liblist_t { | ||
35 | const char *name; | ||
36 | int len; | ||
37 | } LibList; | ||
38 | |||
39 | static LibList libc_list[] = { | ||
40 | { "libselinux.so.", 0 }, | ||
41 | { "ld-linux-x86-64.so.", 0 }, | ||
42 | { "libanl.so.", 0 }, | ||
43 | { "libc.so.", 0 }, | ||
44 | { "libcidn.so.", 0 }, | ||
45 | { "libcrypt.so.", 0 }, | ||
46 | { "libdl.so.", 0 }, | ||
47 | { "libm.so.", 0 }, | ||
48 | { "libmemusage.so", 0 }, | ||
49 | { "libmvec.so.", 0 }, | ||
50 | { "libnsl.so.", 0 }, | ||
51 | { "libnss_compat.so.", 0 }, | ||
52 | { "libnss_dns.so.", 0 }, | ||
53 | { "libnss_files.so.", 0 }, | ||
54 | { "libnss_hesiod.so.", 0 }, | ||
55 | { "libnss_nisplus.so.", 0 }, | ||
56 | { "libnss_nis.so.", 0 }, | ||
57 | { "libpthread.so.", 0 }, | ||
58 | { "libresolv.so.", 0 }, | ||
59 | { "librt.so.", 0 }, | ||
60 | { "libthread_db.so.", 0 }, | ||
61 | { "libutil.so.", 0 }, | ||
62 | { NULL, 0} | ||
63 | }; | ||
64 | |||
65 | static int find_libc_list(const char *name) { | ||
66 | assert(name); | ||
67 | |||
68 | int i = 0; | ||
69 | while (libc_list[i].name) { | ||
70 | if (libc_list[i].len == 0) | ||
71 | libc_list[i].len = strlen(libc_list[i].name); | ||
72 | if (strncmp(name, libc_list[i].name, libc_list[i].len) == 0) | ||
73 | return 1; | ||
74 | i++; | ||
75 | } | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | // compare the files in dirname against liblist above | ||
80 | static void stdc(const char *dirname) { | ||
81 | assert(dirname); | ||
82 | |||
83 | DIR *dir = opendir(dirname); | ||
84 | if (dir) { | ||
85 | struct dirent *entry; | ||
86 | while ((entry = readdir(dir)) != NULL) { | ||
87 | if (strcmp(entry->d_name, ".") == 0) | ||
88 | continue; | ||
89 | if (strcmp(entry->d_name, "..") == 0) | ||
90 | continue; | ||
91 | |||
92 | if (find_libc_list(entry->d_name)) { | ||
93 | char *fname; | ||
94 | if (asprintf(&fname, "%s/%s", dirname, entry->d_name) == -1) | ||
95 | errExit("asprintf"); | ||
96 | |||
97 | fslib_duplicate(fname); | ||
98 | } | ||
99 | } | ||
100 | closedir(dir); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | void fslib_install_stdc(void) { | ||
105 | // install standard C libraries | ||
106 | struct stat s; | ||
107 | char *stdclib = "/lib64"; // CentOS, Fedora, Arch | ||
108 | |||
109 | if (stat("/lib/x86_64-linux-gnu", &s) == 0) { // Debian & friends | ||
110 | mkdir_attr(RUN_LIB_DIR "/x86_64-linux-gnu", 0755, 0, 0); | ||
111 | stdclib = "/lib/x86_64-linux-gnu"; | ||
112 | } | ||
113 | |||
114 | timetrace_start(); | ||
115 | stdc(stdclib); | ||
116 | |||
117 | // install locale | ||
118 | if (stat("/usr/lib/locale", &s) == 0) | ||
119 | fslib_copy_dir("/usr/lib/locale"); | ||
120 | |||
121 | if (!arg_quiet) | ||
122 | fprintf(stderr, "Standard C library installed in %0.2f ms\n", timetrace_end()); | ||
123 | } | ||
124 | |||
125 | void fslib_install_locale(void); | ||
126 | |||
127 | |||
128 | //*************************************************************** | ||
129 | // various system libraries | ||
130 | //*************************************************************** | ||
131 | |||
132 | // look for library in the new filesystem, and install one or two more directories, dir1 and dir2 | ||
133 | typedef struct syslib_t { | ||
134 | const char *library; // look in the system for this library | ||
135 | int len; // length of library string, 0 by default | ||
136 | int found; // library found, 0 by default | ||
137 | const char *dir1; // directory to install | ||
138 | const char *dir2; // directory to install | ||
139 | const char *message; // message to print on the screen | ||
140 | } SysLib; | ||
141 | |||
142 | SysLib syslibs[] = { | ||
143 | #if 0 | ||
144 | { | ||
145 | "", // library | ||
146 | 0, 0, // len and found flag | ||
147 | "", // dir1 | ||
148 | "", // dir2 | ||
149 | "" // message | ||
150 | }, | ||
151 | #endif | ||
152 | { // pixmaps - libraries used by GTK to display application menu icons | ||
153 | "libgdk_pixbuf-2.0", // library | ||
154 | 0, 0, // len and found flag | ||
155 | "gdk-pixbuf-2.0", // dir1 | ||
156 | "", // dir2 | ||
157 | "GdkPixbuf" // message | ||
158 | }, | ||
159 | { // GTK2 | ||
160 | "libgtk-x11-2.0", // library | ||
161 | 0, 0, // len and found flag | ||
162 | "gtk-2.0", // dir1 | ||
163 | "libgtk2.0-0", // dir2 | ||
164 | "GTK2" // message | ||
165 | }, | ||
166 | { // GTK3 | ||
167 | "libgtk-3", // library | ||
168 | 0, 0, // len and found flag | ||
169 | "gtk-3.0", // dir1 | ||
170 | "libgtk-3-0", // dir2 | ||
171 | "GTK3" // message | ||
172 | }, | ||
173 | { // Pango - text internationalization, found on older GTK2-based systems | ||
174 | "libpango", // library | ||
175 | 0, 0, // len and found flag | ||
176 | "pango", // dir1 | ||
177 | "", // dir2 | ||
178 | "Pango" // message | ||
179 | }, | ||
180 | { // Library for handling GObject introspection data on GTK systems | ||
181 | "libgirepository-1.0", // library | ||
182 | 0, 0, // len and found flag | ||
183 | "girepository-1.0", // dir1 | ||
184 | "", // dir2 | ||
185 | "GIRepository" // message | ||
186 | }, | ||
187 | { // Enchant speller | ||
188 | "libenchant.so.", // library | ||
189 | 0, 0, // len and found flag | ||
190 | "enchant", // dir1 | ||
191 | "", // dir2 | ||
192 | "Enchant (speller)" // message | ||
193 | }, | ||
194 | { | ||
195 | "libQt5", // library | ||
196 | 0, 0, // len and found flag | ||
197 | "qt5", // dir1 | ||
198 | "gdk-pixbuf-2.0", // dir2 | ||
199 | "Qt5, GdkPixbuf" // message | ||
200 | }, | ||
201 | { | ||
202 | "libQtCore", // library | ||
203 | 0, 0, // len and found flag | ||
204 | "qt4", // dir1 | ||
205 | "gdk-pixbuf-2.0", // dir2 | ||
206 | "Qt4" // message | ||
207 | }, | ||
208 | |||
209 | { // NULL terminated list | ||
210 | NULL, // library | ||
211 | 0, 0, // len and found flag | ||
212 | "", // dir1 | ||
213 | "", // dir2 | ||
214 | "" // message | ||
215 | } | ||
216 | }; | ||
217 | |||
218 | void fslib_install_system(void) { | ||
219 | // look for installed libraries | ||
220 | DIR *dir = opendir(RUN_LIB_DIR "/x86_64-linux-gnu"); | ||
221 | if (!dir) | ||
222 | dir = opendir(RUN_LIB_DIR); | ||
223 | |||
224 | if (dir) { | ||
225 | struct dirent *entry; | ||
226 | while ((entry = readdir(dir)) != NULL) { | ||
227 | if (strcmp(entry->d_name, ".") == 0) | ||
228 | continue; | ||
229 | if (strcmp(entry->d_name, "..") == 0) | ||
230 | continue; | ||
231 | |||
232 | SysLib *ptr = &syslibs[0]; | ||
233 | while (ptr->library) { | ||
234 | if (ptr->len == 0) | ||
235 | ptr->len = strlen(ptr->library); | ||
236 | |||
237 | if (strncmp(entry->d_name, ptr->library, ptr->len) == 0) { | ||
238 | ptr->found = 1; | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | ptr++; | ||
243 | } | ||
244 | |||
245 | } | ||
246 | closedir(dir); | ||
247 | } | ||
248 | else | ||
249 | assert(0); | ||
250 | |||
251 | // install required directories | ||
252 | SysLib *ptr = &syslibs[0]; | ||
253 | while (ptr->library) { | ||
254 | if (ptr->found) { | ||
255 | assert(*ptr->message != '\0'); | ||
256 | timetrace_start(); | ||
257 | |||
258 | // bring in all libraries | ||
259 | assert(ptr->dir1); | ||
260 | char *name; | ||
261 | // Debian & friends | ||
262 | if (asprintf(&name, "/usr/lib/x86_64-linux-gnu/%s", ptr->dir1) == -1) | ||
263 | errExit("asprintf"); | ||
264 | if (access(name, R_OK) == 0) { | ||
265 | fslib_copy_libs(name); | ||
266 | fslib_copy_dir(name); | ||
267 | } | ||
268 | else { | ||
269 | free(name); | ||
270 | // CentOS, Fedora, Arch | ||
271 | if (asprintf(&name, "/usr/lib64/%s", ptr->dir1) == -1) | ||
272 | errExit("asprintf"); | ||
273 | if (access(name, R_OK) == 0) { | ||
274 | fslib_copy_libs(name); | ||
275 | fslib_copy_dir(name); | ||
276 | } | ||
277 | } | ||
278 | free(name); | ||
279 | |||
280 | if (*ptr->dir2 != '\0') { | ||
281 | // Debian & friends | ||
282 | if (asprintf(&name, "/usr/lib/x86_64-linux-gnu/%s", ptr->dir2) == -1) | ||
283 | errExit("asprintf"); | ||
284 | if (access(name, R_OK) == 0) { | ||
285 | fslib_copy_libs(name); | ||
286 | fslib_copy_dir(name); | ||
287 | } | ||
288 | else { | ||
289 | free(name); | ||
290 | // CentOS, Fedora, Arch | ||
291 | if (asprintf(&name, "/usr/lib64/%s", ptr->dir2) == -1) | ||
292 | errExit("asprintf"); | ||
293 | if (access(name, R_OK) == 0) { | ||
294 | fslib_copy_libs(name); | ||
295 | fslib_copy_dir(name); | ||
296 | } | ||
297 | } | ||
298 | free(name); | ||
299 | } | ||
300 | |||
301 | if (!arg_quiet) | ||
302 | fprintf(stderr, "%s installed in %0.2f ms\n", ptr->message, timetrace_end()); | ||
303 | } | ||
304 | ptr++; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | |||
309 | |||
310 | |||
311 | |||