aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2017-10-04 08:29:31 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2017-10-04 08:29:31 -0400
commit63e177af7278012d7064d4e1695d3a500f51c9eb (patch)
tree57b64ed01d1b888f2bc3db304a4928c6bd2eaa61
parentupdated authors list (diff)
downloadfirejail-63e177af7278012d7064d4e1695d3a500f51c9eb.tar.gz
firejail-63e177af7278012d7064d4e1695d3a500f51c9eb.tar.zst
firejail-63e177af7278012d7064d4e1695d3a500f51c9eb.zip
private-lib: add std C library and locale by default
-rw-r--r--src/firejail/fs_lib.c89
-rw-r--r--src/fldd/main.c26
2 files changed, 97 insertions, 18 deletions
diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c
index cdfd4a6e2..abd7cee1a 100644
--- a/src/firejail/fs_lib.c
+++ b/src/firejail/fs_lib.c
@@ -22,6 +22,7 @@
22#include <sys/stat.h> 22#include <sys/stat.h>
23#include <sys/types.h> 23#include <sys/types.h>
24#include <unistd.h> 24#include <unistd.h>
25#include <dirent.h>
25 26
26#define MAXBUF 4096 27#define MAXBUF 4096
27 28
@@ -133,6 +134,85 @@ static char *valid_file(const char *lib) {
133 return NULL; 134 return NULL;
134} 135}
135 136
137// standard libc libraries based on Debian's libc6 package
138// selinux seems to be linked in most command line utilities
139// locale (/usr/lib/locale) - without it, the program will default to "C" locale
140typedef struct liblist_t {
141 const char *name;
142 int len;
143} LibList;
144
145static LibList libc_list[] = {
146// { "locale", 0 }, hardcoded!
147 { "libselinux.so.", 0 },
148 { "ld-linux-x86-64.so.", 0 },
149 { "libanl.so.", 0 },
150 { "libc.so.", 0 },
151 { "libcidn.so.", 0 },
152 { "libcrypt.so.", 0 },
153 { "libdl.so.", 0 },
154 { "libm.so.", 0 },
155 { "libmemusage.so", 0 },
156 { "libmvec.so.", 0 },
157 { "libnsl.so.", 0 },
158 { "libnss_compat.so.", 0 },
159 { "libnss_dns.so.", 0 },
160 { "libnss_files.so.", 0 },
161 { "libnss_hesiod.so.", 0 },
162 { "libnss_nisplus.so.", 0 },
163 { "libnss_nis.so.", 0 },
164 { "libpthread.so.", 0 },
165 { "libresolv.so.", 0 },
166 { "librt.so.", 0 },
167 { "libthread_db.so.", 0 },
168 { "libutil.so.", 0 },
169 { NULL, 0}
170};
171
172static int find(const char *name) {
173 assert(name);
174
175 int i = 0;
176 while (libc_list[i].name) {
177 if (libc_list[i].len == 0)
178 libc_list[i].len = strlen(libc_list[i].name);
179 if (strncmp(name, libc_list[i].name, libc_list[i].len) == 0)
180 return 1;
181 i++;
182 }
183 return 0;
184}
185
186// compare the files in dirname against liblist above
187static void walk_directory(const char *dirname, const char *destdir) {
188 assert(dirname);
189 assert(destdir);
190
191 DIR *dir = opendir(dirname);
192 if (dir) {
193 struct dirent *entry;
194 while ((entry = readdir(dir)) != NULL) {
195 if (strcmp(entry->d_name, ".") == 0)
196 continue;
197 if (strcmp(entry->d_name, "..") == 0)
198 continue;
199
200 if (find(entry->d_name)) {
201 char *fname;
202 if (asprintf(&fname, "%s/%s", dirname, entry->d_name) == -1)
203 errExit("asprintf");
204
205 if (is_dir(fname))
206 copy_directory(fname, entry->d_name, RUN_LIB_DIR);
207 else
208 duplicate(fname, destdir);
209 }
210 }
211 closedir(dir);
212 }
213 else
214 fprintf(stderr, "Error: cannot open %s in order to set --private-lib\n", dirname);
215}
136 216
137void fs_private_lib(void) { 217void fs_private_lib(void) {
138#ifndef __x86_64__ 218#ifndef __x86_64__
@@ -149,14 +229,13 @@ void fs_private_lib(void) {
149 // create /run/firejail/mnt/lib directory 229 // create /run/firejail/mnt/lib directory
150 mkdir_attr(RUN_LIB_DIR, 0755, 0, 0); 230 mkdir_attr(RUN_LIB_DIR, 0755, 0, 0);
151 231
152 // fix libselinux linking problem on Debian stretch; the library is
153 // linked in most basic command utilities (ls, cp, find etc.), and it
154 // seems to have a path hardlinked under /lib/x86_64-linux-gnu directory.
155 struct stat s; 232 struct stat s;
156 if (stat("/lib/x86_64-linux-gnu/libselinux.so.1", &s) == 0) { 233 if (stat("/lib/x86_64-linux-gnu", &s) == 0) {
157 mkdir_attr(RUN_LIB_DIR "/x86_64-linux-gnu", 0755, 0, 0); 234 mkdir_attr(RUN_LIB_DIR "/x86_64-linux-gnu", 0755, 0, 0);
158 duplicate("/lib/x86_64-linux-gnu/libselinux.so.1", RUN_LIB_DIR "/x86_64-linux-gnu"); 235 walk_directory("/lib/x86_64-linux-gnu", RUN_LIB_DIR "/x86_64-linux-gnu");
159 } 236 }
237 if (stat("/usr/lib/locale", &s) == 0)
238 copy_directory("/usr/lib/locale", "locale", RUN_LIB_DIR);
160 239
161 // copy the libs in the new lib directory for the main exe 240 // copy the libs in the new lib directory for the main exe
162 if (cfg.original_program_index > 0) 241 if (cfg.original_program_index > 0)
diff --git a/src/fldd/main.c b/src/fldd/main.c
index 5fda45266..6127a4a87 100644
--- a/src/fldd/main.c
+++ b/src/fldd/main.c
@@ -94,12 +94,12 @@ static void storage_print(Storage *ptr, int fd) {
94 } 94 }
95} 95}
96 96
97static bool ptr_ok(const void *ptr, const void *base, const void *end, const char *name) { 97static bool ptr_ok(const void *ptr, const void *base, const void *end, const char *name, const char *exe) {
98 bool r; 98 bool r;
99 99
100 r = (ptr >= base && ptr <= end); 100 r = (ptr >= base && ptr <= end);
101 if (!r && !arg_quiet) 101 if (!r && !arg_quiet)
102 fprintf(stderr, "Warning: fldd: bad pointer %s\n", name); 102 fprintf(stderr, "Warning: fldd: bad pointer %s for %s\n", name, exe);
103 return r; 103 return r;
104} 104}
105 105
@@ -130,11 +130,11 @@ static void copy_libs_for_exe(const char *exe) {
130 } 130 }
131 131
132 Elf_Phdr *pbuf = (Elf_Phdr *)(base + sizeof(*ebuf)); 132 Elf_Phdr *pbuf = (Elf_Phdr *)(base + sizeof(*ebuf));
133 while (ebuf->e_phnum-- > 0 && ptr_ok(pbuf, base, end, "pbuf")) { 133 while (ebuf->e_phnum-- > 0 && ptr_ok(pbuf, base, end, "pbuf", exe)) {
134 switch (pbuf->p_type) { 134 switch (pbuf->p_type) {
135 case PT_INTERP: 135 case PT_INTERP:
136 // dynamic loader ld-linux.so 136 // dynamic loader ld-linux.so
137 if (!ptr_ok(base + pbuf->p_offset, base, end, "base + pbuf->p_offset")) 137 if (!ptr_ok(base + pbuf->p_offset, base, end, "base + pbuf->p_offset", exe))
138 goto close; 138 goto close;
139 139
140 storage_add(&libs, base + pbuf->p_offset); 140 storage_add(&libs, base + pbuf->p_offset);
@@ -144,16 +144,16 @@ static void copy_libs_for_exe(const char *exe) {
144 } 144 }
145 145
146 Elf_Shdr *sbuf = (Elf_Shdr *)(base + ebuf->e_shoff); 146 Elf_Shdr *sbuf = (Elf_Shdr *)(base + ebuf->e_shoff);
147 if (!ptr_ok(sbuf, base, end, "sbuf")) 147 if (!ptr_ok(sbuf, base, end, "sbuf", exe))
148 goto close; 148 goto close;
149 149
150 // Find strings section 150 // Find strings section
151 char *strbase = NULL; 151 char *strbase = NULL;
152 int sections = ebuf->e_shnum; 152 int sections = ebuf->e_shnum;
153 while (sections-- > 0 && ptr_ok(sbuf, base, end, "sbuf")) { 153 while (sections-- > 0 && ptr_ok(sbuf, base, end, "sbuf", exe)) {
154 if (sbuf->sh_type == SHT_STRTAB) { 154 if (sbuf->sh_type == SHT_STRTAB) {
155 strbase = base + sbuf->sh_offset; 155 strbase = base + sbuf->sh_offset;
156 if (!ptr_ok(strbase, base, end, "strbase")) 156 if (!ptr_ok(strbase, base, end, "strbase", exe))
157 goto close; 157 goto close;
158 break; 158 break;
159 } 159 }
@@ -164,7 +164,7 @@ static void copy_libs_for_exe(const char *exe) {
164 164
165 // Find dynamic section 165 // Find dynamic section
166 sections = ebuf->e_shnum; 166 sections = ebuf->e_shnum;
167 while (sections-- > 0 && ptr_ok(sbuf, base, end, "sbuf")) { 167 while (sections-- > 0 && ptr_ok(sbuf, base, end, "sbuf", exe)) {
168// TODO: running fldd on large gui programs (fldd /usr/bin/transmission-qt) 168// TODO: running fldd on large gui programs (fldd /usr/bin/transmission-qt)
169// crash on accessing memory location sbuf->sh_type if sbuf->sh_type in the previous section was 0 (SHT_NULL) 169// crash on accessing memory location sbuf->sh_type if sbuf->sh_type in the previous section was 0 (SHT_NULL)
170// for now we just exit the while loop - this is probably incorrect 170// for now we just exit the while loop - this is probably incorrect
@@ -173,14 +173,14 @@ static void copy_libs_for_exe(const char *exe) {
173 break; 173 break;
174 if (sbuf->sh_type == SHT_DYNAMIC) { 174 if (sbuf->sh_type == SHT_DYNAMIC) {
175 Elf_Dyn *dbuf = (Elf_Dyn *)(base + sbuf->sh_offset); 175 Elf_Dyn *dbuf = (Elf_Dyn *)(base + sbuf->sh_offset);
176 if (!ptr_ok(dbuf, base, end, "dbuf")) 176 if (!ptr_ok(dbuf, base, end, "dbuf", exe))
177 goto close; 177 goto close;
178 // Find DT_RPATH/DT_RUNPATH tags first 178 // Find DT_RPATH/DT_RUNPATH tags first
179 unsigned long size = sbuf->sh_size; 179 unsigned long size = sbuf->sh_size;
180 while (size >= sizeof(*dbuf) && ptr_ok(dbuf, base, end, "dbuf")) { 180 while (size >= sizeof(*dbuf) && ptr_ok(dbuf, base, end, "dbuf", exe)) {
181 if (dbuf->d_tag == DT_RPATH || dbuf->d_tag == DT_RUNPATH) { 181 if (dbuf->d_tag == DT_RPATH || dbuf->d_tag == DT_RUNPATH) {
182 const char *searchpath = strbase + dbuf->d_un.d_ptr; 182 const char *searchpath = strbase + dbuf->d_un.d_ptr;
183 if (!ptr_ok(searchpath, base, end, "searchpath")) 183 if (!ptr_ok(searchpath, base, end, "searchpath", exe))
184 goto close; 184 goto close;
185 storage_add(&lib_paths, searchpath); 185 storage_add(&lib_paths, searchpath);
186 } 186 }
@@ -190,10 +190,10 @@ static void copy_libs_for_exe(const char *exe) {
190 // Find DT_NEEDED tags 190 // Find DT_NEEDED tags
191 dbuf = (Elf_Dyn *)(base + sbuf->sh_offset); 191 dbuf = (Elf_Dyn *)(base + sbuf->sh_offset);
192 size = sbuf->sh_size; 192 size = sbuf->sh_size;
193 while (size >= sizeof(*dbuf) && ptr_ok(dbuf, base, end, "dbuf")) { 193 while (size >= sizeof(*dbuf) && ptr_ok(dbuf, base, end, "dbuf", exe)) {
194 if (dbuf->d_tag == DT_NEEDED) { 194 if (dbuf->d_tag == DT_NEEDED) {
195 const char *lib = strbase + dbuf->d_un.d_ptr; 195 const char *lib = strbase + dbuf->d_un.d_ptr;
196 if (!ptr_ok(lib, base, end, "lib")) 196 if (!ptr_ok(lib, base, end, "lib", exe))
197 goto close; 197 goto close;
198 copy_libs_for_lib(lib); 198 copy_libs_for_lib(lib);
199 } 199 }