aboutsummaryrefslogtreecommitdiffstats
path: root/src/fldd
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2017-08-04 11:14:04 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2017-08-04 11:14:04 -0400
commita9babdfbce0a88dd7a21584a514b1479bc4c98f6 (patch)
tree4966fc0ec278654b57a3bc9f865022fb1f21f49a /src/fldd
parentMerge branch 'master' of https://github.com/netblue30/firejail (diff)
downloadfirejail-a9babdfbce0a88dd7a21584a514b1479bc4c98f6.tar.gz
firejail-a9babdfbce0a88dd7a21584a514b1479bc4c98f6.tar.zst
firejail-a9babdfbce0a88dd7a21584a514b1479bc4c98f6.zip
private-lib: add src/fldd
Diffstat (limited to 'src/fldd')
-rw-r--r--src/fldd/Makefile.in45
-rw-r--r--src/fldd/main.c262
2 files changed, 307 insertions, 0 deletions
diff --git a/src/fldd/Makefile.in b/src/fldd/Makefile.in
new file mode 100644
index 000000000..7369c835b
--- /dev/null
+++ b/src/fldd/Makefile.in
@@ -0,0 +1,45 @@
1all: fldd
2
3CC=@CC@
4prefix=@prefix@
5exec_prefix=@exec_prefix@
6libdir=@libdir@
7sysconfdir=@sysconfdir@
8
9VERSION=@PACKAGE_VERSION@
10NAME=@PACKAGE_NAME@
11HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
12HAVE_SECCOMP=@HAVE_SECCOMP@
13HAVE_CHROOT=@HAVE_CHROOT@
14HAVE_BIND=@HAVE_BIND@
15HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
16HAVE_NETWORK=@HAVE_NETWORK@
17HAVE_USERNS=@HAVE_USERNS@
18HAVE_X11=@HAVE_X11@
19HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
20HAVE_WHITELIST=@HAVE_WHITELIST@
21HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
22HAVE_APPARMOR=@HAVE_APPARMOR@
23HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
24HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
25EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
26HAVE_GCOV=@HAVE_GCOV@
27EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
28
29H_FILE_LIST = $(sort $(wildcard *.[h]))
30C_FILE_LIST = $(sort $(wildcard *.c))
31OBJS = $(C_FILE_LIST:.c=.o)
32BINOBJS = $(foreach file, $(OBJS), $file)
33CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
34LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
35
36%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h
37 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
38
39fldd: $(OBJS)
40 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
41
42clean:; rm -f *.o fldd *.gcov *.gcda *.gcno
43
44distclean: clean
45 rm -fr Makefile
diff --git a/src/fldd/main.c b/src/fldd/main.c
new file mode 100644
index 000000000..8b54242a4
--- /dev/null
+++ b/src/fldd/main.c
@@ -0,0 +1,262 @@
1/*
2 * Copyright (C) 2014-2017 netblue30 (netblue30@yahoo.com)
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
21#include "../include/common.h"
22
23#include <elf.h>
24#include <fcntl.h>
25#include <sys/mman.h>
26#include <sys/mount.h>
27#include <sys/stat.h>
28#include <sys/types.h>
29#include <unistd.h>
30
31#ifdef __LP64__
32#define Elf_Ehdr Elf64_Ehdr
33#define Elf_Phdr Elf64_Phdr
34#define Elf_Shdr Elf64_Shdr
35#define Elf_Dyn Elf64_Dyn
36#else
37#define Elf_Ehdr Elf32_Ehdr
38#define Elf_Phdr Elf32_Phdr
39#define Elf_Shdr Elf32_Shdr
40#define Elf_Dyn Elf32_Dyn
41#endif
42
43static int arg_quiet = 0;
44static void copy_libs_for_lib(const char *lib);
45
46static const char * const lib_paths[] = {
47 "/lib",
48 "/lib/x86_64-linux-gnu",
49 "/lib64",
50 "/usr/lib",
51 "/usr/lib/x86_64-linux-gnu",
52 LIBDIR,
53 "/usr/local/lib",
54 NULL
55}; // Note: this array is duplicated in src/firejail/fs_lib.c
56
57
58typedef struct storage_t {
59 struct storage_t *next;
60 const char *name;
61} Storage;
62static Storage *head;
63
64// return 1 if found
65static int storage_find(const char *name) {
66 Storage *ptr = head;
67
68 while (ptr) {
69 if (strcmp(ptr->name, name) == 0)
70 return 1;
71 ptr = ptr->next;
72 }
73
74 return 0;
75}
76
77static void storage_add(const char *name) {
78 if (storage_find(name))
79 return;
80
81 Storage *s = malloc(sizeof(Storage));
82 if (!s)
83 errExit("malloc");
84 s->next = head;
85 head = s;
86 s->name = strdup(name);
87 if (!s->name)
88 errExit("strdup");
89}
90
91
92static void storage_print(int fd) {
93 Storage *ptr = head;
94
95 while (ptr) {
96 dprintf(fd, "%s\n", ptr->name);
97 ptr = ptr->next;
98 }
99}
100
101
102
103static void copy_libs_for_exe(const char *exe) {
104 int f;
105 f = open(exe, O_RDONLY);
106 if (f < 0) {
107 if (!arg_quiet)
108 fprintf(stderr, "Warning fldd: cannot open %s\n", exe);
109 return;
110 }
111
112 struct stat s;
113 char *base = NULL;
114 if (fstat(f, &s) == -1)
115 goto error_close;
116 base = mmap(0, s.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, f, 0);
117 if (base == MAP_FAILED)
118 goto error_close;
119
120
121 Elf_Ehdr *ebuf = (Elf_Ehdr *)base;
122 if (strncmp((const char *)ebuf->e_ident, ELFMAG, SELFMAG) != 0) {
123 if (!arg_quiet)
124 fprintf(stderr, "Warning fldd: %s is not an ELF executable or library\n", exe);
125 goto close;
126 }
127
128 Elf_Phdr *pbuf = (Elf_Phdr *)(base + sizeof(*ebuf));
129 while (ebuf->e_phnum-- > 0) {
130 switch (pbuf->p_type) {
131 case PT_INTERP:
132 // dynamic loader ld-linux.so
133 storage_add(base + pbuf->p_offset);
134 break;
135 }
136 pbuf++;
137 }
138
139 Elf_Shdr *sbuf = (Elf_Shdr *)(base + ebuf->e_shoff);
140
141 // Find strings section
142 char *strbase = NULL;
143 int sections = ebuf->e_shnum;
144 while (sections-- > 0) {
145 if (sbuf->sh_type == SHT_STRTAB) {
146 strbase = base + sbuf->sh_offset;
147 break;
148 }
149 sbuf++;
150 }
151 if (strbase == NULL)
152 goto error_close;
153
154 // Find dynamic section
155 sections = ebuf->e_shnum;
156 while (sections-- > 0) {
157// TODO: running fldd on large gui programs (fldd /usr/bin/transmission-qt)
158// crash on accessing memory location sbuf->sh_type if sbuf->sh_type in the previous section was 0 (SHT_NULL)
159// for now we just exit the while loop - this is probably incorrect
160// printf("sbuf %p #%s#, sections %d, type %u\n", sbuf, exe, sections, sbuf->sh_type);
161 if (sbuf->sh_type == SHT_NULL)
162 break;
163 if (sbuf->sh_type == SHT_DYNAMIC) {
164 // Find DT_NEEDED tags
165 Elf_Dyn *dbuf = (Elf_Dyn *)(base + sbuf->sh_offset);
166 while (sbuf->sh_size >= sizeof(*dbuf)) {
167 if (dbuf->d_tag == DT_NEEDED) {
168 const char *lib = strbase + dbuf->d_un.d_ptr;
169 copy_libs_for_lib(lib);
170 }
171 sbuf->sh_size -= sizeof(*dbuf);
172 dbuf++;
173 }
174 }
175 sbuf++;
176 }
177 goto close;
178
179 error_close:
180 perror("copy libs");
181 close:
182 if (base)
183 munmap(base, s.st_size);
184
185 close(f);
186}
187
188static void copy_libs_for_lib(const char *lib) {
189 int i;
190 for (i = 0; lib_paths[i]; i++) {
191 char *fname;
192 if (asprintf(&fname, "%s/%s", lib_paths[i], lib) == -1)
193 errExit("asprintf");
194 if (access(fname, R_OK) == 0) {
195 if (!storage_find(fname)) {
196 storage_add(fname);
197 // libs may need other libs
198 copy_libs_for_exe(fname);
199 }
200 free(fname);
201 return;
202 }
203 free(fname);
204 }
205 errExit("library not found");
206}
207
208static void usage(void) {
209 printf("Usage: fldd program [file]\n");
210 printf("print a list of libraries used by program or store it in the file.\n");
211}
212
213int main(int argc, char **argv) {
214#if 0
215{
216//system("cat /proc/self/status");
217int i;
218for (i = 0; i < argc; i++)
219 printf("*%s* ", argv[i]);
220printf("\n");
221}
222#endif
223 if (argc < 2) {
224 fprintf(stderr, "Error fldd: invalid arguments\n");
225 usage();
226 exit(1);
227 }
228
229
230 // check program access
231 if (access(argv[1], R_OK)) {
232 fprintf(stderr, "Error fldd: cannot access %s\n", argv[1]);
233 exit(1);
234 }
235
236 char *quiet = getenv("FIREJAIL_QUIET");
237 if (quiet && strcmp(quiet, "yes") == 0)
238 arg_quiet = 1;
239
240 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) {
241 usage();
242 return 0;
243 }
244
245 int fd = STDOUT_FILENO;
246 // attempt to open the file
247 if (argc == 3) {
248 fd = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY, 0644);
249 if (!fd) {
250 fprintf(stderr, "Error fldd: invalid arguments\n");
251 usage();
252 exit(1);
253 }
254 }
255
256 copy_libs_for_exe(argv[1]);
257 storage_print(fd);
258 if (argc == 3)
259 close(fd);
260
261 return 0;
262}