aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail')
-rw-r--r--src/firejail/Makefile.in1
-rw-r--r--src/firejail/appimage.c22
-rw-r--r--src/firejail/appimage_size.c2
-rw-r--r--src/firejail/arg-checking.txt9
-rw-r--r--src/firejail/arp.c28
-rw-r--r--src/firejail/bandwidth.c56
-rw-r--r--src/firejail/caps.c28
-rw-r--r--src/firejail/cgroup.c24
-rw-r--r--src/firejail/checkcfg.c36
-rw-r--r--src/firejail/cmdline.c8
-rw-r--r--src/firejail/cpu.c21
-rw-r--r--src/firejail/env.c22
-rw-r--r--src/firejail/fs.c150
-rw-r--r--src/firejail/fs_bin.c29
-rw-r--r--src/firejail/fs_etc.c27
-rw-r--r--src/firejail/fs_home.c40
-rw-r--r--src/firejail/fs_hostname.c19
-rw-r--r--src/firejail/fs_logger.c12
-rw-r--r--src/firejail/fs_mkdir.c8
-rw-r--r--src/firejail/fs_trace.c5
-rw-r--r--src/firejail/fs_var.c44
-rw-r--r--src/firejail/fs_whitelist.c98
-rw-r--r--src/firejail/git.c16
-rw-r--r--src/firejail/join.c37
-rw-r--r--src/firejail/ls.c58
-rw-r--r--src/firejail/netfilter.c10
-rw-r--r--src/firejail/network.c37
-rw-r--r--src/firejail/network.txt16
-rw-r--r--src/firejail/network_main.c16
-rw-r--r--src/firejail/no_sandbox.c20
-rw-r--r--src/firejail/output.c12
-rw-r--r--src/firejail/preproc.c16
-rw-r--r--src/firejail/protocol.c8
-rw-r--r--src/firejail/pulseaudio.c24
-rw-r--r--src/firejail/restrict_users.c42
-rw-r--r--src/firejail/restricted_shell.c17
-rw-r--r--src/firejail/rlimit.c4
-rw-r--r--src/firejail/run_symlink.c8
-rw-r--r--src/firejail/sbox.c52
-rw-r--r--src/firejail/seccomp.c27
-rw-r--r--src/firejail/shutdown.c10
-rw-r--r--src/firejail/util.c18
-rw-r--r--src/firejail/x11.c6
43 files changed, 563 insertions, 580 deletions
diff --git a/src/firejail/Makefile.in b/src/firejail/Makefile.in
index 80f35ff4d..2059713ac 100644
--- a/src/firejail/Makefile.in
+++ b/src/firejail/Makefile.in
@@ -42,4 +42,3 @@ clean:; rm -f *.o firejail firejail.1 firejail.1.gz *.gcov *.gcda *.gcno
42 42
43distclean: clean 43distclean: clean
44 rm -fr Makefile 44 rm -fr Makefile
45
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c
index e14de3c27..976750f8f 100644
--- a/src/firejail/appimage.c
+++ b/src/firejail/appimage.c
@@ -28,7 +28,7 @@
28#include <linux/loop.h> 28#include <linux/loop.h>
29#include <errno.h> 29#include <errno.h>
30 30
31static char *devloop = NULL; // device file 31static char *devloop = NULL; // device file
32static char *mntdir = NULL; // mount point in /tmp directory 32static char *mntdir = NULL; // mount point in /tmp directory
33 33
34static void err_loop(void) { 34static void err_loop(void) {
@@ -40,7 +40,7 @@ void appimage_set(const char *appimage) {
40 assert(appimage); 40 assert(appimage);
41 assert(devloop == NULL); // don't call this twice! 41 assert(devloop == NULL); // don't call this twice!
42 EUID_ASSERT(); 42 EUID_ASSERT();
43 43
44#ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h 44#ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h
45 // check appimage file 45 // check appimage file
46 invalid_filename(appimage); 46 invalid_filename(appimage);
@@ -74,13 +74,13 @@ void appimage_set(const char *appimage) {
74 close(cfd); 74 close(cfd);
75 if (asprintf(&devloop, "/dev/loop%d", devnr) == -1) 75 if (asprintf(&devloop, "/dev/loop%d", devnr) == -1)
76 errExit("asprintf"); 76 errExit("asprintf");
77 77
78 int lfd = open(devloop, O_RDONLY); 78 int lfd = open(devloop, O_RDONLY);
79 if (lfd == -1) 79 if (lfd == -1)
80 err_loop(); 80 err_loop();
81 if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) 81 if (ioctl(lfd, LOOP_SET_FD, ffd) == -1)
82 err_loop(); 82 err_loop();
83 83
84 if (size) { 84 if (size) {
85 struct loop_info64 info; 85 struct loop_info64 info;
86 memset(&info, 0, sizeof(struct loop_info64)); 86 memset(&info, 0, sizeof(struct loop_info64));
@@ -88,7 +88,7 @@ void appimage_set(const char *appimage) {
88 if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1) 88 if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1)
89 err_loop(); 89 err_loop();
90 } 90 }
91 91
92 close(lfd); 92 close(lfd);
93 close(ffd); 93 close(ffd);
94 EUID_USER(); 94 EUID_USER();
@@ -99,13 +99,13 @@ void appimage_set(const char *appimage) {
99 EUID_ROOT(); 99 EUID_ROOT();
100 mkdir_attr(mntdir, 0700, getuid(), getgid()); 100 mkdir_attr(mntdir, 0700, getuid(), getgid());
101 EUID_USER(); 101 EUID_USER();
102 102
103 // mount 103 // mount
104 char *mode; 104 char *mode;
105 if (asprintf(&mode, "mode=700,uid=%d,gid=%d", getuid(), getgid()) == -1) 105 if (asprintf(&mode, "mode=700,uid=%d,gid=%d", getuid(), getgid()) == -1)
106 errExit("asprintf"); 106 errExit("asprintf");
107 EUID_ROOT(); 107 EUID_ROOT();
108 108
109 if (size == 0) { 109 if (size == 0) {
110 if (mount(devloop, mntdir, "iso9660",MS_MGC_VAL|MS_RDONLY, mode) < 0) 110 if (mount(devloop, mntdir, "iso9660",MS_MGC_VAL|MS_RDONLY, mode) < 0)
111 errExit("mounting appimage"); 111 errExit("mounting appimage");
@@ -128,7 +128,7 @@ void appimage_set(const char *appimage) {
128 // build new command line 128 // build new command line
129 if (asprintf(&cfg.command_line, "%s/AppRun", mntdir) == -1) 129 if (asprintf(&cfg.command_line, "%s/AppRun", mntdir) == -1)
130 errExit("asprintf"); 130 errExit("asprintf");
131 131
132 free(mode); 132 free(mode);
133#ifdef HAVE_GCOV 133#ifdef HAVE_GCOV
134 __gcov_flush(); 134 __gcov_flush();
@@ -151,7 +151,7 @@ void appimage_clear(void) {
151 if (rv == 0) { 151 if (rv == 0) {
152 if (!arg_quiet) 152 if (!arg_quiet)
153 printf("AppImage unmounted\n"); 153 printf("AppImage unmounted\n");
154 154
155 break; 155 break;
156 } 156 }
157 if (rv == -1 && errno == EBUSY) { 157 if (rv == -1 && errno == EBUSY) {
@@ -159,14 +159,14 @@ void appimage_clear(void) {
159 sleep(2); 159 sleep(2);
160 continue; 160 continue;
161 } 161 }
162 162
163 // rv = -1 163 // rv = -1
164 if (!arg_quiet) { 164 if (!arg_quiet) {
165 fwarning("error trying to unmount %s\n", mntdir); 165 fwarning("error trying to unmount %s\n", mntdir);
166 perror("umount"); 166 perror("umount");
167 } 167 }
168 } 168 }
169 169
170 if (rv == 0) { 170 if (rv == 0) {
171 rmdir(mntdir); 171 rmdir(mntdir);
172 free(mntdir); 172 free(mntdir);
diff --git a/src/firejail/appimage_size.c b/src/firejail/appimage_size.c
index 1632440ed..c750f9028 100644
--- a/src/firejail/appimage_size.c
+++ b/src/firejail/appimage_size.c
@@ -156,5 +156,3 @@ getout:
156 close(fd); 156 close(fd);
157 return size; 157 return size;
158} 158}
159
160
diff --git a/src/firejail/arg-checking.txt b/src/firejail/arg-checking.txt
index 07e61df93..cfed454f8 100644
--- a/src/firejail/arg-checking.txt
+++ b/src/firejail/arg-checking.txt
@@ -49,7 +49,7 @@ arg checking:
49 - checking no link 49 - checking no link
50 - checking no ".." 50 - checking no ".."
51 - unit test 51 - unit test
52 52
538. --private=dirname 538. --private=dirname
54 - supported in profiles 54 - supported in profiles
55 - expand "~" 55 - expand "~"
@@ -58,7 +58,7 @@ arg checking:
58 - checking no ".." 58 - checking no ".."
59 - check same owner 59 - check same owner
60 - unit test 60 - unit test
61 61
629. --private-home=filelist 629. --private-home=filelist
63 - supported in profiles 63 - supported in profiles
64 - checking no ".." 64 - checking no ".."
@@ -66,7 +66,7 @@ arg checking:
66 - checking same owner 66 - checking same owner
67 - checking no link 67 - checking no link
68 - unit test 68 - unit test
69 69
7010. --netfilter=filename 7010. --netfilter=filename
71 - supported in profiles 71 - supported in profiles
72 - check access as real GID/UID 72 - check access as real GID/UID
@@ -74,7 +74,7 @@ arg checking:
74 - checking no link 74 - checking no link
75 - checking no ".." 75 - checking no ".."
76 - unit test 76 - unit test
77 77
7811. --shell=filename 7811. --shell=filename
79 - not supported in profiles 79 - not supported in profiles
80 - check access as real GID/UID 80 - check access as real GID/UID
@@ -82,4 +82,3 @@ arg checking:
82 - checking no link 82 - checking no link
83 - checking no ".." 83 - checking no ".."
84 - unit test 84 - unit test
85
diff --git a/src/firejail/arp.c b/src/firejail/arp.c
index 55ffbb301..10cfe507f 100644
--- a/src/firejail/arp.c
+++ b/src/firejail/arp.c
@@ -47,7 +47,7 @@ int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) {
47 fprintf(stderr, "Error: invalid network device name %s\n", dev); 47 fprintf(stderr, "Error: invalid network device name %s\n", dev);
48 exit(1); 48 exit(1);
49 } 49 }
50 50
51 if (arg_debug) 51 if (arg_debug)
52 printf("Trying %d.%d.%d.%d ...\n", PRINT_IP(destaddr)); 52 printf("Trying %d.%d.%d.%d ...\n", PRINT_IP(destaddr));
53 53
@@ -66,7 +66,7 @@ int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) {
66 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) 66 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
67 errExit("ioctl"); 67 errExit("ioctl");
68 close(sock); 68 close(sock);
69 69
70 // configure layer2 socket address information 70 // configure layer2 socket address information
71 struct sockaddr_ll addr; 71 struct sockaddr_ll addr;
72 memset(&addr, 0, sizeof(addr)); 72 memset(&addr, 0, sizeof(addr));
@@ -105,7 +105,7 @@ int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) {
105 if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0) 105 if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0)
106 errExit("send"); 106 errExit("send");
107 fflush(0); 107 fflush(0);
108 108
109 // wait not more than one second for an answer 109 // wait not more than one second for an answer
110 fd_set fds; 110 fd_set fds;
111 FD_ZERO(&fds); 111 FD_ZERO(&fds);
@@ -130,7 +130,7 @@ int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) {
130 close(sock); 130 close(sock);
131 return -1; 131 return -1;
132 } 132 }
133 133
134 // parse the incoming packet 134 // parse the incoming packet
135 if ((unsigned int) len < 14 + sizeof(ArpHdr)) 135 if ((unsigned int) len < 14 + sizeof(ArpHdr))
136 continue; 136 continue;
@@ -147,7 +147,7 @@ int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) {
147 memcpy(&ip, hdr.target_ip, 4); 147 memcpy(&ip, hdr.target_ip, 4);
148 if (ip != srcaddr) { 148 if (ip != srcaddr) {
149 continue; 149 continue;
150 } 150 }
151 close(sock); 151 close(sock);
152 return -1; 152 return -1;
153 } 153 }
@@ -180,13 +180,13 @@ static uint32_t arp_random(const char *dev, Bridge *br) {
180 return 0; // the user will have to set the IP address manually 180 return 0; // the user will have to set the IP address manually
181 range -= 2; // subtract the network address and the broadcast address 181 range -= 2; // subtract the network address and the broadcast address
182 uint32_t start = (ifip & ifmask) + 1; 182 uint32_t start = (ifip & ifmask) + 1;
183 183
184 // adjust range based on --iprange params 184 // adjust range based on --iprange params
185 if (br->iprange_start && br->iprange_end) { 185 if (br->iprange_start && br->iprange_end) {
186 start = br->iprange_start; 186 start = br->iprange_start;
187 range = br->iprange_end - br->iprange_start; 187 range = br->iprange_end - br->iprange_start;
188 } 188 }
189 189
190 if (arg_debug) 190 if (arg_debug)
191 printf("IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n", 191 printf("IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n",
192 PRINT_IP(start), PRINT_IP(start + range)); 192 PRINT_IP(start), PRINT_IP(start + range));
@@ -198,13 +198,13 @@ static uint32_t arp_random(const char *dev, Bridge *br) {
198 dest = start + ((uint32_t) rand()) % range; 198 dest = start + ((uint32_t) rand()) % range;
199 if (dest == ifip) // do not allow the interface address 199 if (dest == ifip) // do not allow the interface address
200 continue; // try again 200 continue; // try again
201 201
202 // if we've made it up to here, we have a valid address 202 // if we've made it up to here, we have a valid address
203 break; 203 break;
204 } 204 }
205 if (i == 10) // we failed 10 times 205 if (i == 10) // we failed 10 times
206 return 0; 206 return 0;
207 207
208 // check address 208 // check address
209 uint32_t rv = arp_check(dev, dest, ifip); 209 uint32_t rv = arp_check(dev, dest, ifip);
210 if (!rv) 210 if (!rv)
@@ -237,7 +237,7 @@ static uint32_t arp_sequential(const char *dev, Bridge *br) {
237 uint32_t last = dest + range - 1; 237 uint32_t last = dest + range - 1;
238 if (br->iprange_end) 238 if (br->iprange_end)
239 last = br->iprange_end; 239 last = br->iprange_end;
240 240
241 if (arg_debug) 241 if (arg_debug)
242 printf("Trying IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n", 242 printf("Trying IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n",
243 PRINT_IP(dest), PRINT_IP(last)); 243 PRINT_IP(dest), PRINT_IP(last));
@@ -272,19 +272,17 @@ uint32_t arp_assign(const char *dev, Bridge *br) {
272 ip = arp_random(dev, br); 272 ip = arp_random(dev, br);
273 if (!ip) 273 if (!ip)
274 ip = arp_random(dev, br); 274 ip = arp_random(dev, br);
275 275
276 // try all possible IP addresses one by one 276 // try all possible IP addresses one by one
277 if (!ip) 277 if (!ip)
278 ip = arp_sequential(dev, br); 278 ip = arp_sequential(dev, br);
279 279
280 // print result 280 // print result
281 if (!ip) { 281 if (!ip) {
282 fprintf(stderr, "Error: cannot assign an IP address; it looks like all of them are in use.\n"); 282 fprintf(stderr, "Error: cannot assign an IP address; it looks like all of them are in use.\n");
283 logerr("Cannot assign an IP address; it looks like all of them are in use."); 283 logerr("Cannot assign an IP address; it looks like all of them are in use.");
284 exit(1); 284 exit(1);
285 } 285 }
286 286
287 return ip; 287 return ip;
288} 288}
289
290
diff --git a/src/firejail/bandwidth.c b/src/firejail/bandwidth.c
index 998fe5ffe..24d027d54 100644
--- a/src/firejail/bandwidth.c
+++ b/src/firejail/bandwidth.c
@@ -58,30 +58,30 @@ IFBW *ifbw_find(const char *dev) {
58 assert(dev); 58 assert(dev);
59 int len = strlen(dev); 59 int len = strlen(dev);
60 assert(len); 60 assert(len);
61 61
62 if (ifbw == NULL) 62 if (ifbw == NULL)
63 return NULL; 63 return NULL;
64 64
65 IFBW *ptr = ifbw; 65 IFBW *ptr = ifbw;
66 while (ptr) { 66 while (ptr) {
67 if (strncmp(ptr->txt, dev, len) == 0 && ptr->txt[len] == ':') 67 if (strncmp(ptr->txt, dev, len) == 0 && ptr->txt[len] == ':')
68 return ptr; 68 return ptr;
69 ptr = ptr->next; 69 ptr = ptr->next;
70 } 70 }
71 71
72 return NULL; 72 return NULL;
73} 73}
74 74
75void ifbw_remove(IFBW *r) { 75void ifbw_remove(IFBW *r) {
76 if (ifbw == NULL) 76 if (ifbw == NULL)
77 return; 77 return;
78 78
79 // remove the first element 79 // remove the first element
80 if (ifbw == r) { 80 if (ifbw == r) {
81 ifbw = ifbw->next; 81 ifbw = ifbw->next;
82 return; 82 return;
83 } 83 }
84 84
85 // walk the list 85 // walk the list
86 IFBW *ptr = ifbw->next; 86 IFBW *ptr = ifbw->next;
87 IFBW *prev = ifbw; 87 IFBW *prev = ifbw;
@@ -90,11 +90,11 @@ void ifbw_remove(IFBW *r) {
90 prev->next = ptr->next; 90 prev->next = ptr->next;
91 return; 91 return;
92 } 92 }
93 93
94 prev = ptr; 94 prev = ptr;
95 ptr = ptr->next; 95 ptr = ptr->next;
96 } 96 }
97 97
98 return; 98 return;
99} 99}
100 100
@@ -106,10 +106,10 @@ int fibw_count(void) {
106 rv++; 106 rv++;
107 ptr = ptr->next; 107 ptr = ptr->next;
108 } 108 }
109 109
110 return rv; 110 return rv;
111} 111}
112 112
113 113
114//*********************************** 114//***********************************
115// run file handling 115// run file handling
@@ -118,7 +118,7 @@ static void bandwidth_create_run_file(pid_t pid) {
118 char *fname; 118 char *fname;
119 if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) 119 if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1)
120 errExit("asprintf"); 120 errExit("asprintf");
121 121
122 // if the file already exists, do nothing 122 // if the file already exists, do nothing
123 struct stat s; 123 struct stat s;
124 if (stat(fname, &s) == 0) { 124 if (stat(fname, &s) == 0) {
@@ -137,7 +137,7 @@ static void bandwidth_create_run_file(pid_t pid) {
137 fprintf(stderr, "Error: cannot create bandwidth file\n"); 137 fprintf(stderr, "Error: cannot create bandwidth file\n");
138 exit(1); 138 exit(1);
139 } 139 }
140 140
141 free(fname); 141 free(fname);
142} 142}
143 143
@@ -162,7 +162,7 @@ void network_set_run_file(pid_t pid) {
162 char *fname; 162 char *fname;
163 if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1) 163 if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1)
164 errExit("asprintf"); 164 errExit("asprintf");
165 165
166 // create an empty file and set mod and ownership 166 // create an empty file and set mod and ownership
167 FILE *fp = fopen(fname, "w"); 167 FILE *fp = fopen(fname, "w");
168 if (fp) { 168 if (fp) {
@@ -182,7 +182,7 @@ void network_set_run_file(pid_t pid) {
182 fprintf(stderr, "Error: cannot create network map file\n"); 182 fprintf(stderr, "Error: cannot create network map file\n");
183 exit(1); 183 exit(1);
184 } 184 }
185 185
186 free(fname); 186 free(fname);
187} 187}
188 188
@@ -204,7 +204,7 @@ static void read_bandwidth_file(pid_t pid) {
204 *ptr = '\0'; 204 *ptr = '\0';
205 if (strlen(buf) == 0) 205 if (strlen(buf) == 0)
206 continue; 206 continue;
207 207
208 // create a new IFBW entry 208 // create a new IFBW entry
209 IFBW *ifbw_new = malloc(sizeof(IFBW)); 209 IFBW *ifbw_new = malloc(sizeof(IFBW));
210 if (!ifbw_new) 210 if (!ifbw_new)
@@ -213,12 +213,12 @@ static void read_bandwidth_file(pid_t pid) {
213 ifbw_new->txt = strdup(buf); 213 ifbw_new->txt = strdup(buf);
214 if (!ifbw_new->txt) 214 if (!ifbw_new->txt)
215 errExit("strdup"); 215 errExit("strdup");
216 216
217 // add it to the linked list 217 // add it to the linked list
218 ifbw_add(ifbw_new); 218 ifbw_add(ifbw_new);
219 } 219 }
220 220
221 fclose(fp); 221 fclose(fp);
222 } 222 }
223} 223}
224 224
@@ -256,17 +256,17 @@ errout:
256// remove interface from run file 256// remove interface from run file
257void bandwidth_remove(pid_t pid, const char *dev) { 257void bandwidth_remove(pid_t pid, const char *dev) {
258 bandwidth_create_run_file(pid); 258 bandwidth_create_run_file(pid);
259 259
260 // read bandwidth file 260 // read bandwidth file
261 read_bandwidth_file(pid); 261 read_bandwidth_file(pid);
262 262
263 // find the element and remove it 263 // find the element and remove it
264 IFBW *elem = ifbw_find(dev); 264 IFBW *elem = ifbw_find(dev);
265 if (elem) { 265 if (elem) {
266 ifbw_remove(elem); 266 ifbw_remove(elem);
267 write_bandwidth_file(pid) ; 267 write_bandwidth_file(pid) ;
268 } 268 }
269 269
270 // remove the file if there are no entries in the list 270 // remove the file if there are no entries in the list
271 if (ifbw == NULL) { 271 if (ifbw == NULL) {
272 bandwidth_del_run_file(pid); 272 bandwidth_del_run_file(pid);
@@ -282,7 +282,7 @@ void bandwidth_set(pid_t pid, const char *dev, int down, int up) {
282 char *txt; 282 char *txt;
283 if (asprintf(&txt, "%s: RX %dKB/s, TX %dKB/s", dev, down, up) == -1) 283 if (asprintf(&txt, "%s: RX %dKB/s, TX %dKB/s", dev, down, up) == -1)
284 errExit("asprintf"); 284 errExit("asprintf");
285 285
286 // read bandwidth file 286 // read bandwidth file
287 read_bandwidth_file(pid); 287 read_bandwidth_file(pid);
288 288
@@ -300,7 +300,7 @@ void bandwidth_set(pid_t pid, const char *dev, int down, int up) {
300 errExit("malloc"); 300 errExit("malloc");
301 memset(ifbw_new, 0, sizeof(IFBW)); 301 memset(ifbw_new, 0, sizeof(IFBW));
302 ifbw_new->txt = txt; 302 ifbw_new->txt = txt;
303 303
304 // add it to the linked list 304 // add it to the linked list
305 ifbw_add(ifbw_new); 305 ifbw_add(ifbw_new);
306 } 306 }
@@ -330,7 +330,7 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in
330 exit(1); 330 exit(1);
331 } 331 }
332 free(comm); 332 free(comm);
333 333
334 // check network namespace 334 // check network namespace
335 char *name; 335 char *name;
336 if (asprintf(&name, "/run/firejail/network/%d-netmap", pid) == -1) 336 if (asprintf(&name, "/run/firejail/network/%d-netmap", pid) == -1)
@@ -376,7 +376,7 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in
376 fprintf(stderr, "Error: cannot read network map file %s\n", fname); 376 fprintf(stderr, "Error: cannot read network map file %s\n", fname);
377 exit(1); 377 exit(1);
378 } 378 }
379 379
380 char buf[1024]; 380 char buf[1024];
381 int len = strlen(dev); 381 int len = strlen(dev);
382 while (fgets(buf, 1024, fp)) { 382 while (fgets(buf, 1024, fp)) {
@@ -402,7 +402,7 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in
402 free(fname); 402 free(fname);
403 fclose(fp); 403 fclose(fp);
404 } 404 }
405 405
406 // build fshaper.sh command 406 // build fshaper.sh command
407 char *cmd = NULL; 407 char *cmd = NULL;
408 if (devname) { 408 if (devname) {
@@ -442,7 +442,7 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in
442 arg[3] = NULL; 442 arg[3] = NULL;
443 clearenv(); 443 clearenv();
444 execvp(arg[0], arg); 444 execvp(arg[0], arg);
445 445
446 // it will never get here 446 // it will never get here
447 errExit("execvp"); 447 errExit("execvp");
448} 448}
diff --git a/src/firejail/caps.c b/src/firejail/caps.c
index 30693f7a0..d45ba20ce 100644
--- a/src/firejail/caps.c
+++ b/src/firejail/caps.c
@@ -154,12 +154,12 @@ static CapsEntry capslist[] = {
154// not in Debian 7 154// not in Debian 7
155#ifdef CAP_BLOCK_SUSPEND 155#ifdef CAP_BLOCK_SUSPEND
156 {"block_suspend", CAP_BLOCK_SUSPEND }, 156 {"block_suspend", CAP_BLOCK_SUSPEND },
157#else 157#else
158 {"block_suspend", 36 }, 158 {"block_suspend", 36 },
159#endif 159#endif
160#ifdef CAP_AUDIT_READ 160#ifdef CAP_AUDIT_READ
161 {"audit_read", CAP_AUDIT_READ }, 161 {"audit_read", CAP_AUDIT_READ },
162#else 162#else
163 {"audit_read", 37 }, 163 {"audit_read", 37 },
164#endif 164#endif
165 165
@@ -176,7 +176,7 @@ static int caps_find_name(const char *name) {
176 if (strcmp(name, capslist[i].name) == 0) 176 if (strcmp(name, capslist[i].name) == 0)
177 return capslist[i].nr; 177 return capslist[i].nr;
178 } 178 }
179 179
180 return -1; 180 return -1;
181} 181}
182 182
@@ -205,32 +205,32 @@ void caps_check_list(const char *clist, void (*callback)(int)) {
205 goto errexit; 205 goto errexit;
206 else if (callback != NULL) 206 else if (callback != NULL)
207 callback(nr); 207 callback(nr);
208 208
209 start = ptr + 1; 209 start = ptr + 1;
210 } 210 }
211 ptr++; 211 ptr++;
212 } 212 }
213 if (*start != '\0') { 213 if (*start != '\0') {
214 int nr = caps_find_name(start); 214 int nr = caps_find_name(start);
215 if (nr == -1) 215 if (nr == -1)
216 goto errexit; 216 goto errexit;
217 else if (callback != NULL) 217 else if (callback != NULL)
218 callback(nr); 218 callback(nr);
219 } 219 }
220 220
221 free(str); 221 free(str);
222 return; 222 return;
223 223
224errexit: 224errexit:
225 fprintf(stderr, "Error: capability \"%s\" not found\n", start); 225 fprintf(stderr, "Error: capability \"%s\" not found\n", start);
226 exit(1); 226 exit(1);
227} 227}
228 228
229void caps_print(void) { 229void caps_print(void) {
230 EUID_ASSERT(); 230 EUID_ASSERT();
231 int i; 231 int i;
232 int elems = sizeof(capslist) / sizeof(capslist[0]); 232 int elems = sizeof(capslist) / sizeof(capslist[0]);
233 233
234 // check current caps supported by the kernel 234 // check current caps supported by the kernel
235 int cnt = 0; 235 int cnt = 0;
236 unsigned long cap; 236 unsigned long cap;
@@ -242,7 +242,7 @@ void caps_print(void) {
242 } 242 }
243 EUID_USER(); 243 EUID_USER();
244 printf("Your kernel supports %d capabilities.\n", cnt); 244 printf("Your kernel supports %d capabilities.\n", cnt);
245 245
246 for (i = 0; i < elems; i++) { 246 for (i = 0; i < elems; i++) {
247 printf("%d\t- %s\n", capslist[i].nr, capslist[i].name); 247 printf("%d\t- %s\n", capslist[i].nr, capslist[i].name);
248 } 248 }
@@ -300,7 +300,7 @@ int caps_default_filter(void) {
300 300
301errexit: 301errexit:
302 fprintf(stderr, "Error: cannot drop capabilities\n"); 302 fprintf(stderr, "Error: cannot drop capabilities\n");
303 exit(1); 303 exit(1);
304} 304}
305 305
306void caps_drop_all(void) { 306void caps_drop_all(void) {
@@ -359,7 +359,7 @@ void caps_keep_list(const char *clist) {
359#define MAXBUF 4098 359#define MAXBUF 4098
360static uint64_t extract_caps(int pid) { 360static uint64_t extract_caps(int pid) {
361 EUID_ASSERT(); 361 EUID_ASSERT();
362 362
363 char *file; 363 char *file;
364 if (asprintf(&file, "/proc/%d/status", pid) == -1) 364 if (asprintf(&file, "/proc/%d/status", pid) == -1)
365 errExit("asprintf"); 365 errExit("asprintf");
@@ -369,7 +369,7 @@ static uint64_t extract_caps(int pid) {
369 EUID_USER(); // grsecurity 369 EUID_USER(); // grsecurity
370 if (!fp) 370 if (!fp)
371 goto errexit; 371 goto errexit;
372 372
373 char buf[MAXBUF]; 373 char buf[MAXBUF];
374 while (fgets(buf, MAXBUF, fp)) { 374 while (fgets(buf, MAXBUF, fp)) {
375 if (strncmp(buf, "CapBnd:\t", 8) == 0) { 375 if (strncmp(buf, "CapBnd:\t", 8) == 0) {
@@ -383,7 +383,7 @@ static uint64_t extract_caps(int pid) {
383 } 383 }
384 fclose(fp); 384 fclose(fp);
385 385
386errexit: 386errexit:
387 free(file); 387 free(file);
388 fprintf(stderr, "Error: cannot read caps configuration\n"); 388 fprintf(stderr, "Error: cannot read caps configuration\n");
389 exit(1); 389 exit(1);
@@ -391,7 +391,7 @@ errexit:
391 391
392void caps_print_filter(pid_t pid) { 392void caps_print_filter(pid_t pid) {
393 EUID_ASSERT(); 393 EUID_ASSERT();
394 394
395 // if the pid is that of a firejail process, use the pid of the first child process 395 // if the pid is that of a firejail process, use the pid of the first child process
396 EUID_ROOT(); // grsecurity 396 EUID_ROOT(); // grsecurity
397 char *comm = pid_proc_comm(pid); 397 char *comm = pid_proc_comm(pid);
diff --git a/src/firejail/cgroup.c b/src/firejail/cgroup.c
index 6ceb647ff..70f07dd23 100644
--- a/src/firejail/cgroup.c
+++ b/src/firejail/cgroup.c
@@ -25,7 +25,7 @@
25void save_cgroup(void) { 25void save_cgroup(void) {
26 if (cfg.cgroup == NULL) 26 if (cfg.cgroup == NULL)
27 return; 27 return;
28 28
29 FILE *fp = fopen(RUN_CGROUP_CFG, "w"); 29 FILE *fp = fopen(RUN_CGROUP_CFG, "w");
30 if (fp) { 30 if (fp) {
31 fprintf(fp, "%s", cfg.cgroup); 31 fprintf(fp, "%s", cfg.cgroup);
@@ -36,7 +36,7 @@ void save_cgroup(void) {
36 } 36 }
37 else 37 else
38 goto errout; 38 goto errout;
39 39
40 return; 40 return;
41 41
42errout: 42errout:
@@ -58,7 +58,7 @@ void load_cgroup(const char *fname) {
58 } 58 }
59 else 59 else
60 goto errout; 60 goto errout;
61 61
62 fclose(fp); 62 fclose(fp);
63 return; 63 return;
64 } 64 }
@@ -71,34 +71,34 @@ errout:
71 71
72void set_cgroup(const char *path) { 72void set_cgroup(const char *path) {
73 EUID_ASSERT(); 73 EUID_ASSERT();
74 74
75 invalid_filename(path); 75 invalid_filename(path);
76 76
77 // path starts with /sys/fs/cgroup 77 // path starts with /sys/fs/cgroup
78 if (strncmp(path, "/sys/fs/cgroup", 14) != 0) 78 if (strncmp(path, "/sys/fs/cgroup", 14) != 0)
79 goto errout; 79 goto errout;
80 80
81 // path ends in tasks 81 // path ends in tasks
82 char *ptr = strstr(path, "tasks"); 82 char *ptr = strstr(path, "tasks");
83 if (!ptr) 83 if (!ptr)
84 goto errout; 84 goto errout;
85 if (*(ptr + 5) != '\0') 85 if (*(ptr + 5) != '\0')
86 goto errout; 86 goto errout;
87 87
88 // no .. traversal 88 // no .. traversal
89 ptr = strstr(path, ".."); 89 ptr = strstr(path, "..");
90 if (ptr) 90 if (ptr)
91 goto errout; 91 goto errout;
92 92
93 // tasks file exists 93 // tasks file exists
94 struct stat s; 94 struct stat s;
95 if (stat(path, &s) == -1) 95 if (stat(path, &s) == -1)
96 goto errout; 96 goto errout;
97 97
98 // task file belongs to the user running the sandbox 98 // task file belongs to the user running the sandbox
99 if (s.st_uid != getuid() && s.st_gid != getgid()) 99 if (s.st_uid != getuid() && s.st_gid != getgid())
100 goto errout2; 100 goto errout2;
101 101
102 // add the task to cgroup 102 // add the task to cgroup
103 /* coverity[toctou] */ 103 /* coverity[toctou] */
104 FILE *fp = fopen(path, "a"); 104 FILE *fp = fopen(path, "a");
@@ -110,10 +110,10 @@ void set_cgroup(const char *path) {
110 fclose(fp); 110 fclose(fp);
111 return; 111 return;
112 112
113errout: 113errout:
114 fprintf(stderr, "Error: invalid cgroup\n"); 114 fprintf(stderr, "Error: invalid cgroup\n");
115 exit(1); 115 exit(1);
116errout2: 116errout2:
117 fprintf(stderr, "Error: you don't have permissions to use this control group\n"); 117 fprintf(stderr, "Error: you don't have permissions to use this control group\n");
118 exit(1); 118 exit(1);
119} 119}
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c
index 3c0c1b9ac..f4e28f084 100644
--- a/src/firejail/checkcfg.c
+++ b/src/firejail/checkcfg.c
@@ -49,33 +49,33 @@ int checkcfg(int val) {
49 cfg_val[CFG_FIREJAIL_PROMPT] = 0; 49 cfg_val[CFG_FIREJAIL_PROMPT] = 0;
50 cfg_val[CFG_FOLLOW_SYMLINK_PRIVATE_BIN] = 0; 50 cfg_val[CFG_FOLLOW_SYMLINK_PRIVATE_BIN] = 0;
51 cfg_val[CFG_DISABLE_MNT] = 0; 51 cfg_val[CFG_DISABLE_MNT] = 0;
52 52
53 // open configuration file 53 // open configuration file
54 const char *fname = SYSCONFDIR "/firejail.config"; 54 const char *fname = SYSCONFDIR "/firejail.config";
55 fp = fopen(fname, "r"); 55 fp = fopen(fname, "r");
56 if (!fp) { 56 if (!fp) {
57#ifdef HAVE_GLOBALCFG 57#ifdef HAVE_GLOBALCFG
58 fprintf(stderr, "Error: Firejail configuration file %s not found\n", fname); 58 fprintf(stderr, "Error: Firejail configuration file %s not found\n", fname);
59 exit(1); 59 exit(1);
60#else 60#else
61 initialized = 1; 61 initialized = 1;
62 return cfg_val[val]; 62 return cfg_val[val];
63#endif 63#endif
64 } 64 }
65 65
66 // read configuration file 66 // read configuration file
67 char buf[MAX_READ]; 67 char buf[MAX_READ];
68 while (fgets(buf,MAX_READ, fp)) { 68 while (fgets(buf,MAX_READ, fp)) {
69 line++; 69 line++;
70 if (*buf == '#' || *buf == '\n') 70 if (*buf == '#' || *buf == '\n')
71 continue; 71 continue;
72 72
73 // parse line 73 // parse line
74 ptr = line_remove_spaces(buf); 74 ptr = line_remove_spaces(buf);
75 if (!ptr) 75 if (!ptr)
76 continue; 76 continue;
77 77
78 // file transfer 78 // file transfer
79 else if (strncmp(ptr, "file-transfer ", 14) == 0) { 79 else if (strncmp(ptr, "file-transfer ", 14) == 0) {
80 if (strcmp(ptr + 14, "yes") == 0) 80 if (strcmp(ptr + 14, "yes") == 0)
81 cfg_val[CFG_FILE_TRANSFER] = 1; 81 cfg_val[CFG_FILE_TRANSFER] = 1;
@@ -209,14 +209,14 @@ int checkcfg(int val) {
209 char *end = strchr(fname, ' '); 209 char *end = strchr(fname, ' ');
210 if (end) 210 if (end)
211 *end = '\0'; 211 *end = '\0';
212 212
213 // is the file present? 213 // is the file present?
214 struct stat s; 214 struct stat s;
215 if (stat(fname, &s) == -1) { 215 if (stat(fname, &s) == -1) {
216 fprintf(stderr, "Error: netfilter-default file %s not available\n", fname); 216 fprintf(stderr, "Error: netfilter-default file %s not available\n", fname);
217 exit(1); 217 exit(1);
218 } 218 }
219 219
220 if (netfilter_default) 220 if (netfilter_default)
221 goto errout; 221 goto errout;
222 netfilter_default = strdup(fname); 222 netfilter_default = strdup(fname);
@@ -225,7 +225,7 @@ int checkcfg(int val) {
225 if (arg_debug) 225 if (arg_debug)
226 printf("netfilter default file %s\n", fname); 226 printf("netfilter default file %s\n", fname);
227 } 227 }
228 228
229 // Xephyr screen size 229 // Xephyr screen size
230 else if (strncmp(ptr, "xephyr-screen ", 14) == 0) { 230 else if (strncmp(ptr, "xephyr-screen ", 14) == 0) {
231 // expecting two numbers and an x between them 231 // expecting two numbers and an x between them
@@ -237,7 +237,7 @@ int checkcfg(int val) {
237 if (asprintf(&xephyr_screen, "%dx%d", n1, n2) == -1) 237 if (asprintf(&xephyr_screen, "%dx%d", n1, n2) == -1)
238 errExit("asprintf"); 238 errExit("asprintf");
239 } 239 }
240 240
241 // xephyr window title 241 // xephyr window title
242 else if (strncmp(ptr, "xephyr-window-title ", 20) == 0) { 242 else if (strncmp(ptr, "xephyr-window-title ", 20) == 0) {
243 if (strcmp(ptr + 20, "yes") == 0) 243 if (strcmp(ptr + 20, "yes") == 0)
@@ -247,7 +247,7 @@ int checkcfg(int val) {
247 else 247 else
248 goto errout; 248 goto errout;
249 } 249 }
250 250
251 // Xephyr command extra parameters 251 // Xephyr command extra parameters
252 else if (strncmp(ptr, "xephyr-extra-params ", 20) == 0) { 252 else if (strncmp(ptr, "xephyr-extra-params ", 20) == 0) {
253 if (*xephyr_extra_params != '\0') 253 if (*xephyr_extra_params != '\0')
@@ -256,7 +256,7 @@ int checkcfg(int val) {
256 if (!xephyr_extra_params) 256 if (!xephyr_extra_params)
257 errExit("strdup"); 257 errExit("strdup");
258 } 258 }
259 259
260 // xpra server extra parameters 260 // xpra server extra parameters
261 else if (strncmp(ptr, "xpra-extra-params ", 18) == 0) { 261 else if (strncmp(ptr, "xpra-extra-params ", 18) == 0) {
262 if (*xpra_extra_params != '\0') 262 if (*xpra_extra_params != '\0')
@@ -287,7 +287,7 @@ int checkcfg(int val) {
287 if (!xvfb_extra_params) 287 if (!xvfb_extra_params)
288 errExit("strdup"); 288 errExit("strdup");
289 } 289 }
290 290
291 // quiet by default 291 // quiet by default
292 else if (strncmp(ptr, "quiet-by-default ", 17) == 0) { 292 else if (strncmp(ptr, "quiet-by-default ", 17) == 0) {
293 if (strcmp(ptr + 17, "yes") == 0) 293 if (strcmp(ptr + 17, "yes") == 0)
@@ -355,9 +355,9 @@ int checkcfg(int val) {
355 fclose(fp); 355 fclose(fp);
356 initialized = 1; 356 initialized = 1;
357 } 357 }
358 358
359 return cfg_val[val]; 359 return cfg_val[val];
360 360
361errout: 361errout:
362 assert(ptr); 362 assert(ptr);
363 free(ptr); 363 free(ptr);
@@ -477,5 +477,5 @@ void print_compiletime_support(void) {
477 "disabled" 477 "disabled"
478#endif 478#endif
479 ); 479 );
480 480
481} 481}
diff --git a/src/firejail/cmdline.c b/src/firejail/cmdline.c
index e62ed8d33..114173b6a 100644
--- a/src/firejail/cmdline.c
+++ b/src/firejail/cmdline.c
@@ -28,7 +28,7 @@
28 28
29static int cmdline_length(int argc, char **argv, int index) { 29static int cmdline_length(int argc, char **argv, int index) {
30 assert(index != -1); 30 assert(index != -1);
31 31
32 unsigned i,j; 32 unsigned i,j;
33 int len = 0; 33 int len = 0;
34 unsigned argcnt = argc - index; 34 unsigned argcnt = argc - index;
@@ -91,7 +91,7 @@ static void quote_cmdline(char *command_line, char *window_title, int len, int a
91 if (j > 0 && argv[i + index][j-1] == '\'') { 91 if (j > 0 && argv[i + index][j-1] == '\'') {
92 ptr1--; 92 ptr1--;
93 sprintf(ptr1, "\'\""); 93 sprintf(ptr1, "\'\"");
94 } 94 }
95 // this first in series 95 // this first in series
96 else 96 else
97 { 97 {
@@ -151,9 +151,9 @@ void build_cmdline(char **command_line, char **window_title, int argc, char **ar
151 *window_title = malloc(len + 1); 151 *window_title = malloc(len + 1);
152 if (!*window_title) 152 if (!*window_title)
153 errExit("malloc"); 153 errExit("malloc");
154 154
155 quote_cmdline(*command_line, *window_title, len, argc, argv, index); 155 quote_cmdline(*command_line, *window_title, len, argc, argv, index);
156 156
157 if (arg_debug) 157 if (arg_debug)
158 printf("Building quoted command line: %s\n", *command_line); 158 printf("Building quoted command line: %s\n", *command_line);
159 159
diff --git a/src/firejail/cpu.c b/src/firejail/cpu.c
index 9c0214502..6b3fc063d 100644
--- a/src/firejail/cpu.c
+++ b/src/firejail/cpu.c
@@ -26,13 +26,13 @@
26static void set_cpu(const char *str) { 26static void set_cpu(const char *str) {
27 if (strlen(str) == 0) 27 if (strlen(str) == 0)
28 return; 28 return;
29 29
30 int val = atoi(str); 30 int val = atoi(str);
31 if (val < 0 || val >= 32) { 31 if (val < 0 || val >= 32) {
32 fprintf(stderr, "Error: invalid cpu number. Accepted values are between 0 and 31.\n"); 32 fprintf(stderr, "Error: invalid cpu number. Accepted values are between 0 and 31.\n");
33 exit(1); 33 exit(1);
34 } 34 }
35 35
36 uint32_t mask = 1; 36 uint32_t mask = 1;
37 int i; 37 int i;
38 for (i = 0; i < val; i++, mask <<= 1); 38 for (i = 0; i < val; i++, mask <<= 1);
@@ -41,11 +41,11 @@ static void set_cpu(const char *str) {
41 41
42void read_cpu_list(const char *str) { 42void read_cpu_list(const char *str) {
43 EUID_ASSERT(); 43 EUID_ASSERT();
44 44
45 char *tmp = strdup(str); 45 char *tmp = strdup(str);
46 if (tmp == NULL) 46 if (tmp == NULL)
47 errExit("strdup"); 47 errExit("strdup");
48 48
49 char *ptr = tmp; 49 char *ptr = tmp;
50 while (*ptr != '\0') { 50 while (*ptr != '\0') {
51 if (*ptr == ',' || isdigit(*ptr)) 51 if (*ptr == ',' || isdigit(*ptr))
@@ -56,7 +56,7 @@ void read_cpu_list(const char *str) {
56 } 56 }
57 ptr++; 57 ptr++;
58 } 58 }
59 59
60 char *start = tmp; 60 char *start = tmp;
61 ptr = tmp; 61 ptr = tmp;
62 while (*ptr != '\0') { 62 while (*ptr != '\0') {
@@ -107,17 +107,17 @@ void set_cpu_affinity(void) {
107 // set cpu affinity 107 // set cpu affinity
108 cpu_set_t mask; 108 cpu_set_t mask;
109 CPU_ZERO(&mask); 109 CPU_ZERO(&mask);
110 110
111 int i; 111 int i;
112 uint32_t m = 1; 112 uint32_t m = 1;
113 for (i = 0; i < 32; i++, m <<= 1) { 113 for (i = 0; i < 32; i++, m <<= 1) {
114 if (cfg.cpus & m) 114 if (cfg.cpus & m)
115 CPU_SET(i, &mask); 115 CPU_SET(i, &mask);
116 } 116 }
117 117
118 if (sched_setaffinity(0, sizeof(mask), &mask) == -1) 118 if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
119 fwarning("cannot set cpu affinity\n"); 119 fwarning("cannot set cpu affinity\n");
120 120
121 // verify cpu affinity 121 // verify cpu affinity
122 cpu_set_t mask2; 122 cpu_set_t mask2;
123 CPU_ZERO(&mask2); 123 CPU_ZERO(&mask2);
@@ -147,7 +147,7 @@ static void print_cpu(int pid) {
147 return; 147 return;
148 } 148 }
149 149
150#define MAXBUF 4096 150#define MAXBUF 4096
151 char buf[MAXBUF]; 151 char buf[MAXBUF];
152 while (fgets(buf, MAXBUF, fp)) { 152 while (fgets(buf, MAXBUF, fp)) {
153 if (strncmp(buf, "Cpus_allowed_list:", 18) == 0) { 153 if (strncmp(buf, "Cpus_allowed_list:", 18) == 0) {
@@ -164,7 +164,7 @@ static void print_cpu(int pid) {
164 164
165void cpu_print_filter(pid_t pid) { 165void cpu_print_filter(pid_t pid) {
166 EUID_ASSERT(); 166 EUID_ASSERT();
167 167
168 // if the pid is that of a firejail process, use the pid of the first child process 168 // if the pid is that of a firejail process, use the pid of the first child process
169 EUID_ROOT(); // grsecurity 169 EUID_ROOT(); // grsecurity
170 char *comm = pid_proc_comm(pid); 170 char *comm = pid_proc_comm(pid);
@@ -192,4 +192,3 @@ void cpu_print_filter(pid_t pid) {
192 print_cpu(pid); 192 print_cpu(pid);
193 exit(0); 193 exit(0);
194} 194}
195
diff --git a/src/firejail/env.c b/src/firejail/env.c
index c54b429c3..b2e4c17f3 100644
--- a/src/firejail/env.c
+++ b/src/firejail/env.c
@@ -33,13 +33,13 @@ static Env *envlist = NULL;
33 33
34static void env_add(Env *env) { 34static void env_add(Env *env) {
35 env->next = NULL; 35 env->next = NULL;
36 36
37 // add the new entry at the end of the list 37 // add the new entry at the end of the list
38 if (envlist == NULL) { 38 if (envlist == NULL) {
39 envlist = env; 39 envlist = env;
40 return; 40 return;
41 } 41 }
42 42
43 Env *ptr = envlist; 43 Env *ptr = envlist;
44 while (1) { 44 while (1) {
45 if (ptr->next == NULL) { 45 if (ptr->next == NULL) {
@@ -77,7 +77,7 @@ void env_ibus_load(void) {
77 continue; 77 continue;
78 if (strlen(ptr) != 6) 78 if (strlen(ptr) != 6)
79 continue; 79 continue;
80 80
81 // open the file 81 // open the file
82 char *fname; 82 char *fname;
83 if (asprintf(&fname, "%s/%s", dirname, entry->d_name) == -1) 83 if (asprintf(&fname, "%s/%s", dirname, entry->d_name) == -1)
@@ -86,7 +86,7 @@ void env_ibus_load(void) {
86 free(fname); 86 free(fname);
87 if (!fp) 87 if (!fp)
88 continue; 88 continue;
89 89
90 // read the file 90 // read the file
91 const int maxline = 4096; 91 const int maxline = 4096;
92 char buf[maxline]; 92 char buf[maxline];
@@ -137,24 +137,24 @@ void env_defaults(void) {
137 if (prompt && strcmp(prompt, "yes") == 0) 137 if (prompt && strcmp(prompt, "yes") == 0)
138 set_prompt = 1; 138 set_prompt = 1;
139 } 139 }
140 140
141 if (set_prompt) { 141 if (set_prompt) {
142 //export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] ' 142 //export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
143 if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0) 143 if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
144 errExit("setenv"); 144 errExit("setenv");
145 } 145 }
146 146
147 // set the window title 147 // set the window title
148 if (!arg_quiet) 148 if (!arg_quiet)
149 printf("\033]0;firejail %s\007", cfg.window_title); 149 printf("\033]0;firejail %s\007", cfg.window_title);
150 fflush(0); 150 fflush(0);
151} 151}
152 152
153// parse and store the environment setting 153// parse and store the environment setting
154void env_store(const char *str, ENV_OP op) { 154void env_store(const char *str, ENV_OP op) {
155 EUID_ASSERT(); 155 EUID_ASSERT();
156 assert(str); 156 assert(str);
157 157
158 // some basic checking 158 // some basic checking
159 if (*str == '\0') 159 if (*str == '\0')
160 goto errexit; 160 goto errexit;
@@ -182,11 +182,11 @@ void env_store(const char *str, ENV_OP op) {
182 env->value = ptr2 + 1; 182 env->value = ptr2 + 1;
183 } 183 }
184 env->op = op; 184 env->op = op;
185 185
186 // add entry to the list 186 // add entry to the list
187 env_add(env); 187 env_add(env);
188 return; 188 return;
189 189
190errexit: 190errexit:
191 fprintf(stderr, "Error: invalid --env setting\n"); 191 fprintf(stderr, "Error: invalid --env setting\n");
192 exit(1); 192 exit(1);
@@ -195,7 +195,7 @@ errexit:
195// set env variables in the new sandbox process 195// set env variables in the new sandbox process
196void env_apply(void) { 196void env_apply(void) {
197 Env *env = envlist; 197 Env *env = envlist;
198 198
199 while (env) { 199 while (env) {
200 if (env->op == SETENV) { 200 if (env->op == SETENV) {
201 if (setenv(env->name, env->value, 1) < 0) 201 if (setenv(env->name, env->value, 1) < 0)
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index ac68e7738..c60322dda 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -55,7 +55,7 @@ static void disable_file(OPERATION op, const char *filename) {
55 assert(filename); 55 assert(filename);
56 assert(op <OPERATION_MAX); 56 assert(op <OPERATION_MAX);
57 last_disable = UNSUCCESSFUL; 57 last_disable = UNSUCCESSFUL;
58 58
59 // Resolve all symlinks 59 // Resolve all symlinks
60 char* fname = realpath(filename, NULL); 60 char* fname = realpath(filename, NULL);
61 if (fname == NULL && errno != EACCES) { 61 if (fname == NULL && errno != EACCES) {
@@ -87,10 +87,10 @@ static void disable_file(OPERATION op, const char *filename) {
87 if (arg_debug) 87 if (arg_debug)
88 printf("Warning (blacklisting): %s is an invalid file, skipping...\n", filename); 88 printf("Warning (blacklisting): %s is an invalid file, skipping...\n", filename);
89 } 89 }
90 90
91 return; 91 return;
92 } 92 }
93 93
94 // if the file is not present, do nothing 94 // if the file is not present, do nothing
95 struct stat s; 95 struct stat s;
96 if (fname == NULL) 96 if (fname == NULL)
@@ -124,7 +124,7 @@ static void disable_file(OPERATION op, const char *filename) {
124 else 124 else
125 printf(" - no logging\n"); 125 printf(" - no logging\n");
126 } 126 }
127 127
128 if (S_ISDIR(s.st_mode)) { 128 if (S_ISDIR(s.st_mode)) {
129 if (mount(RUN_RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0) 129 if (mount(RUN_RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0)
130 errExit("disable file"); 130 errExit("disable file");
@@ -243,7 +243,7 @@ void fs_blacklist(void) {
243 ProfileEntry *entry = cfg.profile; 243 ProfileEntry *entry = cfg.profile;
244 if (!entry) 244 if (!entry)
245 return; 245 return;
246 246
247 size_t noblacklist_c = 0; 247 size_t noblacklist_c = 0;
248 size_t noblacklist_m = 32; 248 size_t noblacklist_m = 32;
249 char **noblacklist = calloc(noblacklist_m, sizeof(*noblacklist)); 249 char **noblacklist = calloc(noblacklist_m, sizeof(*noblacklist));
@@ -256,7 +256,7 @@ void fs_blacklist(void) {
256 char *ptr; 256 char *ptr;
257 257
258 // whitelist commands handled by fs_whitelist() 258 // whitelist commands handled by fs_whitelist()
259 if (strncmp(entry->data, "whitelist ", 10) == 0 || 259 if (strncmp(entry->data, "whitelist ", 10) == 0 ||
260 strncmp(entry->data, "nowhitelist ", 12) == 0 || 260 strncmp(entry->data, "nowhitelist ", 12) == 0 ||
261 *entry->data == '\0') { 261 *entry->data == '\0') {
262 entry = entry->next; 262 entry = entry->next;
@@ -275,7 +275,7 @@ void fs_blacklist(void) {
275 entry = entry->next; 275 entry = entry->next;
276 continue; 276 continue;
277 } 277 }
278 278
279 // mount --bind olddir newdir 279 // mount --bind olddir newdir
280 if (arg_debug) 280 if (arg_debug)
281 printf("Mount-bind %s on top of %s\n", dname1, dname2); 281 printf("Mount-bind %s on top of %s\n", dname1, dname2);
@@ -284,8 +284,8 @@ void fs_blacklist(void) {
284 errExit("mount bind"); 284 errExit("mount bind");
285 /* coverity[toctou] */ 285 /* coverity[toctou] */
286 if (set_perms(dname2, s.st_uid, s.st_gid,s.st_mode)) 286 if (set_perms(dname2, s.st_uid, s.st_gid,s.st_mode))
287 errExit("set_perms"); 287 errExit("set_perms");
288 288
289 entry = entry->next; 289 entry = entry->next;
290 continue; 290 continue;
291 } 291 }
@@ -348,33 +348,33 @@ void fs_blacklist(void) {
348 else if (strncmp(entry->data, "read-only ", 10) == 0) { 348 else if (strncmp(entry->data, "read-only ", 10) == 0) {
349 ptr = entry->data + 10; 349 ptr = entry->data + 10;
350 op = MOUNT_READONLY; 350 op = MOUNT_READONLY;
351 } 351 }
352 else if (strncmp(entry->data, "read-write ", 11) == 0) { 352 else if (strncmp(entry->data, "read-write ", 11) == 0) {
353 ptr = entry->data + 11; 353 ptr = entry->data + 11;
354 op = MOUNT_RDWR; 354 op = MOUNT_RDWR;
355 } 355 }
356 else if (strncmp(entry->data, "noexec ", 7) == 0) { 356 else if (strncmp(entry->data, "noexec ", 7) == 0) {
357 ptr = entry->data + 7; 357 ptr = entry->data + 7;
358 op = MOUNT_NOEXEC; 358 op = MOUNT_NOEXEC;
359 } 359 }
360 else if (strncmp(entry->data, "tmpfs ", 6) == 0) { 360 else if (strncmp(entry->data, "tmpfs ", 6) == 0) {
361 ptr = entry->data + 6; 361 ptr = entry->data + 6;
362 op = MOUNT_TMPFS; 362 op = MOUNT_TMPFS;
363 } 363 }
364 else if (strncmp(entry->data, "mkdir ", 6) == 0) { 364 else if (strncmp(entry->data, "mkdir ", 6) == 0) {
365 EUID_USER(); 365 EUID_USER();
366 fs_mkdir(entry->data + 6); 366 fs_mkdir(entry->data + 6);
367 EUID_ROOT(); 367 EUID_ROOT();
368 entry = entry->next; 368 entry = entry->next;
369 continue; 369 continue;
370 } 370 }
371 else if (strncmp(entry->data, "mkfile ", 7) == 0) { 371 else if (strncmp(entry->data, "mkfile ", 7) == 0) {
372 EUID_USER(); 372 EUID_USER();
373 fs_mkfile(entry->data + 7); 373 fs_mkfile(entry->data + 7);
374 EUID_ROOT(); 374 EUID_ROOT();
375 entry = entry->next; 375 entry = entry->next;
376 continue; 376 continue;
377 } 377 }
378 else { 378 else {
379 fprintf(stderr, "Error: invalid profile line %s\n", entry->data); 379 fprintf(stderr, "Error: invalid profile line %s\n", entry->data);
380 entry = entry->next; 380 entry = entry->next;
@@ -446,10 +446,10 @@ static void fs_rdwr(const char *dir) {
446 fwarning("you are not allowed to change %s to read-write\n", dir); 446 fwarning("you are not allowed to change %s to read-write\n", dir);
447 return; 447 return;
448 } 448 }
449 449
450 // mount --bind /bin /bin 450 // mount --bind /bin /bin
451 // mount --bind -o remount,rw /bin 451 // mount --bind -o remount,rw /bin
452 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || 452 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 ||
453 mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) 453 mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0)
454 errExit("mount read-write"); 454 errExit("mount read-write");
455 fs_logger2("read-write", dir); 455 fs_logger2("read-write", dir);
@@ -464,7 +464,7 @@ void fs_noexec(const char *dir) {
464 if (rv == 0) { 464 if (rv == 0) {
465 // mount --bind /bin /bin 465 // mount --bind /bin /bin
466 // mount --bind -o remount,ro /bin 466 // mount --bind -o remount,ro /bin
467 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || 467 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 ||
468 mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_NOEXEC|MS_NODEV|MS_NOSUID|MS_REC, NULL) < 0) 468 mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_NOEXEC|MS_NODEV|MS_NOSUID|MS_REC, NULL) < 0)
469 errExit("mount noexec"); 469 errExit("mount noexec");
470 fs_logger2("noexec", dir); 470 fs_logger2("noexec", dir);
@@ -504,11 +504,11 @@ void fs_proc_sys_dev_boot(void) {
504 fwarning("failed to mount /sys\n"); 504 fwarning("failed to mount /sys\n");
505 else 505 else
506 fs_logger("remount /sys"); 506 fs_logger("remount /sys");
507 507
508 disable_file(BLACKLIST_FILE, "/sys/firmware"); 508 disable_file(BLACKLIST_FILE, "/sys/firmware");
509 disable_file(BLACKLIST_FILE, "/sys/hypervisor"); 509 disable_file(BLACKLIST_FILE, "/sys/hypervisor");
510 { // allow user access to /sys/fs if "--noblacklist=/sys/fs" is present on the command line 510 { // allow user access to /sys/fs if "--noblacklist=/sys/fs" is present on the command line
511 EUID_USER(); 511 EUID_USER();
512 profile_add("blacklist /sys/fs"); 512 profile_add("blacklist /sys/fs");
513 EUID_ROOT(); 513 EUID_ROOT();
514 } 514 }
@@ -519,11 +519,11 @@ void fs_proc_sys_dev_boot(void) {
519 disable_file(BLACKLIST_FILE, "/sys/kernel/uevent_helper"); 519 disable_file(BLACKLIST_FILE, "/sys/kernel/uevent_helper");
520 520
521 // various /proc/sys files 521 // various /proc/sys files
522 disable_file(BLACKLIST_FILE, "/proc/sys/security"); 522 disable_file(BLACKLIST_FILE, "/proc/sys/security");
523 disable_file(BLACKLIST_FILE, "/proc/sys/efi/vars"); 523 disable_file(BLACKLIST_FILE, "/proc/sys/efi/vars");
524 disable_file(BLACKLIST_FILE, "/proc/sys/fs/binfmt_misc"); 524 disable_file(BLACKLIST_FILE, "/proc/sys/fs/binfmt_misc");
525 disable_file(BLACKLIST_FILE, "/proc/sys/kernel/core_pattern"); 525 disable_file(BLACKLIST_FILE, "/proc/sys/kernel/core_pattern");
526 disable_file(BLACKLIST_FILE, "/proc/sys/kernel/modprobe"); 526 disable_file(BLACKLIST_FILE, "/proc/sys/kernel/modprobe");
527 disable_file(BLACKLIST_FILE, "/proc/sysrq-trigger"); 527 disable_file(BLACKLIST_FILE, "/proc/sysrq-trigger");
528 disable_file(BLACKLIST_FILE, "/proc/sys/kernel/hotplug"); 528 disable_file(BLACKLIST_FILE, "/proc/sys/kernel/hotplug");
529 disable_file(BLACKLIST_FILE, "/proc/sys/vm/panic_on_oom"); 529 disable_file(BLACKLIST_FILE, "/proc/sys/vm/panic_on_oom");
@@ -531,15 +531,15 @@ void fs_proc_sys_dev_boot(void) {
531 // various /proc files 531 // various /proc files
532 disable_file(BLACKLIST_FILE, "/proc/irq"); 532 disable_file(BLACKLIST_FILE, "/proc/irq");
533 disable_file(BLACKLIST_FILE, "/proc/bus"); 533 disable_file(BLACKLIST_FILE, "/proc/bus");
534 disable_file(BLACKLIST_FILE, "/proc/config.gz"); 534 disable_file(BLACKLIST_FILE, "/proc/config.gz");
535 disable_file(BLACKLIST_FILE, "/proc/sched_debug"); 535 disable_file(BLACKLIST_FILE, "/proc/sched_debug");
536 disable_file(BLACKLIST_FILE, "/proc/timer_list"); 536 disable_file(BLACKLIST_FILE, "/proc/timer_list");
537 disable_file(BLACKLIST_FILE, "/proc/timer_stats"); 537 disable_file(BLACKLIST_FILE, "/proc/timer_stats");
538 disable_file(BLACKLIST_FILE, "/proc/kcore"); 538 disable_file(BLACKLIST_FILE, "/proc/kcore");
539 disable_file(BLACKLIST_FILE, "/proc/kallsyms"); 539 disable_file(BLACKLIST_FILE, "/proc/kallsyms");
540 disable_file(BLACKLIST_FILE, "/proc/mem"); 540 disable_file(BLACKLIST_FILE, "/proc/mem");
541 disable_file(BLACKLIST_FILE, "/proc/kmem"); 541 disable_file(BLACKLIST_FILE, "/proc/kmem");
542 542
543 // remove kernel symbol information 543 // remove kernel symbol information
544 if (!arg_allow_debuggers) { 544 if (!arg_allow_debuggers) {
545 disable_file(BLACKLIST_FILE, "/usr/src/linux"); 545 disable_file(BLACKLIST_FILE, "/usr/src/linux");
@@ -547,18 +547,18 @@ void fs_proc_sys_dev_boot(void) {
547 disable_file(BLACKLIST_FILE, "/usr/lib/debug"); 547 disable_file(BLACKLIST_FILE, "/usr/lib/debug");
548 disable_file(BLACKLIST_FILE, "/boot"); 548 disable_file(BLACKLIST_FILE, "/boot");
549 } 549 }
550 550
551 // disable /selinux 551 // disable /selinux
552 disable_file(BLACKLIST_FILE, "/selinux"); 552 disable_file(BLACKLIST_FILE, "/selinux");
553 553
554 // disable /dev/port 554 // disable /dev/port
555 disable_file(BLACKLIST_FILE, "/dev/port"); 555 disable_file(BLACKLIST_FILE, "/dev/port");
556 556
557 557
558 558
559 // disable various ipc sockets in /run/user 559 // disable various ipc sockets in /run/user
560 struct stat s; 560 struct stat s;
561 561
562 char *fname; 562 char *fname;
563 if (asprintf(&fname, "/run/usr/%d", getuid()) == -1) 563 if (asprintf(&fname, "/run/usr/%d", getuid()) == -1)
564 errExit("asprintf"); 564 errExit("asprintf");
@@ -567,24 +567,24 @@ void fs_proc_sys_dev_boot(void) {
567 char *fnamegpg; 567 char *fnamegpg;
568 if (asprintf(&fnamegpg, "/run/user/%d/gnupg", getuid()) == -1) 568 if (asprintf(&fnamegpg, "/run/user/%d/gnupg", getuid()) == -1)
569 errExit("asprintf"); 569 errExit("asprintf");
570 if (stat(fnamegpg, &s) == -1) 570 if (stat(fnamegpg, &s) == -1)
571 mkdir_attr(fnamegpg, 0700, getuid(), getgid()); 571 mkdir_attr(fnamegpg, 0700, getuid(), getgid());
572 if (stat(fnamegpg, &s) == 0) 572 if (stat(fnamegpg, &s) == 0)
573 disable_file(BLACKLIST_FILE, fnamegpg); 573 disable_file(BLACKLIST_FILE, fnamegpg);
574 free(fnamegpg); 574 free(fnamegpg);
575 575
576 // disable /run/user/{uid}/systemd 576 // disable /run/user/{uid}/systemd
577 char *fnamesysd; 577 char *fnamesysd;
578 if (asprintf(&fnamesysd, "/run/user/%d/systemd", getuid()) == -1) 578 if (asprintf(&fnamesysd, "/run/user/%d/systemd", getuid()) == -1)
579 errExit("asprintf"); 579 errExit("asprintf");
580 if (stat(fnamesysd, &s) == -1) 580 if (stat(fnamesysd, &s) == -1)
581 mkdir_attr(fnamesysd, 0755, getuid(), getgid()); 581 mkdir_attr(fnamesysd, 0755, getuid(), getgid());
582 if (stat(fnamesysd, &s) == 0) 582 if (stat(fnamesysd, &s) == 0)
583 disable_file(BLACKLIST_FILE, fnamesysd); 583 disable_file(BLACKLIST_FILE, fnamesysd);
584 free(fnamesysd); 584 free(fnamesysd);
585 } 585 }
586 free(fname); 586 free(fname);
587 587
588 if (getuid() != 0) { 588 if (getuid() != 0) {
589 // disable /dev/kmsg and /proc/kmsg 589 // disable /dev/kmsg and /proc/kmsg
590 disable_file(BLACKLIST_FILE, "/dev/kmsg"); 590 disable_file(BLACKLIST_FILE, "/dev/kmsg");
@@ -602,7 +602,7 @@ static void disable_config(void) {
602 if (stat(fname, &s) == 0) 602 if (stat(fname, &s) == 0)
603 disable_file(BLACKLIST_FILE, fname); 603 disable_file(BLACKLIST_FILE, fname);
604 free(fname); 604 free(fname);
605 605
606 // disable run time information 606 // disable run time information
607 if (stat(RUN_FIREJAIL_NETWORK_DIR, &s) == 0) 607 if (stat(RUN_FIREJAIL_NETWORK_DIR, &s) == 0)
608 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NETWORK_DIR); 608 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NETWORK_DIR);
@@ -618,7 +618,7 @@ static void disable_config(void) {
618// build a basic read-only filesystem 618// build a basic read-only filesystem
619void fs_basic_fs(void) { 619void fs_basic_fs(void) {
620 uid_t uid = getuid(); 620 uid_t uid = getuid();
621 621
622 if (arg_debug) 622 if (arg_debug)
623 printf("Mounting read-only /bin, /sbin, /lib, /lib32, /lib64, /usr"); 623 printf("Mounting read-only /bin, /sbin, /lib, /lib32, /lib64, /usr");
624 if (!arg_writable_etc) { 624 if (!arg_writable_etc) {
@@ -649,15 +649,15 @@ void fs_basic_fs(void) {
649 fs_var_log(); 649 fs_var_log();
650 else 650 else
651 fs_rdwr("/var/log"); 651 fs_rdwr("/var/log");
652 652
653 fs_var_lib(); 653 fs_var_lib();
654 fs_var_cache(); 654 fs_var_cache();
655 fs_var_utmp(); 655 fs_var_utmp();
656 fs_machineid(); 656 fs_machineid();
657 657
658 // don't leak user information 658 // don't leak user information
659 restrict_users(); 659 restrict_users();
660 660
661 // when starting as root, firejail config is not disabled; 661 // when starting as root, firejail config is not disabled;
662 // this mode could be used to install and test new software by chaining 662 // this mode could be used to install and test new software by chaining
663 // firejail sandboxes (firejail --force) 663 // firejail sandboxes (firejail --force)
@@ -675,7 +675,7 @@ char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) {
675 // create ~/.firejail directory 675 // create ~/.firejail directory
676 if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1) 676 if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1)
677 errExit("asprintf"); 677 errExit("asprintf");
678 678
679 if (is_link(dirname)) { 679 if (is_link(dirname)) {
680 fprintf(stderr, "Error: invalid ~/.firejail directory\n"); 680 fprintf(stderr, "Error: invalid ~/.firejail directory\n");
681 exit(1); 681 exit(1);
@@ -688,7 +688,7 @@ char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) {
688 if (child == 0) { 688 if (child == 0) {
689 // drop privileges 689 // drop privileges
690 drop_privs(0); 690 drop_privs(0);
691 691
692 // create directory 692 // create directory
693 if (mkdir(dirname, 0700)) 693 if (mkdir(dirname, 0700))
694 errExit("mkdir"); 694 errExit("mkdir");
@@ -770,7 +770,7 @@ void fs_overlayfs(void) {
770 fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version); 770 fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version);
771 exit(1); 771 exit(1);
772 } 772 }
773 773
774 if (arg_debug) 774 if (arg_debug)
775 printf("Linux kernel version %d.%d\n", major, minor); 775 printf("Linux kernel version %d.%d\n", major, minor);
776 int oldkernel = 0; 776 int oldkernel = 0;
@@ -780,7 +780,7 @@ void fs_overlayfs(void) {
780 } 780 }
781 if (major == 3 && minor < 18) 781 if (major == 3 && minor < 18)
782 oldkernel = 1; 782 oldkernel = 1;
783 783
784 char *oroot; 784 char *oroot;
785 if(asprintf(&oroot, "%s/oroot", RUN_MNT_DIR) == -1) 785 if(asprintf(&oroot, "%s/oroot", RUN_MNT_DIR) == -1)
786 errExit("asprintf"); 786 errExit("asprintf");
@@ -818,7 +818,7 @@ void fs_overlayfs(void) {
818 } 818 }
819 else if (set_perms(odiff, 0, 0, 0755)) 819 else if (set_perms(odiff, 0, 0, 0755))
820 errExit("set_perms"); 820 errExit("set_perms");
821 821
822 char *owork; 822 char *owork;
823 if(asprintf(&owork, "%s/owork", basedir) == -1) 823 if(asprintf(&owork, "%s/owork", basedir) == -1)
824 errExit("asprintf"); 824 errExit("asprintf");
@@ -829,7 +829,7 @@ void fs_overlayfs(void) {
829 } 829 }
830 else if (set_perms(owork, 0, 0, 0755)) 830 else if (set_perms(owork, 0, 0, 0755))
831 errExit("chown"); 831 errExit("chown");
832 832
833 // mount overlayfs 833 // mount overlayfs
834 if (arg_debug) 834 if (arg_debug)
835 printf("Mounting OverlayFS\n"); 835 printf("Mounting OverlayFS\n");
@@ -849,11 +849,11 @@ void fs_overlayfs(void) {
849 errExit("asprintf"); 849 errExit("asprintf");
850 if (mount("overlay", oroot, "overlay", MS_MGC_VAL, option) < 0) 850 if (mount("overlay", oroot, "overlay", MS_MGC_VAL, option) < 0)
851 errExit("mounting overlayfs"); 851 errExit("mounting overlayfs");
852 852
853 //*************************** 853 //***************************
854 // issue #263 start code 854 // issue #263 start code
855 // My setup has a separate mount point for /home. When the overlay is mounted, 855 // My setup has a separate mount point for /home. When the overlay is mounted,
856 // the overlay does not contain the original /home contents. 856 // the overlay does not contain the original /home contents.
857 // I added code to create a second overlay for /home if the overlay home dir is empty and this seems to work 857 // I added code to create a second overlay for /home if the overlay home dir is empty and this seems to work
858 // @dshmgh, Jan 2016 858 // @dshmgh, Jan 2016
859 { 859 {
@@ -862,22 +862,22 @@ void fs_overlayfs(void) {
862 char *hroot; 862 char *hroot;
863 char *hdiff; 863 char *hdiff;
864 char *hwork; 864 char *hwork;
865 865
866 // dons add debug 866 // dons add debug
867 if (arg_debug) printf ("DEBUG: chroot dirs are oroot %s odiff %s owork %s\n",oroot,odiff,owork); 867 if (arg_debug) printf ("DEBUG: chroot dirs are oroot %s odiff %s owork %s\n",oroot,odiff,owork);
868 868
869 // BEFORE NEXT, WE NEED TO TEST IF /home has any contents or do we need to mount it? 869 // BEFORE NEXT, WE NEED TO TEST IF /home has any contents or do we need to mount it?
870 // must create var for oroot/cfg.homedir 870 // must create var for oroot/cfg.homedir
871 if (asprintf(&overlayhome,"%s%s",oroot,cfg.homedir) == -1) 871 if (asprintf(&overlayhome,"%s%s",oroot,cfg.homedir) == -1)
872 errExit("asprintf"); 872 errExit("asprintf");
873 if (arg_debug) printf ("DEBUG: overlayhome var holds ##%s##\n",overlayhome); 873 if (arg_debug) printf ("DEBUG: overlayhome var holds ##%s##\n",overlayhome);
874 874
875 // if no homedir in overlay -- create another overlay for /home 875 // if no homedir in overlay -- create another overlay for /home
876 if (stat(overlayhome, &s) == -1) { 876 if (stat(overlayhome, &s) == -1) {
877 877
878 if(asprintf(&hroot, "%s/oroot/home", RUN_MNT_DIR) == -1) 878 if(asprintf(&hroot, "%s/oroot/home", RUN_MNT_DIR) == -1)
879 errExit("asprintf"); 879 errExit("asprintf");
880 880
881 if(asprintf(&hdiff, "%s/hdiff", basedir) == -1) 881 if(asprintf(&hdiff, "%s/hdiff", basedir) == -1)
882 errExit("asprintf"); 882 errExit("asprintf");
883 883
@@ -887,7 +887,7 @@ void fs_overlayfs(void) {
887 } 887 }
888 else if (set_perms(hdiff, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) 888 else if (set_perms(hdiff, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
889 errExit("set_perms"); 889 errExit("set_perms");
890 890
891 if(asprintf(&hwork, "%s/hwork", basedir) == -1) 891 if(asprintf(&hwork, "%s/hwork", basedir) == -1)
892 errExit("asprintf"); 892 errExit("asprintf");
893 893
@@ -897,13 +897,13 @@ void fs_overlayfs(void) {
897 } 897 }
898 else if (set_perms(hwork, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) 898 else if (set_perms(hwork, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
899 errExit("set_perms"); 899 errExit("set_perms");
900 900
901 // no homedir in overlay so now mount another overlay for /home 901 // no homedir in overlay so now mount another overlay for /home
902 if (asprintf(&option, "lowerdir=/home,upperdir=%s,workdir=%s", hdiff, hwork) == -1) 902 if (asprintf(&option, "lowerdir=/home,upperdir=%s,workdir=%s", hdiff, hwork) == -1)
903 errExit("asprintf"); 903 errExit("asprintf");
904 if (mount("overlay", hroot, "overlay", MS_MGC_VAL, option) < 0) 904 if (mount("overlay", hroot, "overlay", MS_MGC_VAL, option) < 0)
905 errExit("mounting overlayfs for mounted home directory"); 905 errExit("mounting overlayfs for mounted home directory");
906 906
907 printf("OverlayFS for /home configured in %s directory\n", basedir); 907 printf("OverlayFS for /home configured in %s directory\n", basedir);
908 } // stat(overlayhome) 908 } // stat(overlayhome)
909 free(overlayhome); 909 free(overlayhome);
@@ -913,7 +913,7 @@ void fs_overlayfs(void) {
913 } 913 }
914 if (!arg_quiet) 914 if (!arg_quiet)
915 printf("OverlayFS configured in %s directory\n", basedir); 915 printf("OverlayFS configured in %s directory\n", basedir);
916 916
917 // mount-bind dev directory 917 // mount-bind dev directory
918 if (arg_debug) 918 if (arg_debug)
919 printf("Mounting /dev\n"); 919 printf("Mounting /dev\n");
@@ -964,7 +964,7 @@ void fs_overlayfs(void) {
964 fs_var_log(); 964 fs_var_log();
965 else 965 else
966 fs_rdwr("/var/log"); 966 fs_rdwr("/var/log");
967 967
968 fs_var_lib(); 968 fs_var_lib();
969 fs_var_cache(); 969 fs_var_cache();
970 fs_var_utmp(); 970 fs_var_utmp();
@@ -987,7 +987,7 @@ void fs_overlayfs(void) {
987#endif 987#endif
988 988
989 989
990#ifdef HAVE_CHROOT 990#ifdef HAVE_CHROOT
991// return 1 if error 991// return 1 if error
992void fs_check_chroot_dir(const char *rootdir) { 992void fs_check_chroot_dir(const char *rootdir) {
993 EUID_ASSERT(); 993 EUID_ASSERT();
@@ -1035,7 +1035,7 @@ void fs_check_chroot_dir(const char *rootdir) {
1035 exit(1); 1035 exit(1);
1036 } 1036 }
1037 free(name); 1037 free(name);
1038 1038
1039 // check /proc 1039 // check /proc
1040 if (asprintf(&name, "%s/proc", rootdir) == -1) 1040 if (asprintf(&name, "%s/proc", rootdir) == -1)
1041 errExit("asprintf"); 1041 errExit("asprintf");
@@ -1048,7 +1048,7 @@ void fs_check_chroot_dir(const char *rootdir) {
1048 exit(1); 1048 exit(1);
1049 } 1049 }
1050 free(name); 1050 free(name);
1051 1051
1052 // check /tmp 1052 // check /tmp
1053 if (asprintf(&name, "%s/tmp", rootdir) == -1) 1053 if (asprintf(&name, "%s/tmp", rootdir) == -1)
1054 errExit("asprintf"); 1054 errExit("asprintf");
@@ -1110,7 +1110,7 @@ void fs_check_chroot_dir(const char *rootdir) {
1110// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf 1110// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf
1111void fs_chroot(const char *rootdir) { 1111void fs_chroot(const char *rootdir) {
1112 assert(rootdir); 1112 assert(rootdir);
1113 1113
1114 if (checkcfg(CFG_CHROOT_DESKTOP)) { 1114 if (checkcfg(CFG_CHROOT_DESKTOP)) {
1115 // mount-bind a /dev in rootdir 1115 // mount-bind a /dev in rootdir
1116 char *newdev; 1116 char *newdev;
@@ -1121,7 +1121,7 @@ void fs_chroot(const char *rootdir) {
1121 if (mount("/dev", newdev, NULL, MS_BIND|MS_REC, NULL) < 0) 1121 if (mount("/dev", newdev, NULL, MS_BIND|MS_REC, NULL) < 0)
1122 errExit("mounting /dev"); 1122 errExit("mounting /dev");
1123 free(newdev); 1123 free(newdev);
1124 1124
1125 // x11 1125 // x11
1126 if (getenv("FIREJAIL_X11")) { 1126 if (getenv("FIREJAIL_X11")) {
1127 char *newx11; 1127 char *newx11;
@@ -1133,7 +1133,7 @@ void fs_chroot(const char *rootdir) {
1133 errExit("mounting /tmp/.X11-unix"); 1133 errExit("mounting /tmp/.X11-unix");
1134 free(newx11); 1134 free(newx11);
1135 } 1135 }
1136 1136
1137 // some older distros don't have a /run directory 1137 // some older distros don't have a /run directory
1138 // create one by default 1138 // create one by default
1139 // create /run/firejail directory in chroot 1139 // create /run/firejail directory in chroot
@@ -1150,7 +1150,7 @@ void fs_chroot(const char *rootdir) {
1150 errExit("asprintf"); 1150 errExit("asprintf");
1151 create_empty_dir_as_root(rundir, 0755); 1151 create_empty_dir_as_root(rundir, 0755);
1152 free(rundir); 1152 free(rundir);
1153 1153
1154 // create /run/firejail/mnt directory in chroot and mount the current one 1154 // create /run/firejail/mnt directory in chroot and mount the current one
1155 if (asprintf(&rundir, "%s%s", rootdir, RUN_MNT_DIR) == -1) 1155 if (asprintf(&rundir, "%s%s", rootdir, RUN_MNT_DIR) == -1)
1156 errExit("asprintf"); 1156 errExit("asprintf");
@@ -1173,7 +1173,7 @@ void fs_chroot(const char *rootdir) {
1173 if (copy_file("/etc/resolv.conf", fname, 0, 0, 0644) == -1) // root needed 1173 if (copy_file("/etc/resolv.conf", fname, 0, 0, 0644) == -1) // root needed
1174 fwarning("/etc/resolv.conf not initialized\n"); 1174 fwarning("/etc/resolv.conf not initialized\n");
1175 } 1175 }
1176 1176
1177 // chroot into the new directory 1177 // chroot into the new directory
1178#ifdef HAVE_GCOV 1178#ifdef HAVE_GCOV
1179 __gcov_flush(); 1179 __gcov_flush();
@@ -1196,15 +1196,15 @@ void fs_chroot(const char *rootdir) {
1196 fs_var_log(); 1196 fs_var_log();
1197 else 1197 else
1198 fs_rdwr("/var/log"); 1198 fs_rdwr("/var/log");
1199 1199
1200 fs_var_lib(); 1200 fs_var_lib();
1201 fs_var_cache(); 1201 fs_var_cache();
1202 fs_var_utmp(); 1202 fs_var_utmp();
1203 fs_machineid(); 1203 fs_machineid();
1204 1204
1205 // don't leak user information 1205 // don't leak user information
1206 restrict_users(); 1206 restrict_users();
1207 1207
1208 // when starting as root, firejail config is not disabled; 1208 // when starting as root, firejail config is not disabled;
1209 // this mode could be used to install and test new software by chaining 1209 // this mode could be used to install and test new software by chaining
1210 // firejail sandboxes (firejail --force) 1210 // firejail sandboxes (firejail --force)
@@ -1229,10 +1229,10 @@ void fs_private_tmp(void) {
1229 if (rp) 1229 if (rp)
1230 free(rp); 1230 free(rp);
1231 } 1231 }
1232 1232
1233 // whitelist x11 directory 1233 // whitelist x11 directory
1234 profile_add("whitelist /tmp/.X11-unix"); 1234 profile_add("whitelist /tmp/.X11-unix");
1235 1235
1236 // whitelist any pulse* file in /tmp directory 1236 // whitelist any pulse* file in /tmp directory
1237 // some distros use PulseAudio sockets under /tmp instead of the socket in /urn/user 1237 // some distros use PulseAudio sockets under /tmp instead of the socket in /urn/user
1238 DIR *dir; 1238 DIR *dir;
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c
index c572bec88..5170f2edc 100644
--- a/src/firejail/fs_bin.c
+++ b/src/firejail/fs_bin.c
@@ -39,10 +39,10 @@ static char *paths[] = {
39// return 1 if found, 0 if not found 39// return 1 if found, 0 if not found
40static char *check_dir_or_file(const char *name) { 40static char *check_dir_or_file(const char *name) {
41 assert(name); 41 assert(name);
42 42
43 struct stat s; 43 struct stat s;
44 char *fname = NULL; 44 char *fname = NULL;
45 45
46 int i = 0; 46 int i = 0;
47 while (paths[i]) { 47 while (paths[i]) {
48 // private-bin-no-local can be disabled in /etc/firejail/firejail.config 48 // private-bin-no-local can be disabled in /etc/firejail/firejail.config
@@ -50,12 +50,12 @@ static char *check_dir_or_file(const char *name) {
50 i++; 50 i++;
51 continue; 51 continue;
52 } 52 }
53 53
54 // check file 54 // check file
55 if (asprintf(&fname, "%s/%s", paths[i], name) == -1) 55 if (asprintf(&fname, "%s/%s", paths[i], name) == -1)
56 errExit("asprintf"); 56 errExit("asprintf");
57 if (arg_debug) 57 if (arg_debug)
58 printf("Checking %s/%s\n", paths[i], name); 58 printf("Checking %s/%s\n", paths[i], name);
59 if (stat(fname, &s) == 0 && !S_ISDIR(s.st_mode)) { // do not allow directories 59 if (stat(fname, &s) == 0 && !S_ISDIR(s.st_mode)) { // do not allow directories
60 // check symlink to firejail executable in /usr/local/bin 60 // check symlink to firejail executable in /usr/local/bin
61 if (strcmp(paths[i], "/usr/local/bin") == 0 && is_link(fname)) { 61 if (strcmp(paths[i], "/usr/local/bin") == 0 && is_link(fname)) {
@@ -74,11 +74,11 @@ static char *check_dir_or_file(const char *name) {
74 } 74 }
75 free(actual_path); 75 free(actual_path);
76 } 76 }
77 77
78 } 78 }
79 break; // file found 79 break; // file found
80 } 80 }
81 81
82 free(fname); 82 free(fname);
83 fname = NULL; 83 fname = NULL;
84 i++; 84 i++;
@@ -89,7 +89,7 @@ static char *check_dir_or_file(const char *name) {
89 fwarning("file %s not found\n", name); 89 fwarning("file %s not found\n", name);
90 return NULL; 90 return NULL;
91 } 91 }
92 92
93 free(fname); 93 free(fname);
94 return paths[i]; 94 return paths[i];
95} 95}
@@ -109,7 +109,7 @@ static void duplicate(char *fname) {
109 char *full_path; 109 char *full_path;
110 if (asprintf(&full_path, "%s/%s", path, fname) == -1) 110 if (asprintf(&full_path, "%s/%s", path, fname) == -1)
111 errExit("asprintf"); 111 errExit("asprintf");
112 112
113 // copy the file 113 // copy the file
114 if (checkcfg(CFG_FOLLOW_SYMLINK_PRIVATE_BIN)) 114 if (checkcfg(CFG_FOLLOW_SYMLINK_PRIVATE_BIN))
115 sbox_run(SBOX_ROOT| SBOX_SECCOMP, 4, PATH_FCOPY, "--follow-link", full_path, RUN_BIN_DIR); 115 sbox_run(SBOX_ROOT| SBOX_SECCOMP, 4, PATH_FCOPY, "--follow-link", full_path, RUN_BIN_DIR);
@@ -123,10 +123,10 @@ static void duplicate(char *fname) {
123void fs_private_bin_list(void) { 123void fs_private_bin_list(void) {
124 char *private_list = cfg.bin_private_keep; 124 char *private_list = cfg.bin_private_keep;
125 assert(private_list); 125 assert(private_list);
126 126
127 // create /run/firejail/mnt/bin directory 127 // create /run/firejail/mnt/bin directory
128 mkdir_attr(RUN_BIN_DIR, 0755, 0, 0); 128 mkdir_attr(RUN_BIN_DIR, 0755, 0, 0);
129 129
130 if (arg_debug) 130 if (arg_debug)
131 printf("Copying files in the new bin directory\n"); 131 printf("Copying files in the new bin directory\n");
132 132
@@ -134,12 +134,12 @@ void fs_private_bin_list(void) {
134 char *dlist = strdup(private_list); 134 char *dlist = strdup(private_list);
135 if (!dlist) 135 if (!dlist)
136 errExit("strdup"); 136 errExit("strdup");
137 137
138 char *ptr = strtok(dlist, ","); 138 char *ptr = strtok(dlist, ",");
139 duplicate(ptr); 139 duplicate(ptr);
140 while ((ptr = strtok(NULL, ",")) != NULL) 140 while ((ptr = strtok(NULL, ",")) != NULL)
141 duplicate(ptr); 141 duplicate(ptr);
142 free(dlist); 142 free(dlist);
143 fs_logger_print(); 143 fs_logger_print();
144 144
145 // mount-bind 145 // mount-bind
@@ -157,4 +157,3 @@ void fs_private_bin_list(void) {
157 i++; 157 i++;
158 } 158 }
159} 159}
160
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c
index 59700dd9b..b0835d50b 100644
--- a/src/firejail/fs_etc.c
+++ b/src/firejail/fs_etc.c
@@ -36,20 +36,20 @@ void fs_machineid(void) {
36 return; 36 return;
37 if (arg_debug) 37 if (arg_debug)
38 printf("Generating a new machine-id\n"); 38 printf("Generating a new machine-id\n");
39 39
40 // init random number generator 40 // init random number generator
41 srand(time(NULL)); 41 srand(time(NULL));
42 42
43 // generate random id 43 // generate random id
44 mid.u32[0] = rand(); 44 mid.u32[0] = rand();
45 mid.u32[1] = rand(); 45 mid.u32[1] = rand();
46 mid.u32[2] = rand(); 46 mid.u32[2] = rand();
47 mid.u32[3] = rand(); 47 mid.u32[3] = rand();
48 48
49 // UUID version 4 and DCE variant 49 // UUID version 4 and DCE variant
50 mid.u8[6] = (mid.u8[6] & 0x0F) | 0x40; 50 mid.u8[6] = (mid.u8[6] & 0x0F) | 0x40;
51 mid.u8[8] = (mid.u8[8] & 0x3F) | 0x80; 51 mid.u8[8] = (mid.u8[8] & 0x3F) | 0x80;
52 52
53 // write it in a file 53 // write it in a file
54 FILE *fp = fopen(RUN_MACHINEID, "w"); 54 FILE *fp = fopen(RUN_MACHINEID, "w");
55 if (!fp) 55 if (!fp)
@@ -58,7 +58,7 @@ void fs_machineid(void) {
58 fclose(fp); 58 fclose(fp);
59 if (set_perms(RUN_MACHINEID, 0, 0, 0444)) 59 if (set_perms(RUN_MACHINEID, 0, 0, 0444))
60 errExit("set_perms"); 60 errExit("set_perms");
61 61
62 62
63 struct stat s; 63 struct stat s;
64 if (stat("/etc/machine-id", &s) == 0) { 64 if (stat("/etc/machine-id", &s) == 0) {
@@ -93,7 +93,7 @@ static int check_dir_or_file(const char *fname) {
93 if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode) || !is_link(fname)) 93 if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode) || !is_link(fname))
94 return 1; // normal exit 94 return 1; // normal exit
95 95
96errexit: 96errexit:
97 fprintf(stderr, "Error: invalid file type, %s.\n", fname); 97 fprintf(stderr, "Error: invalid file type, %s.\n", fname);
98 exit(1); 98 exit(1);
99} 99}
@@ -116,7 +116,7 @@ static void duplicate(const char *fname, const char *private_dir, const char *pr
116 116
117 if (arg_debug) 117 if (arg_debug)
118 printf("copying %s to private %s\n", src, private_dir); 118 printf("copying %s to private %s\n", src, private_dir);
119 119
120 struct stat s; 120 struct stat s;
121 if (stat(src, &s) == 0 && S_ISDIR(s.st_mode)) { 121 if (stat(src, &s) == 0 && S_ISDIR(s.st_mode)) {
122 // create the directory in RUN_ETC_DIR 122 // create the directory in RUN_ETC_DIR
@@ -139,11 +139,11 @@ void fs_private_dir_list(const char *private_dir, const char *private_run_dir, c
139 assert(private_dir); 139 assert(private_dir);
140 assert(private_run_dir); 140 assert(private_run_dir);
141 assert(private_list); 141 assert(private_list);
142 142
143 // create /run/firejail/mnt/etc directory 143 // create /run/firejail/mnt/etc directory
144 mkdir_attr(private_run_dir, 0755, 0, 0); 144 mkdir_attr(private_run_dir, 0755, 0, 0);
145 fs_logger2("tmpfs", private_dir); 145 fs_logger2("tmpfs", private_dir);
146 146
147 fs_logger_print(); // save the current log 147 fs_logger_print(); // save the current log
148 148
149 149
@@ -157,21 +157,20 @@ void fs_private_dir_list(const char *private_dir, const char *private_run_dir, c
157 char *dlist = strdup(private_list); 157 char *dlist = strdup(private_list);
158 if (!dlist) 158 if (!dlist)
159 errExit("strdup"); 159 errExit("strdup");
160 160
161 161
162 char *ptr = strtok(dlist, ","); 162 char *ptr = strtok(dlist, ",");
163 duplicate(ptr, private_dir, private_run_dir); 163 duplicate(ptr, private_dir, private_run_dir);
164 164
165 while ((ptr = strtok(NULL, ",")) != NULL) 165 while ((ptr = strtok(NULL, ",")) != NULL)
166 duplicate(ptr, private_dir, private_run_dir); 166 duplicate(ptr, private_dir, private_run_dir);
167 free(dlist); 167 free(dlist);
168 fs_logger_print(); 168 fs_logger_print();
169 } 169 }
170 170
171 if (arg_debug) 171 if (arg_debug)
172 printf("Mount-bind %s on top of %s\n", private_run_dir, private_dir); 172 printf("Mount-bind %s on top of %s\n", private_run_dir, private_dir);
173 if (mount(private_run_dir, private_dir, NULL, MS_BIND|MS_REC, NULL) < 0) 173 if (mount(private_run_dir, private_dir, NULL, MS_BIND|MS_REC, NULL) < 0)
174 errExit("mount bind"); 174 errExit("mount bind");
175 fs_logger2("mount", private_dir); 175 fs_logger2("mount", private_dir);
176} 176}
177
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index 70f0388e6..e5e068583 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -63,7 +63,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
63 if (asprintf(&fname, "%s/.cshrc", homedir) == -1) 63 if (asprintf(&fname, "%s/.cshrc", homedir) == -1)
64 errExit("asprintf"); 64 errExit("asprintf");
65 struct stat s; 65 struct stat s;
66 66
67 // don't copy it if we already have the file 67 // don't copy it if we already have the file
68 if (stat(fname, &s) == 0) 68 if (stat(fname, &s) == 0)
69 return; 69 return;
@@ -88,7 +88,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
88 errExit("asprintf"); 88 errExit("asprintf");
89 struct stat s; 89 struct stat s;
90 // don't copy it if we already have the file 90 // don't copy it if we already have the file
91 if (stat(fname, &s) == 0) 91 if (stat(fname, &s) == 0)
92 return; 92 return;
93 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat 93 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat
94 fprintf(stderr, "Error: invalid %s file\n", fname); 94 fprintf(stderr, "Error: invalid %s file\n", fname);
@@ -113,10 +113,10 @@ static int store_xauthority(void) {
113 SET_PERMS_STREAM(fp, getuid(), getgid(), 0600); 113 SET_PERMS_STREAM(fp, getuid(), getgid(), 0600);
114 fclose(fp); 114 fclose(fp);
115 } 115 }
116 116
117 if (asprintf(&src, "%s/.Xauthority", cfg.homedir) == -1) 117 if (asprintf(&src, "%s/.Xauthority", cfg.homedir) == -1)
118 errExit("asprintf"); 118 errExit("asprintf");
119 119
120 struct stat s; 120 struct stat s;
121 if (stat(src, &s) == 0) { 121 if (stat(src, &s) == 0) {
122 if (is_link(src)) { 122 if (is_link(src)) {
@@ -128,7 +128,7 @@ static int store_xauthority(void) {
128 fs_logger2("clone", dest); 128 fs_logger2("clone", dest);
129 return 1; // file copied 129 return 1; // file copied
130 } 130 }
131 131
132 return 0; 132 return 0;
133} 133}
134 134
@@ -143,10 +143,10 @@ static int store_asoundrc(void) {
143 SET_PERMS_STREAM(fp, getuid(), getgid(), 0644); 143 SET_PERMS_STREAM(fp, getuid(), getgid(), 0644);
144 fclose(fp); 144 fclose(fp);
145 } 145 }
146 146
147 if (asprintf(&src, "%s/.asoundrc", cfg.homedir) == -1) 147 if (asprintf(&src, "%s/.asoundrc", cfg.homedir) == -1)
148 errExit("asprintf"); 148 errExit("asprintf");
149 149
150 struct stat s; 150 struct stat s;
151 if (stat(src, &s) == 0) { 151 if (stat(src, &s) == 0) {
152 if (is_link(src)) { 152 if (is_link(src)) {
@@ -168,7 +168,7 @@ static int store_asoundrc(void) {
168 fs_logger2("clone", dest); 168 fs_logger2("clone", dest);
169 return 1; // file copied 169 return 1; // file copied
170 } 170 }
171 171
172 return 0; 172 return 0;
173} 173}
174 174
@@ -178,7 +178,7 @@ static void copy_xauthority(void) {
178 char *dest; 178 char *dest;
179 if (asprintf(&dest, "%s/.Xauthority", cfg.homedir) == -1) 179 if (asprintf(&dest, "%s/.Xauthority", cfg.homedir) == -1)
180 errExit("asprintf"); 180 errExit("asprintf");
181 181
182 // if destination is a symbolic link, exit the sandbox!!! 182 // if destination is a symbolic link, exit the sandbox!!!
183 if (is_link(dest)) { 183 if (is_link(dest)) {
184 fprintf(stderr, "Error: %s is a symbolic link\n", dest); 184 fprintf(stderr, "Error: %s is a symbolic link\n", dest);
@@ -187,7 +187,7 @@ static void copy_xauthority(void) {
187 187
188 copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); // regular user 188 copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); // regular user
189 fs_logger2("clone", dest); 189 fs_logger2("clone", dest);
190 190
191 // delete the temporary file 191 // delete the temporary file
192 unlink(src); 192 unlink(src);
193} 193}
@@ -198,7 +198,7 @@ static void copy_asoundrc(void) {
198 char *dest; 198 char *dest;
199 if (asprintf(&dest, "%s/.asoundrc", cfg.homedir) == -1) 199 if (asprintf(&dest, "%s/.asoundrc", cfg.homedir) == -1)
200 errExit("asprintf"); 200 errExit("asprintf");
201 201
202 // if destination is a symbolic link, exit the sandbox!!! 202 // if destination is a symbolic link, exit the sandbox!!!
203 if (is_link(dest)) { 203 if (is_link(dest)) {
204 fprintf(stderr, "Error: %s is a symbolic link\n", dest); 204 fprintf(stderr, "Error: %s is a symbolic link\n", dest);
@@ -222,10 +222,10 @@ void fs_private_homedir(void) {
222 char *private_homedir = cfg.home_private; 222 char *private_homedir = cfg.home_private;
223 assert(homedir); 223 assert(homedir);
224 assert(private_homedir); 224 assert(private_homedir);
225 225
226 int xflag = store_xauthority(); 226 int xflag = store_xauthority();
227 int aflag = store_asoundrc(); 227 int aflag = store_asoundrc();
228 228
229 uid_t u = getuid(); 229 uid_t u = getuid();
230 gid_t g = getgid(); 230 gid_t g = getgid();
231 231
@@ -258,7 +258,7 @@ void fs_private_homedir(void) {
258 errExit("mounting home directory"); 258 errExit("mounting home directory");
259 fs_logger("tmpfs /home"); 259 fs_logger("tmpfs /home");
260 } 260 }
261 261
262 262
263 skel(homedir, u, g); 263 skel(homedir, u, g);
264 if (xflag) 264 if (xflag)
@@ -309,7 +309,7 @@ void fs_private(void) {
309 errExit("chown"); 309 errExit("chown");
310 fs_logger2("mkdir", homedir); 310 fs_logger2("mkdir", homedir);
311 } 311 }
312 312
313 skel(homedir, u, g); 313 skel(homedir, u, g);
314 if (xflag) 314 if (xflag)
315 copy_xauthority(); 315 copy_xauthority();
@@ -322,12 +322,12 @@ void fs_private(void) {
322void fs_check_private_dir(void) { 322void fs_check_private_dir(void) {
323 EUID_ASSERT(); 323 EUID_ASSERT();
324 invalid_filename(cfg.home_private); 324 invalid_filename(cfg.home_private);
325 325
326 // Expand the home directory 326 // Expand the home directory
327 char *tmp = expand_home(cfg.home_private, cfg.homedir); 327 char *tmp = expand_home(cfg.home_private, cfg.homedir);
328 cfg.home_private = realpath(tmp, NULL); 328 cfg.home_private = realpath(tmp, NULL);
329 free(tmp); 329 free(tmp);
330 330
331 if (!cfg.home_private 331 if (!cfg.home_private
332 || !is_dir(cfg.home_private) 332 || !is_dir(cfg.home_private)
333 || is_link(cfg.home_private) 333 || is_link(cfg.home_private)
@@ -383,7 +383,7 @@ static char *check_dir_or_file(const char *name) {
383 // we allow only files in user home directory or symbolic links to files or directories owned by the user 383 // we allow only files in user home directory or symbolic links to files or directories owned by the user
384 struct stat s; 384 struct stat s;
385 if (lstat(fname, &s) == 0 && S_ISLNK(s.st_mode)) { 385 if (lstat(fname, &s) == 0 && S_ISLNK(s.st_mode)) {
386 if (stat(fname, &s) == 0) { 386 if (stat(fname, &s) == 0) {
387 if (s.st_uid != getuid()) { 387 if (s.st_uid != getuid()) {
388 fprintf(stderr, "Error: symbolic link %s to file or directory not owned by the user\n", fname); 388 fprintf(stderr, "Error: symbolic link %s to file or directory not owned by the user\n", fname);
389 exit(1); 389 exit(1);
@@ -404,7 +404,7 @@ static char *check_dir_or_file(const char *name) {
404 fprintf(stderr, "Error: invalid file %s\n", name); 404 fprintf(stderr, "Error: invalid file %s\n", name);
405 exit(1); 405 exit(1);
406 } 406 }
407 407
408 // only top files and directories in user home are allowed 408 // only top files and directories in user home are allowed
409 char *ptr = rname + strlen(cfg.homedir); 409 char *ptr = rname + strlen(cfg.homedir);
410 assert(*ptr != '\0'); 410 assert(*ptr != '\0');
@@ -480,7 +480,7 @@ void fs_private_home_list(void) {
480 char *dlist = strdup(cfg.home_private_keep); 480 char *dlist = strdup(cfg.home_private_keep);
481 if (!dlist) 481 if (!dlist)
482 errExit("strdup"); 482 errExit("strdup");
483 483
484 char *ptr = strtok(dlist, ","); 484 char *ptr = strtok(dlist, ",");
485 duplicate(ptr); 485 duplicate(ptr);
486 while ((ptr = strtok(NULL, ",")) != NULL) 486 while ((ptr = strtok(NULL, ",")) != NULL)
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c
index 32243c700..42255070c 100644
--- a/src/firejail/fs_hostname.c
+++ b/src/firejail/fs_hostname.c
@@ -27,7 +27,7 @@
27 27
28void fs_hostname(const char *hostname) { 28void fs_hostname(const char *hostname) {
29 struct stat s; 29 struct stat s;
30 30
31 // create a new /etc/hostname 31 // create a new /etc/hostname
32 if (stat("/etc/hostname", &s) == 0) { 32 if (stat("/etc/hostname", &s) == 0) {
33 if (arg_debug) 33 if (arg_debug)
@@ -40,7 +40,7 @@ void fs_hostname(const char *hostname) {
40 errExit("mount bind /etc/hostname"); 40 errExit("mount bind /etc/hostname");
41 fs_logger("create /etc/hostname"); 41 fs_logger("create /etc/hostname");
42 } 42 }
43 43
44 // create a new /etc/hosts 44 // create a new /etc/hosts
45 if (cfg.hosts_file == NULL && stat("/etc/hosts", &s) == 0) { 45 if (cfg.hosts_file == NULL && stat("/etc/hosts", &s) == 0) {
46 if (arg_debug) 46 if (arg_debug)
@@ -56,7 +56,7 @@ void fs_hostname(const char *hostname) {
56 fclose(fp1); 56 fclose(fp1);
57 goto errexit; 57 goto errexit;
58 } 58 }
59 59
60 char buf[4096]; 60 char buf[4096];
61 int done = 0; 61 int done = 0;
62 while (fgets(buf, sizeof(buf), fp1)) { 62 while (fgets(buf, sizeof(buf), fp1)) {
@@ -64,7 +64,7 @@ void fs_hostname(const char *hostname) {
64 char *ptr = strchr(buf, '\n'); 64 char *ptr = strchr(buf, '\n');
65 if (ptr) 65 if (ptr)
66 *ptr = '\0'; 66 *ptr = '\0';
67 67
68 // copy line 68 // copy line
69 if (strstr(buf, "127.0.0.1") && done == 0) { 69 if (strstr(buf, "127.0.0.1") && done == 0) {
70 done = 1; 70 done = 1;
@@ -77,7 +77,7 @@ void fs_hostname(const char *hostname) {
77 // mode and owner 77 // mode and owner
78 SET_PERMS_STREAM(fp2, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 78 SET_PERMS_STREAM(fp2, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH);
79 fclose(fp2); 79 fclose(fp2);
80 80
81 // bind-mount the file on top of /etc/hostname 81 // bind-mount the file on top of /etc/hostname
82 fs_mount_hosts_file(); 82 fs_mount_hosts_file();
83 } 83 }
@@ -93,7 +93,7 @@ void fs_resolvconf(void) {
93 return; 93 return;
94 94
95 struct stat s; 95 struct stat s;
96 96
97 // create a new /etc/hostname 97 // create a new /etc/hostname
98 if (stat("/etc/resolv.conf", &s) == 0) { 98 if (stat("/etc/resolv.conf", &s) == 0) {
99 if (arg_debug) 99 if (arg_debug)
@@ -103,7 +103,7 @@ void fs_resolvconf(void) {
103 fprintf(stderr, "Error: cannot create %s\n", RUN_RESOLVCONF_FILE); 103 fprintf(stderr, "Error: cannot create %s\n", RUN_RESOLVCONF_FILE);
104 exit(1); 104 exit(1);
105 } 105 }
106 106
107 if (cfg.dns1) 107 if (cfg.dns1)
108 fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns1)); 108 fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
109 if (cfg.dns2) 109 if (cfg.dns2)
@@ -115,7 +115,7 @@ void fs_resolvconf(void) {
115 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 115 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH);
116 116
117 fclose(fp); 117 fclose(fp);
118 118
119 // bind-mount the file on top of /etc/hostname 119 // bind-mount the file on top of /etc/hostname
120 if (mount(RUN_RESOLVCONF_FILE, "/etc/resolv.conf", NULL, MS_BIND|MS_REC, NULL) < 0) 120 if (mount(RUN_RESOLVCONF_FILE, "/etc/resolv.conf", NULL, MS_BIND|MS_REC, NULL) < 0)
121 errExit("mount bind /etc/resolv.conf"); 121 errExit("mount bind /etc/resolv.conf");
@@ -135,7 +135,7 @@ char *fs_check_hosts_file(const char *fname) {
135 // no a link 135 // no a link
136 if (is_link(rv)) 136 if (is_link(rv))
137 goto errexit; 137 goto errexit;
138 138
139 // the user has read access to the file 139 // the user has read access to the file
140 if (access(rv, R_OK)) 140 if (access(rv, R_OK))
141 goto errexit; 141 goto errexit;
@@ -175,4 +175,3 @@ errexit:
175 fprintf(stderr, "Error: invalid /etc/hosts file\n"); 175 fprintf(stderr, "Error: invalid /etc/hosts file\n");
176 exit(1); 176 exit(1);
177} 177}
178
diff --git a/src/firejail/fs_logger.c b/src/firejail/fs_logger.c
index a2b6b317e..354e720a1 100644
--- a/src/firejail/fs_logger.c
+++ b/src/firejail/fs_logger.c
@@ -17,7 +17,7 @@
17 * with this program; if not, write to the Free Software Foundation, Inc., 17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20 20
21#include "firejail.h" 21#include "firejail.h"
22#include <sys/types.h> 22#include <sys/types.h>
23#include <sys/stat.h> 23#include <sys/stat.h>
@@ -47,7 +47,7 @@ static inline void insertmsg(FsMsg *ptr) {
47 last = ptr; 47 last = ptr;
48 return; 48 return;
49 } 49 }
50 50
51 assert(last); 51 assert(last);
52 last->next = ptr; 52 last->next = ptr;
53 last = ptr; 53 last = ptr;
@@ -91,14 +91,14 @@ void fs_logger3(const char *msg1, const char *msg2, const char *msg3) {
91void fs_logger_print(void) { 91void fs_logger_print(void) {
92 if (!head) 92 if (!head)
93 return; 93 return;
94 94
95 FILE *fp = fopen(RUN_FSLOGGER_FILE, "a"); 95 FILE *fp = fopen(RUN_FSLOGGER_FILE, "a");
96 if (!fp) { 96 if (!fp) {
97 perror("fopen"); 97 perror("fopen");
98 return; 98 return;
99 } 99 }
100 SET_PERMS_STREAM_NOERR(fp, getuid(), getgid(), 0644); 100 SET_PERMS_STREAM_NOERR(fp, getuid(), getgid(), 0644);
101 101
102 FsMsg *ptr = head; 102 FsMsg *ptr = head;
103 while (ptr) { 103 while (ptr) {
104 fprintf(fp, "%s\n", ptr->msg); 104 fprintf(fp, "%s\n", ptr->msg);
@@ -162,7 +162,7 @@ void fs_logger_print_log(pid_t pid) {
162 fprintf(stderr, "Error: Cannot open filesystem log\n"); 162 fprintf(stderr, "Error: Cannot open filesystem log\n");
163 exit(1); 163 exit(1);
164 } 164 }
165 165
166 char buf[MAXBUF]; 166 char buf[MAXBUF];
167 while (fgets(buf, MAXBUF, fp)) 167 while (fgets(buf, MAXBUF, fp))
168 printf("%s", buf); 168 printf("%s", buf);
diff --git a/src/firejail/fs_mkdir.c b/src/firejail/fs_mkdir.c
index 4397f0721..20ffe825a 100644
--- a/src/firejail/fs_mkdir.c
+++ b/src/firejail/fs_mkdir.c
@@ -57,7 +57,7 @@ static void mkdir_recursive(char *path) {
57 57
58void fs_mkdir(const char *name) { 58void fs_mkdir(const char *name) {
59 EUID_ASSERT(); 59 EUID_ASSERT();
60 60
61 // check directory name 61 // check directory name
62 invalid_filename(name); 62 invalid_filename(name);
63 char *expanded = expand_home(name, cfg.homedir); 63 char *expanded = expand_home(name, cfg.homedir);
@@ -93,11 +93,11 @@ void fs_mkdir(const char *name) {
93 93
94doexit: 94doexit:
95 free(expanded); 95 free(expanded);
96} 96}
97 97
98void fs_mkfile(const char *name) { 98void fs_mkfile(const char *name) {
99 EUID_ASSERT(); 99 EUID_ASSERT();
100 100
101 // check file name 101 // check file name
102 invalid_filename(name); 102 invalid_filename(name);
103 char *expanded = expand_home(name, cfg.homedir); 103 char *expanded = expand_home(name, cfg.homedir);
@@ -115,7 +115,7 @@ void fs_mkfile(const char *name) {
115 115
116 // create file 116 // create file
117 touch_file_as_user(expanded, getuid(), getgid(), 0600); 117 touch_file_as_user(expanded, getuid(), getgid(), 0600);
118 118
119doexit: 119doexit:
120 free(expanded); 120 free(expanded);
121} 121}
diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c
index 2a58d1eb2..f964c05d0 100644
--- a/src/firejail/fs_trace.c
+++ b/src/firejail/fs_trace.c
@@ -58,11 +58,11 @@ void fs_trace(void) {
58 fprintf(fp, "%s/firejail/libtracelog.so\n", LIBDIR); 58 fprintf(fp, "%s/firejail/libtracelog.so\n", LIBDIR);
59 if (!arg_quiet) 59 if (!arg_quiet)
60 printf("Blacklist violations are logged to syslog\n"); 60 printf("Blacklist violations are logged to syslog\n");
61 } 61 }
62 62
63 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 63 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH);
64 fclose(fp); 64 fclose(fp);
65 65
66 // mount the new preload file 66 // mount the new preload file
67 if (arg_debug) 67 if (arg_debug)
68 printf("Mount the new ld.so.preload file\n"); 68 printf("Mount the new ld.so.preload file\n");
@@ -70,4 +70,3 @@ void fs_trace(void) {
70 errExit("mount bind ld.so.preload"); 70 errExit("mount bind ld.so.preload");
71 fs_logger("create /etc/ld.so.preload"); 71 fs_logger("create /etc/ld.so.preload");
72} 72}
73
diff --git a/src/firejail/fs_var.c b/src/firejail/fs_var.c
index 426ef48bf..9452d162d 100644
--- a/src/firejail/fs_var.c
+++ b/src/firejail/fs_var.c
@@ -48,7 +48,7 @@ static void release_all(void) {
48 } 48 }
49 dirlist = NULL; 49 dirlist = NULL;
50} 50}
51 51
52static void build_list(const char *srcdir) { 52static void build_list(const char *srcdir) {
53 // extract current /var/log directory data 53 // extract current /var/log directory data
54 struct dirent *dir; 54 struct dirent *dir;
@@ -77,7 +77,7 @@ static void build_list(const char *srcdir) {
77// s.st_uid, 77// s.st_uid,
78// s.st_gid, 78// s.st_gid,
79// dir->d_name); 79// dir->d_name);
80 80
81 DirData *ptr = malloc(sizeof(DirData)); 81 DirData *ptr = malloc(sizeof(DirData));
82 if (ptr == NULL) 82 if (ptr == NULL)
83 errExit("malloc"); 83 errExit("malloc");
@@ -87,8 +87,8 @@ static void build_list(const char *srcdir) {
87 ptr->st_uid = s.st_uid; 87 ptr->st_uid = s.st_uid;
88 ptr->st_gid = s.st_gid; 88 ptr->st_gid = s.st_gid;
89 ptr->next = dirlist; 89 ptr->next = dirlist;
90 dirlist = ptr; 90 dirlist = ptr;
91 } 91 }
92 } 92 }
93 closedir(d); 93 closedir(d);
94} 94}
@@ -102,10 +102,10 @@ static void build_dirs(void) {
102 ptr = ptr->next; 102 ptr = ptr->next;
103 } 103 }
104} 104}
105 105
106void fs_var_log(void) { 106void fs_var_log(void) {
107 build_list("/var/log"); 107 build_list("/var/log");
108 108
109 // note: /var/log is not created here, if it does not exist, this section fails. 109 // note: /var/log is not created here, if it does not exist, this section fails.
110 // create /var/log if it doesn't exit 110 // create /var/log if it doesn't exit
111 if (is_dir("/var/log")) { 111 if (is_dir("/var/log")) {
@@ -114,17 +114,17 @@ void fs_var_log(void) {
114 gid_t wtmp_group = 0; 114 gid_t wtmp_group = 0;
115 if (stat("/var/log/wtmp", &s) == 0) 115 if (stat("/var/log/wtmp", &s) == 0)
116 wtmp_group = s.st_gid; 116 wtmp_group = s.st_gid;
117 117
118 // mount a tmpfs on top of /var/log 118 // mount a tmpfs on top of /var/log
119 if (arg_debug) 119 if (arg_debug)
120 printf("Mounting tmpfs on /var/log\n"); 120 printf("Mounting tmpfs on /var/log\n");
121 if (mount("tmpfs", "/var/log", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) 121 if (mount("tmpfs", "/var/log", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
122 errExit("mounting /var/log"); 122 errExit("mounting /var/log");
123 fs_logger("tmpfs /var/log"); 123 fs_logger("tmpfs /var/log");
124 124
125 build_dirs(); 125 build_dirs();
126 release_all(); 126 release_all();
127 127
128 // create an empty /var/log/wtmp file 128 // create an empty /var/log/wtmp file
129 /* coverity[toctou] */ 129 /* coverity[toctou] */
130 FILE *fp = fopen("/var/log/wtmp", "w"); 130 FILE *fp = fopen("/var/log/wtmp", "w");
@@ -133,7 +133,7 @@ void fs_var_log(void) {
133 fclose(fp); 133 fclose(fp);
134 } 134 }
135 fs_logger("touch /var/log/wtmp"); 135 fs_logger("touch /var/log/wtmp");
136 136
137 // create an empty /var/log/btmp file 137 // create an empty /var/log/btmp file
138 fp = fopen("/var/log/btmp", "w"); 138 fp = fopen("/var/log/btmp", "w");
139 if (fp) { 139 if (fp) {
@@ -148,7 +148,7 @@ void fs_var_log(void) {
148 148
149void fs_var_lib(void) { 149void fs_var_lib(void) {
150 struct stat s; 150 struct stat s;
151 151
152 // ISC DHCP multiserver 152 // ISC DHCP multiserver
153 if (stat("/var/lib/dhcp", &s) == 0) { 153 if (stat("/var/lib/dhcp", &s) == 0) {
154 if (arg_debug) 154 if (arg_debug)
@@ -156,10 +156,10 @@ void fs_var_lib(void) {
156 if (mount("tmpfs", "/var/lib/dhcp", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) 156 if (mount("tmpfs", "/var/lib/dhcp", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
157 errExit("mounting /var/lib/dhcp"); 157 errExit("mounting /var/lib/dhcp");
158 fs_logger("tmpfs /var/lib/dhcp"); 158 fs_logger("tmpfs /var/lib/dhcp");
159 159
160 // isc dhcp server requires a /var/lib/dhcp/dhcpd.leases file 160 // isc dhcp server requires a /var/lib/dhcp/dhcpd.leases file
161 FILE *fp = fopen("/var/lib/dhcp/dhcpd.leases", "w"); 161 FILE *fp = fopen("/var/lib/dhcp/dhcpd.leases", "w");
162 162
163 if (fp) { 163 if (fp) {
164 fprintf(fp, "\n"); 164 fprintf(fp, "\n");
165 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 165 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
@@ -175,7 +175,7 @@ void fs_var_lib(void) {
175 if (mount("tmpfs", "/var/lib/nginx", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) 175 if (mount("tmpfs", "/var/lib/nginx", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
176 errExit("mounting /var/lib/nginx"); 176 errExit("mounting /var/lib/nginx");
177 fs_logger("tmpfs /var/lib/nginx"); 177 fs_logger("tmpfs /var/lib/nginx");
178 } 178 }
179 179
180 // net-snmp multiserver 180 // net-snmp multiserver
181 if (stat("/var/lib/snmp", &s) == 0) { 181 if (stat("/var/lib/snmp", &s) == 0) {
@@ -184,7 +184,7 @@ void fs_var_lib(void) {
184 if (mount("tmpfs", "/var/lib/snmp", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) 184 if (mount("tmpfs", "/var/lib/snmp", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
185 errExit("mounting /var/lib/snmp"); 185 errExit("mounting /var/lib/snmp");
186 fs_logger("tmpfs /var/lib/snmp"); 186 fs_logger("tmpfs /var/lib/snmp");
187 } 187 }
188 188
189 // this is where sudo remembers its state 189 // this is where sudo remembers its state
190 if (stat("/var/lib/sudo", &s) == 0) { 190 if (stat("/var/lib/sudo", &s) == 0) {
@@ -193,7 +193,7 @@ void fs_var_lib(void) {
193 if (mount("tmpfs", "/var/lib/sudo", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) 193 if (mount("tmpfs", "/var/lib/sudo", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
194 errExit("mounting /var/lib/sudo"); 194 errExit("mounting /var/lib/sudo");
195 fs_logger("tmpfs /var/lib/sudo"); 195 fs_logger("tmpfs /var/lib/sudo");
196 } 196 }
197} 197}
198 198
199void fs_var_cache(void) { 199void fs_var_cache(void) {
@@ -205,7 +205,7 @@ void fs_var_cache(void) {
205 if (mount("tmpfs", "/var/cache/apache2", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) 205 if (mount("tmpfs", "/var/cache/apache2", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
206 errExit("mounting /var/cache/apache2"); 206 errExit("mounting /var/cache/apache2");
207 fs_logger("tmpfs /var/cache/apache2"); 207 fs_logger("tmpfs /var/cache/apache2");
208 } 208 }
209 209
210 if (stat("/var/cache/lighttpd", &s) == 0) { 210 if (stat("/var/cache/lighttpd", &s) == 0) {
211 if (arg_debug) 211 if (arg_debug)
@@ -221,13 +221,13 @@ void fs_var_cache(void) {
221 uid = p->pw_uid; 221 uid = p->pw_uid;
222 gid = p->pw_gid; 222 gid = p->pw_gid;
223 } 223 }
224 224
225 mkdir_attr("/var/cache/lighttpd/compress", 0755, uid, gid); 225 mkdir_attr("/var/cache/lighttpd/compress", 0755, uid, gid);
226 fs_logger("mkdir /var/cache/lighttpd/compress"); 226 fs_logger("mkdir /var/cache/lighttpd/compress");
227 227
228 mkdir_attr("/var/cache/lighttpd/uploads", 0755, uid, gid); 228 mkdir_attr("/var/cache/lighttpd/uploads", 0755, uid, gid);
229 fs_logger("/var/cache/lighttpd/uploads"); 229 fs_logger("/var/cache/lighttpd/uploads");
230 } 230 }
231} 231}
232 232
233void dbg_test_dir(const char *dir) { 233void dbg_test_dir(const char *dir) {
@@ -312,7 +312,7 @@ void fs_var_utmp(void) {
312 FILE *fp = fopen(RUN_UTMP_FILE, "w"); 312 FILE *fp = fopen(RUN_UTMP_FILE, "w");
313 if (!fp) 313 if (!fp)
314 errExit("fopen"); 314 errExit("fopen");
315 315
316 // read current utmp 316 // read current utmp
317 struct utmp *u; 317 struct utmp *u;
318 struct utmp u_boot; 318 struct utmp u_boot;
@@ -324,12 +324,12 @@ void fs_var_utmp(void) {
324 } 324 }
325 } 325 }
326 endutent(); 326 endutent();
327 327
328 // save new utmp file 328 // save new utmp file
329 fwrite(&u_boot, sizeof(u_boot), 1, fp); 329 fwrite(&u_boot, sizeof(u_boot), 1, fp);
330 SET_PERMS_STREAM(fp, 0, utmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH); 330 SET_PERMS_STREAM(fp, 0, utmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH);
331 fclose(fp); 331 fclose(fp);
332 332
333 // mount the new utmp file 333 // mount the new utmp file
334 if (arg_debug) 334 if (arg_debug)
335 printf("Mount the new utmp file\n"); 335 printf("Mount the new utmp file\n");
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c
index 407192200..3403c57a7 100644
--- a/src/firejail/fs_whitelist.c
+++ b/src/firejail/fs_whitelist.c
@@ -44,11 +44,11 @@ static char *resolve_downloads(int nowhitelist_flag) {
44 while (dentry[i] != NULL) { 44 while (dentry[i] != NULL) {
45 if (asprintf(&fname, "%s/%s", cfg.homedir, dentry[i]) == -1) 45 if (asprintf(&fname, "%s/%s", cfg.homedir, dentry[i]) == -1)
46 errExit("asprintf"); 46 errExit("asprintf");
47 47
48 if (stat(fname, &s) == 0) { 48 if (stat(fname, &s) == 0) {
49 if (arg_debug || arg_debug_whitelists) 49 if (arg_debug || arg_debug_whitelists)
50 printf("Downloads directory resolved as \"%s\"\n", fname); 50 printf("Downloads directory resolved as \"%s\"\n", fname);
51 51
52 char *rv; 52 char *rv;
53 if (nowhitelist_flag) { 53 if (nowhitelist_flag) {
54 if (asprintf(&rv, "nowhitelist ~/%s", dentry[i]) == -1) 54 if (asprintf(&rv, "nowhitelist ~/%s", dentry[i]) == -1)
@@ -72,14 +72,14 @@ static char *resolve_downloads(int nowhitelist_flag) {
72 if (!fp) { 72 if (!fp) {
73 free(fname); 73 free(fname);
74 return NULL; 74 return NULL;
75 } 75 }
76 free(fname); 76 free(fname);
77 77
78 // extract downloads directory 78 // extract downloads directory
79 char buf[MAXBUF]; 79 char buf[MAXBUF];
80 while (fgets(buf, MAXBUF, fp)) { 80 while (fgets(buf, MAXBUF, fp)) {
81 char *ptr = buf; 81 char *ptr = buf;
82 82
83 // skip blanks 83 // skip blanks
84 while (*ptr == ' ' || *ptr == '\t') 84 while (*ptr == ' ' || *ptr == '\t')
85 ptr++; 85 ptr++;
@@ -97,15 +97,15 @@ static char *resolve_downloads(int nowhitelist_flag) {
97 if (strlen(ptr1) != 0) { 97 if (strlen(ptr1) != 0) {
98 if (arg_debug || arg_debug_whitelists) 98 if (arg_debug || arg_debug_whitelists)
99 printf("Downloads directory resolved as \"%s\"\n", ptr1); 99 printf("Downloads directory resolved as \"%s\"\n", ptr1);
100 100
101 if (asprintf(&fname, "%s/%s", cfg.homedir, ptr1) == -1) 101 if (asprintf(&fname, "%s/%s", cfg.homedir, ptr1) == -1)
102 errExit("asprintf"); 102 errExit("asprintf");
103 103
104 if (stat(fname, &s) == -1) { 104 if (stat(fname, &s) == -1) {
105 free(fname); 105 free(fname);
106 goto errout; 106 goto errout;
107 } 107 }
108 108
109 char *rv; 109 char *rv;
110 if (nowhitelist_flag) { 110 if (nowhitelist_flag) {
111 if (asprintf(&rv, "nowhitelist ~/%s", ptr + 24) == -1) 111 if (asprintf(&rv, "nowhitelist ~/%s", ptr + 24) == -1)
@@ -122,7 +122,7 @@ static char *resolve_downloads(int nowhitelist_flag) {
122 } 122 }
123 } 123 }
124 } 124 }
125 125
126 fclose(fp); 126 fclose(fp);
127 return NULL; 127 return NULL;
128 128
@@ -131,13 +131,13 @@ errout:
131 fprintf(stderr, "*** Error: Downloads directory was not found in user home.\n"); 131 fprintf(stderr, "*** Error: Downloads directory was not found in user home.\n");
132 fprintf(stderr, "*** \tAny files saved by the program, will be lost when the sandbox is closed.\n"); 132 fprintf(stderr, "*** \tAny files saved by the program, will be lost when the sandbox is closed.\n");
133 fprintf(stderr, "***\n"); 133 fprintf(stderr, "***\n");
134 134
135 return NULL; 135 return NULL;
136} 136}
137 137
138static int mkpath(const char* path, mode_t mode) { 138static int mkpath(const char* path, mode_t mode) {
139 assert(path && *path); 139 assert(path && *path);
140 140
141 mode |= 0111; 141 mode |= 0111;
142 142
143 // create directories with uid/gid as root or as current user if inside home directory 143 // create directories with uid/gid as root or as current user if inside home directory
@@ -168,13 +168,13 @@ static int mkpath(const char* path, mode_t mode) {
168 if (set_perms(file_path, uid, gid, mode)) 168 if (set_perms(file_path, uid, gid, mode))
169 errExit("set_perms"); 169 errExit("set_perms");
170 done = 1; 170 done = 1;
171 } 171 }
172 172
173 *p='/'; 173 *p='/';
174 } 174 }
175 if (done) 175 if (done)
176 fs_logger2("mkpath", path); 176 fs_logger2("mkpath", path);
177 177
178 free(file_path); 178 free(file_path);
179 return 0; 179 return 0;
180} 180}
@@ -187,14 +187,14 @@ static void whitelist_path(ProfileEntry *entry) {
187 char *wfile = NULL; 187 char *wfile = NULL;
188 188
189 if (entry->home_dir) { 189 if (entry->home_dir) {
190 if (strncmp(path, cfg.homedir, strlen(cfg.homedir)) == 0) { 190 if (strncmp(path, cfg.homedir, strlen(cfg.homedir)) == 0) {
191 fname = path + strlen(cfg.homedir); 191 fname = path + strlen(cfg.homedir);
192 if (*fname == '\0') 192 if (*fname == '\0')
193 goto errexit; 193 goto errexit;
194 } 194 }
195 else 195 else
196 fname = path; 196 fname = path;
197 197
198 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_HOME_USER_DIR, fname) == -1) 198 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_HOME_USER_DIR, fname) == -1)
199 errExit("asprintf"); 199 errExit("asprintf");
200 } 200 }
@@ -202,7 +202,7 @@ static void whitelist_path(ProfileEntry *entry) {
202 fname = path + 4; // strlen("/tmp") 202 fname = path + 4; // strlen("/tmp")
203 if (*fname == '\0') 203 if (*fname == '\0')
204 goto errexit; 204 goto errexit;
205 205
206 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_TMP_DIR, fname) == -1) 206 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_TMP_DIR, fname) == -1)
207 errExit("asprintf"); 207 errExit("asprintf");
208 } 208 }
@@ -210,7 +210,7 @@ static void whitelist_path(ProfileEntry *entry) {
210 fname = path + 6; // strlen("/media") 210 fname = path + 6; // strlen("/media")
211 if (*fname == '\0') 211 if (*fname == '\0')
212 goto errexit; 212 goto errexit;
213 213
214 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_MEDIA_DIR, fname) == -1) 214 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_MEDIA_DIR, fname) == -1)
215 errExit("asprintf"); 215 errExit("asprintf");
216 } 216 }
@@ -226,7 +226,7 @@ static void whitelist_path(ProfileEntry *entry) {
226 fname = path + 4; // strlen("/var") 226 fname = path + 4; // strlen("/var")
227 if (*fname == '\0') 227 if (*fname == '\0')
228 goto errexit; 228 goto errexit;
229 229
230 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_VAR_DIR, fname) == -1) 230 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_VAR_DIR, fname) == -1)
231 errExit("asprintf"); 231 errExit("asprintf");
232 } 232 }
@@ -234,7 +234,7 @@ static void whitelist_path(ProfileEntry *entry) {
234 fname = path + 4; // strlen("/dev") 234 fname = path + 4; // strlen("/dev")
235 if (*fname == '\0') 235 if (*fname == '\0')
236 goto errexit; 236 goto errexit;
237 237
238 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_DEV_DIR, fname) == -1) 238 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_DEV_DIR, fname) == -1)
239 errExit("asprintf"); 239 errExit("asprintf");
240 } 240 }
@@ -242,7 +242,7 @@ static void whitelist_path(ProfileEntry *entry) {
242 fname = path + 4; // strlen("/opt") 242 fname = path + 4; // strlen("/opt")
243 if (*fname == '\0') 243 if (*fname == '\0')
244 goto errexit; 244 goto errexit;
245 245
246 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_OPT_DIR, fname) == -1) 246 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_OPT_DIR, fname) == -1)
247 errExit("asprintf"); 247 errExit("asprintf");
248 } 248 }
@@ -263,18 +263,18 @@ static void whitelist_path(ProfileEntry *entry) {
263 else { 263 else {
264 return; 264 return;
265 } 265 }
266 266
267 // create the path if necessary 267 // create the path if necessary
268 mkpath(path, s.st_mode); 268 mkpath(path, s.st_mode);
269 fs_logger2("whitelist", path); 269 fs_logger2("whitelist", path);
270 270
271 // process directory 271 // process directory
272 if (S_ISDIR(s.st_mode)) { 272 if (S_ISDIR(s.st_mode)) {
273 // create directory 273 // create directory
274 int rv = mkdir(path, 0755); 274 int rv = mkdir(path, 0755);
275 (void) rv; 275 (void) rv;
276 } 276 }
277 277
278 // process regular file 278 // process regular file
279 else { 279 else {
280 if (access(path, R_OK)) { 280 if (access(path, R_OK)) {
@@ -291,7 +291,7 @@ static void whitelist_path(ProfileEntry *entry) {
291 else 291 else
292 return; // the file is already present 292 return; // the file is already present
293 } 293 }
294 294
295 // mount 295 // mount
296 if (mount(wfile, path, NULL, MS_BIND|MS_REC, NULL) < 0) 296 if (mount(wfile, path, NULL, MS_BIND|MS_REC, NULL) < 0)
297 errExit("mount bind"); 297 errExit("mount bind");
@@ -328,11 +328,11 @@ void fs_whitelist(void) {
328 char **nowhitelist = calloc(nowhitelist_m, sizeof(*nowhitelist)); 328 char **nowhitelist = calloc(nowhitelist_m, sizeof(*nowhitelist));
329 if (nowhitelist == NULL) 329 if (nowhitelist == NULL)
330 errExit("failed allocating memory for nowhitelist entries"); 330 errExit("failed allocating memory for nowhitelist entries");
331 331
332 // verify whitelist files, extract symbolic links, etc. 332 // verify whitelist files, extract symbolic links, etc.
333 while (entry) { 333 while (entry) {
334 int nowhitelist_flag = 0; 334 int nowhitelist_flag = 0;
335 335
336 // handle only whitelist and nowhitelist commands 336 // handle only whitelist and nowhitelist commands
337 if (strncmp(entry->data, "whitelist ", 10) == 0) 337 if (strncmp(entry->data, "whitelist ", 10) == 0)
338 nowhitelist_flag = 0; 338 nowhitelist_flag = 0;
@@ -412,16 +412,16 @@ void fs_whitelist(void) {
412 else if (strncmp(new_name, "/srv/", 5) == 0) 412 else if (strncmp(new_name, "/srv/", 5) == 0)
413 opt_dir = 1; 413 opt_dir = 1;
414 } 414 }
415 415
416 *entry->data = '\0'; 416 *entry->data = '\0';
417 continue; 417 continue;
418 } 418 }
419 419
420 if (nowhitelist_flag) { 420 if (nowhitelist_flag) {
421 // store the path in nowhitelist array 421 // store the path in nowhitelist array
422 if (arg_debug || arg_debug_whitelists) 422 if (arg_debug || arg_debug_whitelists)
423 printf("Storing nowhitelist %s\n", fname); 423 printf("Storing nowhitelist %s\n", fname);
424 424
425 if (nowhitelist_c >= nowhitelist_m) { 425 if (nowhitelist_c >= nowhitelist_m) {
426 nowhitelist_m *= 2; 426 nowhitelist_m *= 2;
427 nowhitelist = realloc(nowhitelist, sizeof(*nowhitelist) * nowhitelist_m); 427 nowhitelist = realloc(nowhitelist, sizeof(*nowhitelist) * nowhitelist_m);
@@ -432,8 +432,8 @@ void fs_whitelist(void) {
432 *entry->data = 0; 432 *entry->data = 0;
433 continue; 433 continue;
434 } 434 }
435 435
436 436
437 // check for supported directories 437 // check for supported directories
438 if (strncmp(new_name, cfg.homedir, strlen(cfg.homedir)) == 0) { 438 if (strncmp(new_name, cfg.homedir, strlen(cfg.homedir)) == 0) {
439 // whitelisting home directory is disabled if --private option is present 439 // whitelisting home directory is disabled if --private option is present
@@ -544,7 +544,7 @@ void fs_whitelist(void) {
544 free(fname); 544 free(fname);
545 continue; 545 continue;
546 } 546 }
547 } 547 }
548 548
549 // mark symbolic links 549 // mark symbolic links
550 if (is_link(new_name)) 550 if (is_link(new_name))
@@ -566,29 +566,29 @@ void fs_whitelist(void) {
566 free(fname); 566 free(fname);
567 entry = entry->next; 567 entry = entry->next;
568 } 568 }
569 569
570 // release nowhitelist memory 570 // release nowhitelist memory
571 assert(nowhitelist); 571 assert(nowhitelist);
572 free(nowhitelist); 572 free(nowhitelist);
573 573
574 // /home/user 574 // /home/user
575 if (home_dir) { 575 if (home_dir) {
576 // keep a copy of real home dir in RUN_WHITELIST_HOME_USER_DIR 576 // keep a copy of real home dir in RUN_WHITELIST_HOME_USER_DIR
577 mkdir_attr(RUN_WHITELIST_HOME_USER_DIR, 0755, getuid(), getgid()); 577 mkdir_attr(RUN_WHITELIST_HOME_USER_DIR, 0755, getuid(), getgid());
578 if (mount(cfg.homedir, RUN_WHITELIST_HOME_USER_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) 578 if (mount(cfg.homedir, RUN_WHITELIST_HOME_USER_DIR, NULL, MS_BIND|MS_REC, NULL) < 0)
579 errExit("mount bind"); 579 errExit("mount bind");
580 580
581 // mount a tmpfs and initialize /home/user 581 // mount a tmpfs and initialize /home/user
582 fs_private(); 582 fs_private();
583 } 583 }
584 584
585 // /tmp mountpoint 585 // /tmp mountpoint
586 if (tmp_dir) { 586 if (tmp_dir) {
587 // keep a copy of real /tmp directory in 587 // keep a copy of real /tmp directory in
588 mkdir_attr(RUN_WHITELIST_TMP_DIR, 1777, 0, 0); 588 mkdir_attr(RUN_WHITELIST_TMP_DIR, 1777, 0, 0);
589 if (mount("/tmp", RUN_WHITELIST_TMP_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) 589 if (mount("/tmp", RUN_WHITELIST_TMP_DIR, NULL, MS_BIND|MS_REC, NULL) < 0)
590 errExit("mount bind"); 590 errExit("mount bind");
591 591
592 // mount tmpfs on /tmp 592 // mount tmpfs on /tmp
593 if (arg_debug || arg_debug_whitelists) 593 if (arg_debug || arg_debug_whitelists)
594 printf("Mounting tmpfs on /tmp directory\n"); 594 printf("Mounting tmpfs on /tmp directory\n");
@@ -596,7 +596,7 @@ void fs_whitelist(void) {
596 errExit("mounting tmpfs on /tmp"); 596 errExit("mounting tmpfs on /tmp");
597 fs_logger("tmpfs /tmp"); 597 fs_logger("tmpfs /tmp");
598 } 598 }
599 599
600 // /media mountpoint 600 // /media mountpoint
601 if (media_dir) { 601 if (media_dir) {
602 // some distros don't have a /media directory 602 // some distros don't have a /media directory
@@ -606,7 +606,7 @@ void fs_whitelist(void) {
606 mkdir_attr(RUN_WHITELIST_MEDIA_DIR, 0755, 0, 0); 606 mkdir_attr(RUN_WHITELIST_MEDIA_DIR, 0755, 0, 0);
607 if (mount("/media", RUN_WHITELIST_MEDIA_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) 607 if (mount("/media", RUN_WHITELIST_MEDIA_DIR, NULL, MS_BIND|MS_REC, NULL) < 0)
608 errExit("mount bind"); 608 errExit("mount bind");
609 609
610 // mount tmpfs on /media 610 // mount tmpfs on /media
611 if (arg_debug || arg_debug_whitelists) 611 if (arg_debug || arg_debug_whitelists)
612 printf("Mounting tmpfs on /media directory\n"); 612 printf("Mounting tmpfs on /media directory\n");
@@ -646,7 +646,7 @@ void fs_whitelist(void) {
646 mkdir_attr(RUN_WHITELIST_VAR_DIR, 0755, 0, 0); 646 mkdir_attr(RUN_WHITELIST_VAR_DIR, 0755, 0, 0);
647 if (mount("/var", RUN_WHITELIST_VAR_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) 647 if (mount("/var", RUN_WHITELIST_VAR_DIR, NULL, MS_BIND|MS_REC, NULL) < 0)
648 errExit("mount bind"); 648 errExit("mount bind");
649 649
650 // mount tmpfs on /var 650 // mount tmpfs on /var
651 if (arg_debug || arg_debug_whitelists) 651 if (arg_debug || arg_debug_whitelists)
652 printf("Mounting tmpfs on /var directory\n"); 652 printf("Mounting tmpfs on /var directory\n");
@@ -661,7 +661,7 @@ void fs_whitelist(void) {
661 mkdir_attr(RUN_WHITELIST_DEV_DIR, 0755, 0, 0); 661 mkdir_attr(RUN_WHITELIST_DEV_DIR, 0755, 0, 0);
662 if (mount("/dev", RUN_WHITELIST_DEV_DIR, NULL, MS_BIND|MS_REC, "mode=755,gid=0") < 0) 662 if (mount("/dev", RUN_WHITELIST_DEV_DIR, NULL, MS_BIND|MS_REC, "mode=755,gid=0") < 0)
663 errExit("mount bind"); 663 errExit("mount bind");
664 664
665 // mount tmpfs on /dev 665 // mount tmpfs on /dev
666 if (arg_debug || arg_debug_whitelists) 666 if (arg_debug || arg_debug_whitelists)
667 printf("Mounting tmpfs on /dev directory\n"); 667 printf("Mounting tmpfs on /dev directory\n");
@@ -676,7 +676,7 @@ void fs_whitelist(void) {
676 mkdir_attr(RUN_WHITELIST_OPT_DIR, 0755, 0, 0); 676 mkdir_attr(RUN_WHITELIST_OPT_DIR, 0755, 0, 0);
677 if (mount("/opt", RUN_WHITELIST_OPT_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) 677 if (mount("/opt", RUN_WHITELIST_OPT_DIR, NULL, MS_BIND|MS_REC, NULL) < 0)
678 errExit("mount bind"); 678 errExit("mount bind");
679 679
680 // mount tmpfs on /opt 680 // mount tmpfs on /opt
681 if (arg_debug || arg_debug_whitelists) 681 if (arg_debug || arg_debug_whitelists)
682 printf("Mounting tmpfs on /opt directory\n"); 682 printf("Mounting tmpfs on /opt directory\n");
@@ -707,7 +707,7 @@ void fs_whitelist(void) {
707 } 707 }
708 708
709 709
710 710
711 // go through profile rules again, and interpret whitelist commands 711 // go through profile rules again, and interpret whitelist commands
712 entry = cfg.profile; 712 entry = cfg.profile;
713 while (entry) { 713 while (entry) {
@@ -719,7 +719,7 @@ void fs_whitelist(void) {
719 719
720//printf("here %d#%s#\n", __LINE__, entry->data); 720//printf("here %d#%s#\n", __LINE__, entry->data);
721 // whitelist the real file 721 // whitelist the real file
722 if (strcmp(entry->data, "whitelist /run") == 0 && 722 if (strcmp(entry->data, "whitelist /run") == 0 &&
723 (strcmp(entry->link, "/var/run") == 0 || strcmp(entry->link, "/var/lock") == 0)) { 723 (strcmp(entry->link, "/var/run") == 0 || strcmp(entry->link, "/var/lock") == 0)) {
724 int rv = symlink(entry->data + 10, entry->link); 724 int rv = symlink(entry->data + 10, entry->link);
725 if (rv) 725 if (rv)
@@ -729,7 +729,7 @@ void fs_whitelist(void) {
729 } 729 }
730 else { 730 else {
731 whitelist_path(entry); 731 whitelist_path(entry);
732 732
733 // create the link if any 733 // create the link if any
734 if (entry->link) { 734 if (entry->link) {
735 // if the link is already there, do not bother 735 // if the link is already there, do not bother
@@ -737,7 +737,7 @@ void fs_whitelist(void) {
737 if (stat(entry->link, &s) != 0) { 737 if (stat(entry->link, &s) != 0) {
738 // create the path if necessary 738 // create the path if necessary
739 mkpath(entry->link, s.st_mode); 739 mkpath(entry->link, s.st_mode);
740 740
741 int rv = symlink(entry->data + 10, entry->link); 741 int rv = symlink(entry->data + 10, entry->link);
742 if (rv) 742 if (rv)
743 fprintf(stderr, "Warning cannot create symbolic link %s\n", entry->link); 743 fprintf(stderr, "Warning cannot create symbolic link %s\n", entry->link);
@@ -756,7 +756,7 @@ void fs_whitelist(void) {
756 errExit("mount tmpfs"); 756 errExit("mount tmpfs");
757 fs_logger2("tmpfs", RUN_WHITELIST_HOME_USER_DIR); 757 fs_logger2("tmpfs", RUN_WHITELIST_HOME_USER_DIR);
758 } 758 }
759 759
760 // mask the real /tmp directory, currently mounted on RUN_WHITELIST_TMP_DIR 760 // mask the real /tmp directory, currently mounted on RUN_WHITELIST_TMP_DIR
761 if (tmp_dir) { 761 if (tmp_dir) {
762 if (mount("tmpfs", RUN_WHITELIST_TMP_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) 762 if (mount("tmpfs", RUN_WHITELIST_TMP_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
@@ -808,7 +808,7 @@ void fs_whitelist(void) {
808 808
809 if (new_name) 809 if (new_name)
810 free(new_name); 810 free(new_name);
811 811
812 return; 812 return;
813 813
814errexit: 814errexit:
diff --git a/src/firejail/git.c b/src/firejail/git.c
index c4dd54a1b..ae28f7ec1 100644
--- a/src/firejail/git.c
+++ b/src/firejail/git.c
@@ -19,7 +19,7 @@
19 */ 19 */
20 20
21#ifdef HAVE_GIT_INSTALL 21#ifdef HAVE_GIT_INSTALL
22 22
23#include "firejail.h" 23#include "firejail.h"
24#include <sys/utsname.h> 24#include <sys/utsname.h>
25#include <sched.h> 25#include <sched.h>
@@ -46,7 +46,7 @@ static void sbox_ns(void) {
46 errExit("setgid/getgid"); 46 errExit("setgid/getgid");
47 if (setuid(getuid()) < 0) 47 if (setuid(getuid()) < 0)
48 errExit("setuid/getuid"); 48 errExit("setuid/getuid");
49 assert(getenv("LD_PRELOAD") == NULL); 49 assert(getenv("LD_PRELOAD") == NULL);
50 50
51 printf("Running as "); fflush(0); 51 printf("Running as "); fflush(0);
52 int rv = system("whoami"); 52 int rv = system("whoami");
@@ -55,16 +55,16 @@ static void sbox_ns(void) {
55 rv = system("ls -l /tmp"); 55 rv = system("ls -l /tmp");
56 (void) rv; 56 (void) rv;
57} 57}
58 58
59 59
60void git_install(void) { 60void git_install(void) {
61 // redirect to "/usr/bin/firejail --noprofile --private-tmp /usr/lib/firejail/fgit-install.sh" 61 // redirect to "/usr/bin/firejail --noprofile --private-tmp /usr/lib/firejail/fgit-install.sh"
62 EUID_ASSERT(); 62 EUID_ASSERT();
63 EUID_ROOT(); 63 EUID_ROOT();
64 64
65 // install a mount namespace with a tmpfs on top of /tmp 65 // install a mount namespace with a tmpfs on top of /tmp
66 sbox_ns(); 66 sbox_ns();
67 67
68 // run command 68 // run command
69 const char *cmd = LIBDIR "/firejail/fgit-install.sh"; 69 const char *cmd = LIBDIR "/firejail/fgit-install.sh";
70 int rv = system(cmd); 70 int rv = system(cmd);
@@ -76,15 +76,15 @@ void git_uninstall(void) {
76 // redirect to "/usr/bin/firejail --noprofile --private-tmp /usr/lib/firejail/fgit-install.sh" 76 // redirect to "/usr/bin/firejail --noprofile --private-tmp /usr/lib/firejail/fgit-install.sh"
77 EUID_ASSERT(); 77 EUID_ASSERT();
78 EUID_ROOT(); 78 EUID_ROOT();
79 79
80 // install a mount namespace with a tmpfs on top of /tmp 80 // install a mount namespace with a tmpfs on top of /tmp
81 sbox_ns(); 81 sbox_ns();
82 82
83 // run command 83 // run command
84 const char *cmd = LIBDIR "/firejail/fgit-uninstall.sh"; 84 const char *cmd = LIBDIR "/firejail/fgit-uninstall.sh";
85 int rv = system(cmd); 85 int rv = system(cmd);
86 (void) rv; 86 (void) rv;
87 exit(0); 87 exit(0);
88} 88}
89 89
90#endif // HAVE_GIT_INSTALL 90#endif // HAVE_GIT_INSTALL
diff --git a/src/firejail/join.c b/src/firejail/join.c
index 2f6f070e0..b5b45a3bf 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -48,7 +48,7 @@ static void extract_command(int argc, char **argv, int index) {
48 if (index >= argc) 48 if (index >= argc)
49 return; 49 return;
50 } 50 }
51 51
52 // first argv needs to be a valid command 52 // first argv needs to be a valid command
53 if (arg_doubledash == 0 && *argv[index] == '-') { 53 if (arg_doubledash == 0 && *argv[index] == '-') {
54 fprintf(stderr, "Error: invalid option %s after --join\n", argv[index]); 54 fprintf(stderr, "Error: invalid option %s after --join\n", argv[index]);
@@ -66,7 +66,7 @@ static void extract_nogroups(pid_t pid) {
66 char *fname; 66 char *fname;
67 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_GROUPS_CFG) == -1) 67 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_GROUPS_CFG) == -1)
68 errExit("asprintf"); 68 errExit("asprintf");
69 69
70 struct stat s; 70 struct stat s;
71 if (stat(fname, &s) == -1) 71 if (stat(fname, &s) == -1)
72 return; 72 return;
@@ -79,11 +79,11 @@ static void extract_cpu(pid_t pid) {
79 char *fname; 79 char *fname;
80 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_CPU_CFG) == -1) 80 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_CPU_CFG) == -1)
81 errExit("asprintf"); 81 errExit("asprintf");
82 82
83 struct stat s; 83 struct stat s;
84 if (stat(fname, &s) == -1) 84 if (stat(fname, &s) == -1)
85 return; 85 return;
86 86
87 // there is a CPU_CFG file, load it! 87 // there is a CPU_CFG file, load it!
88 load_cpu(fname); 88 load_cpu(fname);
89 free(fname); 89 free(fname);
@@ -93,11 +93,11 @@ static void extract_cgroup(pid_t pid) {
93 char *fname; 93 char *fname;
94 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_CGROUP_CFG) == -1) 94 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_CGROUP_CFG) == -1)
95 errExit("asprintf"); 95 errExit("asprintf");
96 96
97 struct stat s; 97 struct stat s;
98 if (stat(fname, &s) == -1) 98 if (stat(fname, &s) == -1)
99 return; 99 return;
100 100
101 // there is a cgroup file CGROUP_CFG, load it! 101 // there is a cgroup file CGROUP_CFG, load it!
102 load_cgroup(fname); 102 load_cgroup(fname);
103 free(fname); 103 free(fname);
@@ -127,7 +127,7 @@ static void extract_caps_seccomp(pid_t pid) {
127 apply_seccomp = 1; 127 apply_seccomp = 1;
128 break; 128 break;
129 } 129 }
130 else if (strncmp(buf, "CapBnd:", 7) == 0) { 130 else if (strncmp(buf, "CapBnd:", 7) == 0) {
131 char *ptr = buf + 7; 131 char *ptr = buf + 7;
132 unsigned long long val; 132 unsigned long long val;
133 sscanf(ptr, "%llx", &val); 133 sscanf(ptr, "%llx", &val);
@@ -149,7 +149,7 @@ static void extract_user_namespace(pid_t pid) {
149 stat("/proc/self/gid_map", &s3) == 0); 149 stat("/proc/self/gid_map", &s3) == 0);
150 else 150 else
151 return; 151 return;
152 152
153 // read uid map 153 // read uid map
154 char *uidmap; 154 char *uidmap;
155 if (asprintf(&uidmap, "/proc/%u/uid_map", pid) == -1) 155 if (asprintf(&uidmap, "/proc/%u/uid_map", pid) == -1)
@@ -215,11 +215,11 @@ void join(pid_t pid, int argc, char **argv, int index) {
215 extract_nogroups(pid); 215 extract_nogroups(pid);
216 extract_user_namespace(pid); 216 extract_user_namespace(pid);
217 } 217 }
218 218
219 // set cgroup 219 // set cgroup
220 if (cfg.cgroup) // not available for uid 0 220 if (cfg.cgroup) // not available for uid 0
221 set_cgroup(cfg.cgroup); 221 set_cgroup(cfg.cgroup);
222 222
223 // join namespaces 223 // join namespaces
224 if (arg_join_network) { 224 if (arg_join_network) {
225 if (join_namespace(pid, "net")) 225 if (join_namespace(pid, "net"))
@@ -246,14 +246,14 @@ void join(pid_t pid, int argc, char **argv, int index) {
246 char *rootdir; 246 char *rootdir;
247 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1) 247 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
248 errExit("asprintf"); 248 errExit("asprintf");
249 249
250 int rv; 250 int rv;
251 if (!arg_join_network) { 251 if (!arg_join_network) {
252 rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option 252 rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
253 if (rv == 0) 253 if (rv == 0)
254 printf("changing root to %s\n", rootdir); 254 printf("changing root to %s\n", rootdir);
255 } 255 }
256 256
257 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died 257 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
258 if (chdir("/") < 0) 258 if (chdir("/") < 0)
259 errExit("chdir"); 259 errExit("chdir");
@@ -265,11 +265,11 @@ void join(pid_t pid, int argc, char **argv, int index) {
265 errExit("chdir"); 265 errExit("chdir");
266 } 266 }
267 } 267 }
268 268
269 // set cpu affinity 269 // set cpu affinity
270 if (cfg.cpus) // not available for uid 0 270 if (cfg.cpus) // not available for uid 0
271 set_cpu_affinity(); 271 set_cpu_affinity();
272 272
273 // set caps filter 273 // set caps filter
274 if (apply_caps == 1) // not available for uid 0 274 if (apply_caps == 1) // not available for uid 0
275 caps_set(caps); 275 caps_set(caps);
@@ -278,9 +278,9 @@ void join(pid_t pid, int argc, char **argv, int index) {
278 if (getuid() != 0) 278 if (getuid() != 0)
279 protocol_filter_load(RUN_PROTOCOL_CFG); 279 protocol_filter_load(RUN_PROTOCOL_CFG);
280 if (cfg.protocol) { // not available for uid 0 280 if (cfg.protocol) { // not available for uid 0
281 seccomp_load(RUN_SECCOMP_PROTOCOL); // install filter 281 seccomp_load(RUN_SECCOMP_PROTOCOL); // install filter
282 } 282 }
283 283
284 // set seccomp filter 284 // set seccomp filter
285 if (apply_seccomp == 1) // not available for uid 0 285 if (apply_seccomp == 1) // not available for uid 0
286 seccomp_load(RUN_SECCOMP_CFG); 286 seccomp_load(RUN_SECCOMP_CFG);
@@ -298,7 +298,7 @@ void join(pid_t pid, int argc, char **argv, int index) {
298 if (apply_caps == 1) // not available for uid 0 298 if (apply_caps == 1) // not available for uid 0
299 caps_set(caps); 299 caps_set(caps);
300 } 300 }
301 else 301 else
302 drop_privs(arg_nogroups); // nogroups not available for uid 0 302 drop_privs(arg_nogroups); // nogroups not available for uid 0
303 303
304 304
@@ -349,6 +349,3 @@ void join(pid_t pid, int argc, char **argv, int index) {
349 flush_stdin(); 349 flush_stdin();
350 exit(0); 350 exit(0);
351} 351}
352
353
354
diff --git a/src/firejail/ls.c b/src/firejail/ls.c
index 7b51ee697..7b994b835 100644
--- a/src/firejail/ls.c
+++ b/src/firejail/ls.c
@@ -17,7 +17,7 @@
17 * with this program; if not, write to the Free Software Foundation, Inc., 17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20 20
21#include "firejail.h" 21#include "firejail.h"
22#include <sys/types.h> 22#include <sys/types.h>
23#include <sys/stat.h> 23#include <sys/stat.h>
@@ -36,7 +36,7 @@ static char *c_uid_name = NULL;
36 36
37static void print_file_or_dir(const char *path, const char *fname, int separator) { 37static void print_file_or_dir(const char *path, const char *fname, int separator) {
38 assert(fname); 38 assert(fname);
39 39
40 char *name; 40 char *name;
41 if (separator) { 41 if (separator) {
42 if (asprintf(&name, "%s/%s", path, fname) == -1) 42 if (asprintf(&name, "%s/%s", path, fname) == -1)
@@ -46,7 +46,7 @@ static void print_file_or_dir(const char *path, const char *fname, int separator
46 if (asprintf(&name, "%s%s", path, fname) == -1) 46 if (asprintf(&name, "%s%s", path, fname) == -1)
47 errExit("asprintf"); 47 errExit("asprintf");
48 } 48 }
49 49
50 struct stat s; 50 struct stat s;
51 if (stat(name, &s) == -1) { 51 if (stat(name, &s) == -1) {
52 if (lstat(name, &s) == -1) { 52 if (lstat(name, &s) == -1) {
@@ -78,7 +78,7 @@ static void print_file_or_dir(const char *path, const char *fname, int separator
78 printf( (s.st_mode & S_IWOTH) ? "w" : "-"); 78 printf( (s.st_mode & S_IWOTH) ? "w" : "-");
79 printf( (s.st_mode & S_IXOTH) ? "x" : "-"); 79 printf( (s.st_mode & S_IXOTH) ? "x" : "-");
80 printf(" "); 80 printf(" ");
81 81
82 // user name 82 // user name
83 char *username; 83 char *username;
84 int allocated = 0; 84 int allocated = 0;
@@ -100,7 +100,7 @@ static void print_file_or_dir(const char *path, const char *fname, int separator
100 if (!username) 100 if (!username)
101 errExit("asprintf"); 101 errExit("asprintf");
102 } 102 }
103 103
104 if (c_uid == 0) { 104 if (c_uid == 0) {
105 c_uid = s.st_uid; 105 c_uid = s.st_uid;
106 c_uid_name = strdup(username); 106 c_uid_name = strdup(username);
@@ -108,7 +108,7 @@ static void print_file_or_dir(const char *path, const char *fname, int separator
108 errExit("asprintf"); 108 errExit("asprintf");
109 } 109 }
110 } 110 }
111 111
112 // print user name, 8 chars maximum 112 // print user name, 8 chars maximum
113 int len = strlen(username); 113 int len = strlen(username);
114 if (len > 8) { 114 if (len > 8) {
@@ -121,7 +121,7 @@ static void print_file_or_dir(const char *path, const char *fname, int separator
121 printf(" "); 121 printf(" ");
122 if (allocated) 122 if (allocated)
123 free(username); 123 free(username);
124 124
125 125
126 // group name 126 // group name
127 char *groupname; 127 char *groupname;
@@ -141,7 +141,7 @@ static void print_file_or_dir(const char *path, const char *fname, int separator
141 errExit("asprintf"); 141 errExit("asprintf");
142 } 142 }
143 } 143 }
144 144
145 // print grup name, 8 chars maximum 145 // print grup name, 8 chars maximum
146 len = strlen(groupname); 146 len = strlen(groupname);
147 if (len > 8) { 147 if (len > 8) {
@@ -159,7 +159,7 @@ static void print_file_or_dir(const char *path, const char *fname, int separator
159 errExit("asprintf"); 159 errExit("asprintf");
160 printf("%11.10s %s\n", sz, fname); 160 printf("%11.10s %s\n", sz, fname);
161 free(sz); 161 free(sz);
162 162
163} 163}
164 164
165static void print_directory(const char *path) { 165static void print_directory(const char *path) {
@@ -168,7 +168,7 @@ static void print_directory(const char *path) {
168 if (stat(path, &s) == -1) 168 if (stat(path, &s) == -1)
169 return; 169 return;
170 assert(S_ISDIR(s.st_mode)); 170 assert(S_ISDIR(s.st_mode));
171 171
172 struct dirent **namelist; 172 struct dirent **namelist;
173 int i; 173 int i;
174 int n; 174 int n;
@@ -200,7 +200,7 @@ char *expand_path(const char *path) {
200 // assume the file is in current working directory 200 // assume the file is in current working directory
201 if (asprintf(&fname, "%s/%s", cfg.cwd, path) == -1) 201 if (asprintf(&fname, "%s/%s", cfg.cwd, path) == -1)
202 errExit("asprintf"); 202 errExit("asprintf");
203 } 203 }
204 return fname; 204 return fname;
205} 205}
206 206
@@ -241,7 +241,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
241 printf("file1 %s\n", fname1); 241 printf("file1 %s\n", fname1);
242 printf("file2 %s\n", fname2); 242 printf("file2 %s\n", fname2);
243 } 243 }
244 244
245 // sandbox root directory 245 // sandbox root directory
246 char *rootdir; 246 char *rootdir;
247 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1) 247 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
@@ -254,7 +254,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
254 errExit("chroot"); 254 errExit("chroot");
255 if (chdir("/") < 0) 255 if (chdir("/") < 0)
256 errExit("chdir"); 256 errExit("chdir");
257 257
258 // drop privileges 258 // drop privileges
259 drop_privs(0); 259 drop_privs(0);
260 260
@@ -271,8 +271,8 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
271 } 271 }
272 if (arg_debug) 272 if (arg_debug)
273 printf("realpath %s\n", rp); 273 printf("realpath %s\n", rp);
274 274
275 275
276 // list directory contents 276 // list directory contents
277 struct stat s; 277 struct stat s;
278 if (stat(rp, &s) == -1) { 278 if (stat(rp, &s) == -1) {
@@ -283,7 +283,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
283 char *dir; 283 char *dir;
284 if (asprintf(&dir, "%s/", rp) == -1) 284 if (asprintf(&dir, "%s/", rp) == -1)
285 errExit("asprintf"); 285 errExit("asprintf");
286 286
287 print_directory(dir); 287 print_directory(dir);
288 free(dir); 288 free(dir);
289 } 289 }
@@ -299,7 +299,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
299 } 299 }
300 free(rp); 300 free(rp);
301 } 301 }
302 302
303 // get file from sandbox and store it in the current directory 303 // get file from sandbox and store it in the current directory
304 else if (op == SANDBOX_FS_GET) { 304 else if (op == SANDBOX_FS_GET) {
305 char *src_fname =fname1; 305 char *src_fname =fname1;
@@ -320,7 +320,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
320 SET_PERMS_FD(fd, getuid(), getgid(), 0600); 320 SET_PERMS_FD(fd, getuid(), getgid(), 0600);
321 close(fd); 321 close(fd);
322 } 322 }
323 323
324 // copy the source file into the temporary file - we need to chroot 324 // copy the source file into the temporary file - we need to chroot
325 pid_t child = fork(); 325 pid_t child = fork();
326 if (child < 0) 326 if (child < 0)
@@ -331,10 +331,10 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
331 errExit("chroot"); 331 errExit("chroot");
332 if (chdir("/") < 0) 332 if (chdir("/") < 0)
333 errExit("chdir"); 333 errExit("chdir");
334 334
335 // drop privileges 335 // drop privileges
336 drop_privs(0); 336 drop_privs(0);
337 337
338 // copy the file 338 // copy the file
339 if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600)) // already a regular user 339 if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600)) // already a regular user
340 _exit(1); 340 _exit(1);
@@ -352,7 +352,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
352 unlink(tmp_fname); 352 unlink(tmp_fname);
353 exit(1); 353 exit(1);
354 } 354 }
355 355
356 // copy the temporary file into the destionation file 356 // copy the temporary file into the destionation file
357 child = fork(); 357 child = fork();
358 if (child < 0) 358 if (child < 0)
@@ -360,7 +360,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
360 if (child == 0) { 360 if (child == 0) {
361 // drop privileges 361 // drop privileges
362 drop_privs(0); 362 drop_privs(0);
363 363
364 // copy the file 364 // copy the file
365 if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600)) // already a regular user 365 if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600)) // already a regular user
366 _exit(1); 366 _exit(1);
@@ -378,7 +378,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
378 unlink(tmp_fname); 378 unlink(tmp_fname);
379 exit(1); 379 exit(1);
380 } 380 }
381 381
382 // remove the temporary file 382 // remove the temporary file
383 unlink(tmp_fname); 383 unlink(tmp_fname);
384 EUID_USER(); 384 EUID_USER();
@@ -401,7 +401,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
401 } 401 }
402 SET_PERMS_FD(fd, getuid(), getgid(), 0600); 402 SET_PERMS_FD(fd, getuid(), getgid(), 0600);
403 close(fd); 403 close(fd);
404 404
405 // copy the source file into the temporary file - we need to chroot 405 // copy the source file into the temporary file - we need to chroot
406 pid_t child = fork(); 406 pid_t child = fork();
407 if (child < 0) 407 if (child < 0)
@@ -409,7 +409,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
409 if (child == 0) { 409 if (child == 0) {
410 // drop privileges 410 // drop privileges
411 drop_privs(0); 411 drop_privs(0);
412 412
413 // copy the file 413 // copy the file
414 if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600)) // already a regular user 414 if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600)) // already a regular user
415 _exit(1); 415 _exit(1);
@@ -427,7 +427,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
427 unlink(tmp_fname); 427 unlink(tmp_fname);
428 exit(1); 428 exit(1);
429 } 429 }
430 430
431 // copy the temporary file into the destionation file 431 // copy the temporary file into the destionation file
432 child = fork(); 432 child = fork();
433 if (child < 0) 433 if (child < 0)
@@ -438,10 +438,10 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
438 errExit("chroot"); 438 errExit("chroot");
439 if (chdir("/") < 0) 439 if (chdir("/") < 0)
440 errExit("chdir"); 440 errExit("chdir");
441 441
442 // drop privileges 442 // drop privileges
443 drop_privs(0); 443 drop_privs(0);
444 444
445 // copy the file 445 // copy the file
446 if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600)) // already a regular user 446 if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600)) // already a regular user
447 _exit(1); 447 _exit(1);
@@ -459,7 +459,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
459 unlink(tmp_fname); 459 unlink(tmp_fname);
460 exit(1); 460 exit(1);
461 } 461 }
462 462
463 // remove the temporary file 463 // remove the temporary file
464 unlink(tmp_fname); 464 unlink(tmp_fname);
465 EUID_USER(); 465 EUID_USER();
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c
index ea1d45dd7..14b3b54a6 100644
--- a/src/firejail/netfilter.c
+++ b/src/firejail/netfilter.c
@@ -46,7 +46,7 @@ static char *client_filter =
46void check_netfilter_file(const char *fname) { 46void check_netfilter_file(const char *fname) {
47 EUID_ASSERT(); 47 EUID_ASSERT();
48 invalid_filename(fname); 48 invalid_filename(fname);
49 49
50 if (is_dir(fname) || is_link(fname) || strstr(fname, "..") || access(fname, R_OK )) { 50 if (is_dir(fname) || is_link(fname) || strstr(fname, "..") || access(fname, R_OK )) {
51 fprintf(stderr, "Error: invalid network filter file %s\n", fname); 51 fprintf(stderr, "Error: invalid network filter file %s\n", fname);
52 exit(1); 52 exit(1);
@@ -95,14 +95,14 @@ void netfilter(const char *fname) {
95 // push filter 95 // push filter
96 if (arg_debug) 96 if (arg_debug)
97 printf("Installing network filter:\n%s\n", filter); 97 printf("Installing network filter:\n%s\n", filter);
98 98
99 // first run of iptables on this platform installs a number of kernel modules such as ip_tables, x_tables, iptable_filter 99 // first run of iptables on this platform installs a number of kernel modules such as ip_tables, x_tables, iptable_filter
100 // we run this command with caps and seccomp disabled in order to allow the loading of these modules 100 // we run this command with caps and seccomp disabled in order to allow the loading of these modules
101 sbox_run(SBOX_ROOT /* | SBOX_CAPS_NETWORK | SBOX_SECCOMP*/ | SBOX_STDIN_FROM_FILE, 1, iptables_restore); 101 sbox_run(SBOX_ROOT /* | SBOX_CAPS_NETWORK | SBOX_SECCOMP*/ | SBOX_STDIN_FROM_FILE, 1, iptables_restore);
102 unlink(SBOX_STDIN_FILE); 102 unlink(SBOX_STDIN_FILE);
103 103
104 // debug 104 // debug
105 if (arg_debug) 105 if (arg_debug)
106 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-vL"); 106 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-vL");
107 107
108 if (allocated) 108 if (allocated)
@@ -113,7 +113,7 @@ void netfilter(const char *fname) {
113void netfilter6(const char *fname) { 113void netfilter6(const char *fname) {
114 if (fname == NULL) 114 if (fname == NULL)
115 return; 115 return;
116 116
117 // find iptables command 117 // find iptables command
118 char *ip6tables = NULL; 118 char *ip6tables = NULL;
119 char *ip6tables_restore = NULL; 119 char *ip6tables_restore = NULL;
@@ -149,7 +149,7 @@ void netfilter6(const char *fname) {
149 // we run this command with caps and seccomp disabled in order to allow the loading of these modules 149 // we run this command with caps and seccomp disabled in order to allow the loading of these modules
150 sbox_run(SBOX_ROOT | /* SBOX_CAPS_NETWORK | SBOX_SECCOMP | */ SBOX_STDIN_FROM_FILE, 1, ip6tables_restore); 150 sbox_run(SBOX_ROOT | /* SBOX_CAPS_NETWORK | SBOX_SECCOMP | */ SBOX_STDIN_FROM_FILE, 1, ip6tables_restore);
151 unlink(SBOX_STDIN_FILE); 151 unlink(SBOX_STDIN_FILE);
152 152
153 // debug 153 // debug
154 if (arg_debug) 154 if (arg_debug)
155 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, ip6tables, "-vL"); 155 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, ip6tables, "-vL");
diff --git a/src/firejail/network.c b/src/firejail/network.c
index 44fc4f68f..f7ddef917 100644
--- a/src/firejail/network.c
+++ b/src/firejail/network.c
@@ -50,8 +50,8 @@ int net_get_mtu(const char *ifname) {
50 if (arg_debug) 50 if (arg_debug)
51 printf("MTU of %s is %d.\n", ifname, ifr.ifr_mtu); 51 printf("MTU of %s is %d.\n", ifname, ifr.ifr_mtu);
52 close(s); 52 close(s);
53 53
54 54
55 return mtu; 55 return mtu;
56} 56}
57 57
@@ -84,10 +84,10 @@ int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t ma
84 assert(bridge); 84 assert(bridge);
85 assert(ip); 85 assert(ip);
86 assert(mask); 86 assert(mask);
87 87
88 if (arg_debug) 88 if (arg_debug)
89 printf("get interface %s configuration\n", bridge); 89 printf("get interface %s configuration\n", bridge);
90 90
91 int rv = -1; 91 int rv = -1;
92 struct ifaddrs *ifaddr, *ifa; 92 struct ifaddrs *ifaddr, *ifa;
93 93
@@ -110,7 +110,7 @@ int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t ma
110 net_get_mac(ifa->ifa_name, mac); 110 net_get_mac(ifa->ifa_name, mac);
111 *mtu = net_get_mtu(bridge); 111 *mtu = net_get_mtu(bridge);
112 } 112 }
113 113
114 rv = 0; 114 rv = 0;
115 break; 115 break;
116 } 116 }
@@ -126,9 +126,9 @@ void net_if_up(const char *ifname) {
126 fprintf(stderr, "Error: invalid network device name %s\n", ifname); 126 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
127 exit(1); 127 exit(1);
128 } 128 }
129 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 3, 129 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 3,
130 PATH_FNET, "ifup", ifname); 130 PATH_FNET, "ifup", ifname);
131} 131}
132 132
133 133
134// configure interface ipv6 address 134// configure interface ipv6 address
@@ -138,8 +138,8 @@ void net_if_ip6(const char *ifname, const char *addr6) {
138 fprintf(stderr, "Error: invalid IPv6 address %s\n", addr6); 138 fprintf(stderr, "Error: invalid IPv6 address %s\n", addr6);
139 exit(1); 139 exit(1);
140 } 140 }
141 141
142 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 5, 142 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 5,
143 PATH_FNET, "config", "ipv6", ifname, addr6); 143 PATH_FNET, "config", "ipv6", ifname, addr6);
144 144
145} 145}
@@ -187,19 +187,19 @@ uint32_t network_get_defaultgw(void) {
187 FILE *fp = fopen("/proc/self/net/route", "r"); 187 FILE *fp = fopen("/proc/self/net/route", "r");
188 if (!fp) 188 if (!fp)
189 errExit("fopen"); 189 errExit("fopen");
190 190
191 char buf[BUFSIZE]; 191 char buf[BUFSIZE];
192 uint32_t retval = 0; 192 uint32_t retval = 0;
193 while (fgets(buf, BUFSIZE, fp)) { 193 while (fgets(buf, BUFSIZE, fp)) {
194 if (strncmp(buf, "Iface", 5) == 0) 194 if (strncmp(buf, "Iface", 5) == 0)
195 continue; 195 continue;
196 196
197 char *ptr = buf; 197 char *ptr = buf;
198 while (*ptr != ' ' && *ptr != '\t') 198 while (*ptr != ' ' && *ptr != '\t')
199 ptr++; 199 ptr++;
200 while (*ptr == ' ' || *ptr == '\t') 200 while (*ptr == ' ' || *ptr == '\t')
201 ptr++; 201 ptr++;
202 202
203 unsigned dest; 203 unsigned dest;
204 unsigned gw; 204 unsigned gw;
205 int rv = sscanf(ptr, "%x %x", &dest, &gw); 205 int rv = sscanf(ptr, "%x %x", &dest, &gw);
@@ -219,9 +219,9 @@ int net_config_mac(const char *ifname, const unsigned char mac[6]) {
219 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) == -1) 219 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) == -1)
220 errExit("asprintf"); 220 errExit("asprintf");
221 221
222 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 5, 222 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 5,
223 PATH_FNET, "config", "mac", ifname, macstr); 223 PATH_FNET, "config", "mac", ifname, macstr);
224 224
225 free(macstr); 225 free(macstr);
226 return 0; 226 return 0;
227} 227}
@@ -237,7 +237,7 @@ int net_get_mac(const char *ifname, unsigned char mac[6]) {
237 memset(&ifr, 0, sizeof(ifr)); 237 memset(&ifr, 0, sizeof(ifr));
238 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 238 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
239 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; 239 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
240 240
241 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) 241 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1)
242 errExit("ioctl"); 242 errExit("ioctl");
243 memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); 243 memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
@@ -248,7 +248,7 @@ int net_get_mac(const char *ifname, unsigned char mac[6]) {
248 248
249void net_config_interface(const char *dev, uint32_t ip, uint32_t mask, int mtu) { 249void net_config_interface(const char *dev, uint32_t ip, uint32_t mask, int mtu) {
250 assert(dev); 250 assert(dev);
251 251
252 char *ipstr; 252 char *ipstr;
253 if (asprintf(&ipstr, "%llu", (long long unsigned) ip) == -1) 253 if (asprintf(&ipstr, "%llu", (long long unsigned) ip) == -1)
254 errExit("asprintf"); 254 errExit("asprintf");
@@ -260,12 +260,11 @@ void net_config_interface(const char *dev, uint32_t ip, uint32_t mask, int mtu)
260 char *mtustr; 260 char *mtustr;
261 if (asprintf(&mtustr, "%d", mtu) == -1) 261 if (asprintf(&mtustr, "%d", mtu) == -1)
262 errExit("asprintf"); 262 errExit("asprintf");
263 263
264 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 7, 264 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 7,
265 PATH_FNET, "config", "interface", dev, ipstr, maskstr, mtustr); 265 PATH_FNET, "config", "interface", dev, ipstr, maskstr, mtustr);
266 266
267 free(ipstr); 267 free(ipstr);
268 free(maskstr); 268 free(maskstr);
269 free(mtustr); 269 free(mtustr);
270} 270}
271
diff --git a/src/firejail/network.txt b/src/firejail/network.txt
index f6df0f485..75bdc346d 100644
--- a/src/firejail/network.txt
+++ b/src/firejail/network.txt
@@ -40,10 +40,10 @@ main() {
40 else if --ip 40 else if --ip
41 br = last bridge configured 41 br = last bridge configured
42 br->ipsandbox = ip address extracted from argv[i] 42 br->ipsandbox = ip address extracted from argv[i]
43 else if --defaultgw 43 else if --defaultgw
44 cfg.defaultgw = ip address extracted from argv[i] 44 cfg.defaultgw = ip address extracted from argv[i]
45 } 45 }
46 46
47 net_check_cfg(); // check the validity of network configuration so far 47 net_check_cfg(); // check the validity of network configuration so far
48 48
49 if (any bridge configured) { 49 if (any bridge configured) {
@@ -51,29 +51,29 @@ main() {
51 for each bridge 51 for each bridge
52 net_configure_sandbox_ip(br) 52 net_configure_sandbox_ip(br)
53 } 53 }
54 54
55 clone (new network namespace if any bridge configured or --net=none) 55 clone (new network namespace if any bridge configured or --net=none)
56 56
57 if (any bridge configured) { 57 if (any bridge configured) {
58 for each bridge 58 for each bridge
59 net_configure_veth_pair 59 net_configure_veth_pair
60 } 60 }
61 61
62 notify child init is done 62 notify child init is done
63 63
64 if (any bridge configured) { 64 if (any bridge configured) {
65 for each bridge 65 for each bridge
66 net_bridge_wait_ip 66 net_bridge_wait_ip
67 unlock /var/lock/firejail.lock file 67 unlock /var/lock/firejail.lock file
68 } 68 }
69 69
70 wait on child 70 wait on child
71 exit 71 exit
72} 72}
73 73
74 74
75****************************************************** 75******************************************************
76* macvlan notes 76* macvlan notes
77****************************************************** 77******************************************************
78Configure a macvlan interface 78Configure a macvlan interface
79 79
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c
index 3450bceea..1da25dd08 100644
--- a/src/firejail/network_main.c
+++ b/src/firejail/network_main.c
@@ -50,7 +50,7 @@ void net_configure_bridge(Bridge *br, char *dev_name) {
50 if (asprintf(&newname, "%s-%u", br->devsandbox, getpid()) == -1) 50 if (asprintf(&newname, "%s-%u", br->devsandbox, getpid()) == -1)
51 errExit("asprintf"); 51 errExit("asprintf");
52 br->devsandbox = newname; 52 br->devsandbox = newname;
53 } 53 }
54 else { 54 else {
55 fprintf(stderr, "Error: cannot find network device %s\n", br->dev); 55 fprintf(stderr, "Error: cannot find network device %s\n", br->dev);
56 exit(1); 56 exit(1);
@@ -72,7 +72,7 @@ void net_configure_bridge(Bridge *br, char *dev_name) {
72 printf("macvlan parent device %s at %d.%d.%d.%d/%d\n", 72 printf("macvlan parent device %s at %d.%d.%d.%d/%d\n",
73 br->dev, PRINT_IP(br->ip), mask2bits(br->mask)); 73 br->dev, PRINT_IP(br->ip), mask2bits(br->mask));
74 } 74 }
75 75
76 uint32_t range = ~br->mask + 1; // the number of potential addresses 76 uint32_t range = ~br->mask + 1; // the number of potential addresses
77 // this software is not supported for /31 networks 77 // this software is not supported for /31 networks
78 if (range < 4) { 78 if (range < 4) {
@@ -127,7 +127,7 @@ void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) {
127 } 127 }
128 else 128 else
129 dev = br->veth_name; 129 dev = br->veth_name;
130 130
131 char *cstr; 131 char *cstr;
132 if (asprintf(&cstr, "%d", child) == -1) 132 if (asprintf(&cstr, "%d", child) == -1)
133 errExit("asprintf"); 133 errExit("asprintf");
@@ -249,7 +249,7 @@ void net_dns_print(pid_t pid) {
249 } 249 }
250 free(comm); 250 free(comm);
251 } 251 }
252 252
253 char *fname; 253 char *fname;
254 EUID_ROOT(); 254 EUID_ROOT();
255 if (asprintf(&fname, "/proc/%d/root/etc/resolv.conf", pid) == -1) 255 if (asprintf(&fname, "/proc/%d/root/etc/resolv.conf", pid) == -1)
@@ -261,7 +261,7 @@ void net_dns_print(pid_t pid) {
261 fprintf(stderr, "Error: cannot access /etc/resolv.conf\n"); 261 fprintf(stderr, "Error: cannot access /etc/resolv.conf\n");
262 exit(1); 262 exit(1);
263 } 263 }
264 264
265 char buf[MAXBUF]; 265 char buf[MAXBUF];
266 while (fgets(buf, MAXBUF, fp)) 266 while (fgets(buf, MAXBUF, fp))
267 printf("%s", buf); 267 printf("%s", buf);
@@ -284,21 +284,21 @@ void network_main(pid_t child) {
284 else 284 else
285 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge0.devsandbox, cfg.bridge0.dev, cstr); 285 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge0.devsandbox, cfg.bridge0.dev, cstr);
286 } 286 }
287 287
288 if (cfg.bridge1.configured) { 288 if (cfg.bridge1.configured) {
289 if (cfg.bridge1.macvlan == 0) 289 if (cfg.bridge1.macvlan == 0)
290 net_configure_veth_pair(&cfg.bridge1, "eth1", child); 290 net_configure_veth_pair(&cfg.bridge1, "eth1", child);
291 else 291 else
292 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge1.devsandbox, cfg.bridge1.dev, cstr); 292 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge1.devsandbox, cfg.bridge1.dev, cstr);
293 } 293 }
294 294
295 if (cfg.bridge2.configured) { 295 if (cfg.bridge2.configured) {
296 if (cfg.bridge2.macvlan == 0) 296 if (cfg.bridge2.macvlan == 0)
297 net_configure_veth_pair(&cfg.bridge2, "eth2", child); 297 net_configure_veth_pair(&cfg.bridge2, "eth2", child);
298 else 298 else
299 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge2.devsandbox, cfg.bridge2.dev, cstr); 299 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge2.devsandbox, cfg.bridge2.dev, cstr);
300 } 300 }
301 301
302 if (cfg.bridge3.configured) { 302 if (cfg.bridge3.configured) {
303 if (cfg.bridge3.macvlan == 0) 303 if (cfg.bridge3.macvlan == 0)
304 net_configure_veth_pair(&cfg.bridge3, "eth3", child); 304 net_configure_veth_pair(&cfg.bridge3, "eth3", child);
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c
index 05f5abe2a..b37c5abf7 100644
--- a/src/firejail/no_sandbox.c
+++ b/src/firejail/no_sandbox.c
@@ -39,12 +39,12 @@ int is_container(const char *str) {
39// returns 1 if we are running under LXC 39// returns 1 if we are running under LXC
40int check_namespace_virt(void) { 40int check_namespace_virt(void) {
41 EUID_ASSERT(); 41 EUID_ASSERT();
42 42
43 // check container environment variable 43 // check container environment variable
44 char *str = getenv("container"); 44 char *str = getenv("container");
45 if (str && is_container(str)) 45 if (str && is_container(str))
46 return 1; 46 return 1;
47 47
48 // check PID 1 container environment variable 48 // check PID 1 container environment variable
49 EUID_ROOT(); 49 EUID_ROOT();
50 FILE *fp = fopen("/proc/1/environ", "r"); 50 FILE *fp = fopen("/proc/1/environ", "r");
@@ -62,7 +62,7 @@ int check_namespace_virt(void) {
62 break; 62 break;
63 } 63 }
64 buf[i] = '\0'; 64 buf[i] = '\0';
65 65
66 // check env var name 66 // check env var name
67 if (strncmp(buf, "container=", 10) == 0) { 67 if (strncmp(buf, "container=", 10) == 0) {
68 // found it 68 // found it
@@ -74,10 +74,10 @@ int check_namespace_virt(void) {
74 } 74 }
75// printf("i %d c %d, buf #%s#\n", i, c, buf); 75// printf("i %d c %d, buf #%s#\n", i, c, buf);
76 } 76 }
77 77
78 fclose(fp); 78 fclose(fp);
79 } 79 }
80 80
81 EUID_USER(); 81 EUID_USER();
82 return 0; 82 return 0;
83} 83}
@@ -104,7 +104,7 @@ int check_kernel_procs(void) {
104 104
105 // look at the first 10 processes 105 // look at the first 10 processes
106 // if a kernel process is found, return 1 106 // if a kernel process is found, return 1
107 for (i = 1; i <= 10; i++) { 107 for (i = 1; i <= 10; i++) {
108 struct stat s; 108 struct stat s;
109 char *fname; 109 char *fname;
110 if (asprintf(&fname, "/proc/%d/comm", i) == -1) 110 if (asprintf(&fname, "/proc/%d/comm", i) == -1)
@@ -113,7 +113,7 @@ int check_kernel_procs(void) {
113 free(fname); 113 free(fname);
114 continue; 114 continue;
115 } 115 }
116 116
117 // open file 117 // open file
118 /* coverity[toctou] */ 118 /* coverity[toctou] */
119 FILE *fp = fopen(fname, "r"); 119 FILE *fp = fopen(fname, "r");
@@ -122,7 +122,7 @@ int check_kernel_procs(void) {
122 free(fname); 122 free(fname);
123 continue; 123 continue;
124 } 124 }
125 125
126 // read file 126 // read file
127 char buf[100]; 127 char buf[100];
128 if (fgets(buf, 10, fp) == NULL) { 128 if (fgets(buf, 10, fp) == NULL) {
@@ -135,7 +135,7 @@ int check_kernel_procs(void) {
135 char *ptr; 135 char *ptr;
136 if ((ptr = strchr(buf, '\n')) != NULL) 136 if ((ptr = strchr(buf, '\n')) != NULL)
137 *ptr = '\0'; 137 *ptr = '\0';
138 138
139 // check process name against the kernel list 139 // check process name against the kernel list
140 int j = 0; 140 int j = 0;
141 while (kern_proc[j] != NULL) { 141 while (kern_proc[j] != NULL) {
@@ -148,7 +148,7 @@ int check_kernel_procs(void) {
148 } 148 }
149 j++; 149 j++;
150 } 150 }
151 151
152 fclose(fp); 152 fclose(fp);
153 free(fname); 153 free(fname);
154 } 154 }
diff --git a/src/firejail/output.c b/src/firejail/output.c
index cea4f4e28..9fb4ad6b1 100644
--- a/src/firejail/output.c
+++ b/src/firejail/output.c
@@ -24,7 +24,7 @@
24 24
25void check_output(int argc, char **argv) { 25void check_output(int argc, char **argv) {
26 EUID_ASSERT(); 26 EUID_ASSERT();
27 27
28 int i; 28 int i;
29 int outindex = 0; 29 int outindex = 0;
30 30
@@ -49,7 +49,7 @@ void check_output(int argc, char **argv) {
49 fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n"); 49 fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n");
50 exit(1); 50 exit(1);
51 } 51 }
52 52
53 struct stat s; 53 struct stat s;
54 if (stat(outfile, &s) == 0) { 54 if (stat(outfile, &s) == 0) {
55 // check permissions 55 // check permissions
@@ -57,7 +57,7 @@ void check_output(int argc, char **argv) {
57 fprintf(stderr, "Error: the output file needs to be owned by the current user.\n"); 57 fprintf(stderr, "Error: the output file needs to be owned by the current user.\n");
58 exit(1); 58 exit(1);
59 } 59 }
60 60
61 // check hard links 61 // check hard links
62 if (s.st_nlink != 1) { 62 if (s.st_nlink != 1) {
63 fprintf(stderr, "Error: no hard links allowed.\n"); 63 fprintf(stderr, "Error: no hard links allowed.\n");
@@ -71,11 +71,11 @@ void check_output(int argc, char **argv) {
71 len += strlen(argv[i]) + 1; // + ' ' 71 len += strlen(argv[i]) + 1; // + ' '
72 } 72 }
73 len += 100 + strlen(LIBDIR) + strlen(outfile); // tee command 73 len += 100 + strlen(LIBDIR) + strlen(outfile); // tee command
74 74
75 char *cmd = malloc(len + 1); // + '\0' 75 char *cmd = malloc(len + 1); // + '\0'
76 if (!cmd) 76 if (!cmd)
77 errExit("malloc"); 77 errExit("malloc");
78 78
79 char *ptr = cmd; 79 char *ptr = cmd;
80 for (i = 0; i < argc; i++) { 80 for (i = 0; i < argc; i++) {
81 if (strncmp(argv[i], "--output=", 9) == 0) 81 if (strncmp(argv[i], "--output=", 9) == 0)
@@ -91,7 +91,7 @@ void check_output(int argc, char **argv) {
91 a[2] = cmd; 91 a[2] = cmd;
92 a[3] = NULL; 92 a[3] = NULL;
93 93
94 execvp(a[0], a); 94 execvp(a[0], a);
95 95
96 perror("execvp"); 96 perror("execvp");
97 exit(1); 97 exit(1);
diff --git a/src/firejail/preproc.c b/src/firejail/preproc.c
index b834e6275..ef93368bf 100644
--- a/src/firejail/preproc.c
+++ b/src/firejail/preproc.c
@@ -35,27 +35,27 @@ void preproc_build_firejail_dir(void) {
35 if (stat(RUN_FIREJAIL_DIR, &s)) { 35 if (stat(RUN_FIREJAIL_DIR, &s)) {
36 create_empty_dir_as_root(RUN_FIREJAIL_DIR, 0755); 36 create_empty_dir_as_root(RUN_FIREJAIL_DIR, 0755);
37 } 37 }
38 38
39 if (stat(RUN_FIREJAIL_NETWORK_DIR, &s)) { 39 if (stat(RUN_FIREJAIL_NETWORK_DIR, &s)) {
40 create_empty_dir_as_root(RUN_FIREJAIL_NETWORK_DIR, 0755); 40 create_empty_dir_as_root(RUN_FIREJAIL_NETWORK_DIR, 0755);
41 } 41 }
42 42
43 if (stat(RUN_FIREJAIL_BANDWIDTH_DIR, &s)) { 43 if (stat(RUN_FIREJAIL_BANDWIDTH_DIR, &s)) {
44 create_empty_dir_as_root(RUN_FIREJAIL_BANDWIDTH_DIR, 0755); 44 create_empty_dir_as_root(RUN_FIREJAIL_BANDWIDTH_DIR, 0755);
45 } 45 }
46 46
47 if (stat(RUN_FIREJAIL_NAME_DIR, &s)) { 47 if (stat(RUN_FIREJAIL_NAME_DIR, &s)) {
48 create_empty_dir_as_root(RUN_FIREJAIL_NAME_DIR, 0755); 48 create_empty_dir_as_root(RUN_FIREJAIL_NAME_DIR, 0755);
49 } 49 }
50 50
51 if (stat(RUN_FIREJAIL_X11_DIR, &s)) { 51 if (stat(RUN_FIREJAIL_X11_DIR, &s)) {
52 create_empty_dir_as_root(RUN_FIREJAIL_X11_DIR, 0755); 52 create_empty_dir_as_root(RUN_FIREJAIL_X11_DIR, 0755);
53 } 53 }
54 54
55 if (stat(RUN_FIREJAIL_APPIMAGE_DIR, &s)) { 55 if (stat(RUN_FIREJAIL_APPIMAGE_DIR, &s)) {
56 create_empty_dir_as_root(RUN_FIREJAIL_APPIMAGE_DIR, 0755); 56 create_empty_dir_as_root(RUN_FIREJAIL_APPIMAGE_DIR, 0755);
57 } 57 }
58 58
59 if (stat(RUN_MNT_DIR, &s)) { 59 if (stat(RUN_MNT_DIR, &s)) {
60 create_empty_dir_as_root(RUN_MNT_DIR, 0755); 60 create_empty_dir_as_root(RUN_MNT_DIR, 0755);
61 } 61 }
@@ -74,7 +74,7 @@ void preproc_mount_mnt_dir(void) {
74 errExit("mounting /run/firejail/mnt"); 74 errExit("mounting /run/firejail/mnt");
75 tmpfs_mounted = 1; 75 tmpfs_mounted = 1;
76 fs_logger2("tmpfs", RUN_MNT_DIR); 76 fs_logger2("tmpfs", RUN_MNT_DIR);
77 77
78 //copy defaultl seccomp files 78 //copy defaultl seccomp files
79 copy_file(PATH_SECCOMP_I386, RUN_SECCOMP_I386, getuid(), getgid(), 0644); // root needed 79 copy_file(PATH_SECCOMP_I386, RUN_SECCOMP_I386, getuid(), getgid(), 0644); // root needed
80 copy_file(PATH_SECCOMP_AMD64, RUN_SECCOMP_AMD64, getuid(), getgid(), 0644); // root needed 80 copy_file(PATH_SECCOMP_AMD64, RUN_SECCOMP_AMD64, getuid(), getgid(), 0644); // root needed
@@ -82,7 +82,7 @@ void preproc_mount_mnt_dir(void) {
82 copy_file(PATH_SECCOMP_DEFAULT_DEBUG, RUN_SECCOMP_CFG, getuid(), getgid(), 0644); // root needed 82 copy_file(PATH_SECCOMP_DEFAULT_DEBUG, RUN_SECCOMP_CFG, getuid(), getgid(), 0644); // root needed
83 else 83 else
84 copy_file(PATH_SECCOMP_DEFAULT, RUN_SECCOMP_CFG, getuid(), getgid(), 0644); // root needed 84 copy_file(PATH_SECCOMP_DEFAULT, RUN_SECCOMP_CFG, getuid(), getgid(), 0644); // root needed
85 85
86 // as root, create an empty RUN_SECCOMP_PROTOCOL file 86 // as root, create an empty RUN_SECCOMP_PROTOCOL file
87 create_empty_file_as_root(RUN_SECCOMP_PROTOCOL, 0644); 87 create_empty_file_as_root(RUN_SECCOMP_PROTOCOL, 0644);
88 if (set_perms(RUN_SECCOMP_PROTOCOL, getuid(), getgid(), 0644)) 88 if (set_perms(RUN_SECCOMP_PROTOCOL, getuid(), getgid(), 0644))
diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c
index 098c9fb16..9524d6617 100644
--- a/src/firejail/protocol.c
+++ b/src/firejail/protocol.c
@@ -34,7 +34,7 @@ void protocol_filter_save(void) {
34 34
35void protocol_filter_load(const char *fname) { 35void protocol_filter_load(const char *fname) {
36 assert(fname); 36 assert(fname);
37 37
38 // read protocol filter configuration from PROTOCOL_CFG 38 // read protocol filter configuration from PROTOCOL_CFG
39 FILE *fp = fopen(fname, "r"); 39 FILE *fp = fopen(fname, "r");
40 if (!fp) 40 if (!fp)
@@ -48,7 +48,7 @@ void protocol_filter_load(const char *fname) {
48 return; 48 return;
49 } 49 }
50 fclose(fp); 50 fclose(fp);
51 51
52 char *ptr = strchr(buf, '\n'); 52 char *ptr = strchr(buf, '\n');
53 if (ptr) 53 if (ptr)
54 *ptr = '\0'; 54 *ptr = '\0';
@@ -61,7 +61,7 @@ void protocol_filter_load(const char *fname) {
61// --protocol.print 61// --protocol.print
62void protocol_print_filter(pid_t pid) { 62void protocol_print_filter(pid_t pid) {
63 EUID_ASSERT(); 63 EUID_ASSERT();
64 64
65 (void) pid; 65 (void) pid;
66#ifdef SYS_socket 66#ifdef SYS_socket
67 // if the pid is that of a firejail process, use the pid of the first child process 67 // if the pid is that of a firejail process, use the pid of the first child process
@@ -109,7 +109,7 @@ void protocol_print_filter(pid_t pid) {
109#else 109#else
110 fwarning("--protocol not supported on this platform\n"); 110 fwarning("--protocol not supported on this platform\n");
111 return; 111 return;
112#endif 112#endif
113} 113}
114 114
115 115
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c
index ead5dd361..246ba8fd8 100644
--- a/src/firejail/pulseaudio.c
+++ b/src/firejail/pulseaudio.c
@@ -27,17 +27,17 @@
27static void disable_file(const char *path, const char *file) { 27static void disable_file(const char *path, const char *file) {
28 assert(file); 28 assert(file);
29 assert(path); 29 assert(path);
30 30
31 struct stat s; 31 struct stat s;
32 char *fname; 32 char *fname;
33 if (asprintf(&fname, "%s/%s", path, file) == -1) 33 if (asprintf(&fname, "%s/%s", path, file) == -1)
34 errExit("asprintf"); 34 errExit("asprintf");
35 if (stat(fname, &s) == -1) 35 if (stat(fname, &s) == -1)
36 goto doexit; 36 goto doexit;
37 37
38 if (arg_debug) 38 if (arg_debug)
39 printf("Disable%s\n", fname); 39 printf("Disable%s\n", fname);
40 40
41 if (S_ISDIR(s.st_mode)) { 41 if (S_ISDIR(s.st_mode)) {
42 if (mount(RUN_RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0) 42 if (mount(RUN_RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0)
43 errExit("disable file"); 43 errExit("disable file");
@@ -71,7 +71,7 @@ void pulseaudio_disable(void) {
71 errExit("asprintf"); 71 errExit("asprintf");
72 disable_file(path, "pulse/native"); 72 disable_file(path, "pulse/native");
73 free(path); 73 free(path);
74 74
75 75
76 76
77 // blacklist any pulse* file in /tmp directory 77 // blacklist any pulse* file in /tmp directory
@@ -99,11 +99,11 @@ void pulseaudio_disable(void) {
99// disable shm in pulseaudio 99// disable shm in pulseaudio
100void pulseaudio_init(void) { 100void pulseaudio_init(void) {
101 struct stat s; 101 struct stat s;
102 102
103 // do we have pulseaudio in the system? 103 // do we have pulseaudio in the system?
104 if (stat("/etc/pulse/client.conf", &s) == -1) 104 if (stat("/etc/pulse/client.conf", &s) == -1)
105 return; 105 return;
106 106
107 // create the new user pulseaudio directory 107 // create the new user pulseaudio directory
108 int rv = mkdir(RUN_PULSE_DIR, 0700); 108 int rv = mkdir(RUN_PULSE_DIR, 0700);
109 (void) rv; // in --chroot mode the directory can already be there 109 (void) rv; // in --chroot mode the directory can already be there
@@ -134,7 +134,7 @@ void pulseaudio_init(void) {
134 if (child == 0) { 134 if (child == 0) {
135 // drop privileges 135 // drop privileges
136 drop_privs(0); 136 drop_privs(0);
137 137
138 int rv = mkdir(dir1, 0755); 138 int rv = mkdir(dir1, 0755);
139 if (rv == 0) { 139 if (rv == 0) {
140 if (set_perms(dir1, getuid(), getgid(), 0755)) 140 if (set_perms(dir1, getuid(), getgid(), 0755))
@@ -156,7 +156,7 @@ void pulseaudio_init(void) {
156 } 156 }
157 } 157 }
158 free(dir1); 158 free(dir1);
159 159
160 if (asprintf(&dir1, "%s/.config/pulse", cfg.homedir) == -1) 160 if (asprintf(&dir1, "%s/.config/pulse", cfg.homedir) == -1)
161 errExit("asprintf"); 161 errExit("asprintf");
162 if (stat(dir1, &s) == -1) { 162 if (stat(dir1, &s) == -1) {
@@ -166,7 +166,7 @@ void pulseaudio_init(void) {
166 if (child == 0) { 166 if (child == 0) {
167 // drop privileges 167 // drop privileges
168 drop_privs(0); 168 drop_privs(0);
169 169
170 int rv = mkdir(dir1, 0700); 170 int rv = mkdir(dir1, 0700);
171 if (rv == 0) { 171 if (rv == 0) {
172 if (set_perms(dir1, getuid(), getgid(), 0700)) 172 if (set_perms(dir1, getuid(), getgid(), 0700))
@@ -188,8 +188,8 @@ void pulseaudio_init(void) {
188 } 188 }
189 } 189 }
190 free(dir1); 190 free(dir1);
191 191
192 192
193 // if we have ~/.config/pulse mount the new directory, else set environment variable 193 // if we have ~/.config/pulse mount the new directory, else set environment variable
194 char *homeusercfg; 194 char *homeusercfg;
195 if (asprintf(&homeusercfg, "%s/.config/pulse", cfg.homedir) == -1) 195 if (asprintf(&homeusercfg, "%s/.config/pulse", cfg.homedir) == -1)
@@ -204,7 +204,7 @@ void pulseaudio_init(void) {
204 if (setenv("PULSE_CLIENTCONFIG", pulsecfg, 1) < 0) 204 if (setenv("PULSE_CLIENTCONFIG", pulsecfg, 1) < 0)
205 errExit("setenv"); 205 errExit("setenv");
206 } 206 }
207 207
208 free(pulsecfg); 208 free(pulsecfg);
209 free(homeusercfg); 209 free(homeusercfg);
210} 210}
diff --git a/src/firejail/restrict_users.c b/src/firejail/restrict_users.c
index 086af48b0..87ee513af 100644
--- a/src/firejail/restrict_users.c
+++ b/src/firejail/restrict_users.c
@@ -56,23 +56,23 @@ static USER_LIST *ulist_find(const char *user) {
56 return ptr; 56 return ptr;
57 ptr = ptr->next; 57 ptr = ptr->next;
58 } 58 }
59 59
60 return NULL; 60 return NULL;
61} 61}
62 62
63static void sanitize_home(void) { 63static void sanitize_home(void) {
64 assert(getuid() != 0); // this code works only for regular users 64 assert(getuid() != 0); // this code works only for regular users
65 65
66 if (arg_debug) 66 if (arg_debug)
67 printf("Cleaning /home directory\n"); 67 printf("Cleaning /home directory\n");
68 68
69 struct stat s; 69 struct stat s;
70 if (stat(cfg.homedir, &s) == -1) { 70 if (stat(cfg.homedir, &s) == -1) {
71 // cannot find home directory, just return 71 // cannot find home directory, just return
72 fwarning("cannot find home directory\n"); 72 fwarning("cannot find home directory\n");
73 return; 73 return;
74 } 74 }
75 75
76 if (mkdir(RUN_WHITELIST_HOME_DIR, 0755) == -1) 76 if (mkdir(RUN_WHITELIST_HOME_DIR, 0755) == -1)
77 errExit("mkdir"); 77 errExit("mkdir");
78 78
@@ -93,7 +93,7 @@ static void sanitize_home(void) {
93 errExit("mkdir"); 93 errExit("mkdir");
94 } 94 }
95 fs_logger2("mkdir", cfg.homedir); 95 fs_logger2("mkdir", cfg.homedir);
96 96
97 // set mode and ownership 97 // set mode and ownership
98 if (set_perms(cfg.homedir, s.st_uid, s.st_gid, s.st_mode)) 98 if (set_perms(cfg.homedir, s.st_uid, s.st_gid, s.st_mode))
99 errExit("set_perms"); 99 errExit("set_perms");
@@ -108,7 +108,7 @@ static void sanitize_home(void) {
108 fs_logger2("tmpfs", RUN_WHITELIST_HOME_DIR); 108 fs_logger2("tmpfs", RUN_WHITELIST_HOME_DIR);
109 if (!arg_private) 109 if (!arg_private)
110 fs_logger2("whitelist", cfg.homedir); 110 fs_logger2("whitelist", cfg.homedir);
111 111
112} 112}
113 113
114static void sanitize_passwd(void) { 114static void sanitize_passwd(void) {
@@ -133,7 +133,7 @@ static void sanitize_passwd(void) {
133 fpout = fopen(RUN_PASSWD_FILE, "w"); 133 fpout = fopen(RUN_PASSWD_FILE, "w");
134 if (!fpout) 134 if (!fpout)
135 goto errout; 135 goto errout;
136 136
137 // read the file line by line 137 // read the file line by line
138 char buf[MAXBUF]; 138 char buf[MAXBUF];
139 uid_t myuid = getuid(); 139 uid_t myuid = getuid();
@@ -141,12 +141,12 @@ static void sanitize_passwd(void) {
141 // comments and empty lines 141 // comments and empty lines
142 if (*buf == '\0' || *buf == '#') 142 if (*buf == '\0' || *buf == '#')
143 continue; 143 continue;
144 144
145 // sample line: 145 // sample line:
146 // www-data:x:33:33:www-data:/var/www:/bin/sh 146 // www-data:x:33:33:www-data:/var/www:/bin/sh
147 // drop lines with uid > 1000 and not the current user 147 // drop lines with uid > 1000 and not the current user
148 char *ptr = buf; 148 char *ptr = buf;
149 149
150 // advance to uid 150 // advance to uid
151 while (*ptr != ':' && *ptr != '\0') 151 while (*ptr != ':' && *ptr != '\0')
152 ptr++; 152 ptr++;
@@ -190,9 +190,9 @@ static void sanitize_passwd(void) {
190 if (mount(RUN_PASSWD_FILE, "/etc/passwd", "none", MS_BIND, "mode=400,gid=0") < 0) 190 if (mount(RUN_PASSWD_FILE, "/etc/passwd", "none", MS_BIND, "mode=400,gid=0") < 0)
191 errExit("mount"); 191 errExit("mount");
192 fs_logger("create /etc/passwd"); 192 fs_logger("create /etc/passwd");
193 193
194 return; 194 return;
195 195
196errout: 196errout:
197 fwarning("failed to clean up /etc/passwd\n"); 197 fwarning("failed to clean up /etc/passwd\n");
198 if (fpin) 198 if (fpin)
@@ -206,7 +206,7 @@ static int copy_line(FILE *fpout, char *buf, char *ptr) {
206 // fpout: GROUP_FILE 206 // fpout: GROUP_FILE
207 // buf: pulse:x:115:netblue,bingo 207 // buf: pulse:x:115:netblue,bingo
208 // ptr: 115:neblue,bingo 208 // ptr: 115:neblue,bingo
209 209
210 while (*ptr != ':' && *ptr != '\0') 210 while (*ptr != ':' && *ptr != '\0')
211 ptr++; 211 ptr++;
212 if (*ptr == '\0') 212 if (*ptr == '\0')
@@ -217,7 +217,7 @@ static int copy_line(FILE *fpout, char *buf, char *ptr) {
217 fprintf(fpout, "%s", buf); 217 fprintf(fpout, "%s", buf);
218 return 0; 218 return 0;
219 } 219 }
220 220
221 // print what we have so far 221 // print what we have so far
222 char tmp = *ptr; 222 char tmp = *ptr;
223 *ptr = '\0'; 223 *ptr = '\0';
@@ -266,7 +266,7 @@ static void sanitize_group(void) {
266 fpout = fopen(RUN_GROUP_FILE, "w"); 266 fpout = fopen(RUN_GROUP_FILE, "w");
267 if (!fpout) 267 if (!fpout)
268 goto errout; 268 goto errout;
269 269
270 // read the file line by line 270 // read the file line by line
271 char buf[MAXBUF]; 271 char buf[MAXBUF];
272 gid_t mygid = getgid(); 272 gid_t mygid = getgid();
@@ -274,12 +274,12 @@ static void sanitize_group(void) {
274 // comments and empty lines 274 // comments and empty lines
275 if (*buf == '\0' || *buf == '#') 275 if (*buf == '\0' || *buf == '#')
276 continue; 276 continue;
277 277
278 // sample line: 278 // sample line:
279 // pulse:x:115:netblue,bingo 279 // pulse:x:115:netblue,bingo
280 // drop lines with uid > 1000 and not the current user group 280 // drop lines with uid > 1000 and not the current user group
281 char *ptr = buf; 281 char *ptr = buf;
282 282
283 // advance to uid 283 // advance to uid
284 while (*ptr != ':' && *ptr != '\0') 284 while (*ptr != ':' && *ptr != '\0')
285 ptr++; 285 ptr++;
@@ -318,9 +318,9 @@ static void sanitize_group(void) {
318 if (mount(RUN_GROUP_FILE, "/etc/group", "none", MS_BIND, "mode=400,gid=0") < 0) 318 if (mount(RUN_GROUP_FILE, "/etc/group", "none", MS_BIND, "mode=400,gid=0") < 0)
319 errExit("mount"); 319 errExit("mount");
320 fs_logger("create /etc/group"); 320 fs_logger("create /etc/group");
321 321
322 return; 322 return;
323 323
324errout: 324errout:
325 fwarning("failed to clean up /etc/group\n"); 325 fwarning("failed to clean up /etc/group\n");
326 if (fpin) 326 if (fpin)
@@ -332,7 +332,7 @@ errout:
332void restrict_users(void) { 332void restrict_users(void) {
333 if (arg_allusers) 333 if (arg_allusers)
334 return; 334 return;
335 335
336 // only in user mode 336 // only in user mode
337 if (getuid()) { 337 if (getuid()) {
338 if (strncmp(cfg.homedir, "/home/", 6) == 0) { 338 if (strncmp(cfg.homedir, "/home/", 6) == 0) {
diff --git a/src/firejail/restricted_shell.c b/src/firejail/restricted_shell.c
index 9919c4656..d09a2c7e5 100644
--- a/src/firejail/restricted_shell.c
+++ b/src/firejail/restricted_shell.c
@@ -44,7 +44,7 @@ int restricted_shell(const char *user) {
44 44
45 // remove empty spaces at the beginning of the line 45 // remove empty spaces at the beginning of the line
46 char *ptr = buf; 46 char *ptr = buf;
47 while (*ptr == ' ' || *ptr == '\t') { 47 while (*ptr == ' ' || *ptr == '\t') {
48 ptr++; 48 ptr++;
49 } 49 }
50 if (*ptr == '\n' || *ptr == '#') 50 if (*ptr == '\n' || *ptr == '#')
@@ -53,7 +53,7 @@ int restricted_shell(const char *user) {
53 // 53 //
54 // parse line 54 // parse line
55 // 55 //
56 56
57 // extract users 57 // extract users
58 char *usr = ptr; 58 char *usr = ptr;
59 char *args = strchr(usr, ':'); 59 char *args = strchr(usr, ':');
@@ -61,13 +61,13 @@ int restricted_shell(const char *user) {
61 fprintf(stderr, "Error: users.conf line %d\n", lineno); 61 fprintf(stderr, "Error: users.conf line %d\n", lineno);
62 exit(1); 62 exit(1);
63 } 63 }
64 64
65 *args = '\0'; 65 *args = '\0';
66 args++; 66 args++;
67 ptr = strchr(args, '\n'); 67 ptr = strchr(args, '\n');
68 if (ptr) 68 if (ptr)
69 *ptr = '\0'; 69 *ptr = '\0';
70 70
71 // extract firejail command line arguments 71 // extract firejail command line arguments
72 char *ptr2 = args; 72 char *ptr2 = args;
73 int found = 0; 73 int found = 0;
@@ -81,7 +81,7 @@ int restricted_shell(const char *user) {
81 // if nothing follows, continue 81 // if nothing follows, continue
82 if (!found) 82 if (!found)
83 continue; 83 continue;
84 84
85 // user name globbing 85 // user name globbing
86 if (fnmatch(usr, user, 0) == 0) { 86 if (fnmatch(usr, user, 0) == 0) {
87 // process program arguments 87 // process program arguments
@@ -102,8 +102,8 @@ int restricted_shell(const char *user) {
102 fclose(fp); 102 fclose(fp);
103 } 103 }
104 EUID_USER();} 104 EUID_USER();}
105#endif 105#endif
106 106
107 if (*ptr != '\0') { 107 if (*ptr != '\0') {
108 // go to the end of the word 108 // go to the end of the word
109 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0') 109 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
@@ -128,6 +128,5 @@ int restricted_shell(const char *user) {
128 } 128 }
129 fclose(fp); 129 fclose(fp);
130 130
131 return 0; 131 return 0;
132} 132}
133
diff --git a/src/firejail/rlimit.c b/src/firejail/rlimit.c
index bf63bae38..99127673e 100644
--- a/src/firejail/rlimit.c
+++ b/src/firejail/rlimit.c
@@ -47,7 +47,7 @@ void set_rlimits(void) {
47 if (arg_debug) 47 if (arg_debug)
48 printf("Config rlimit: number of processes %llu\n", cfg.rlimit_nproc); 48 printf("Config rlimit: number of processes %llu\n", cfg.rlimit_nproc);
49 } 49 }
50 50
51 if (arg_rlimit_fsize) { 51 if (arg_rlimit_fsize) {
52 rl.rlim_cur = (rlim_t) cfg.rlimit_fsize; 52 rl.rlim_cur = (rlim_t) cfg.rlimit_fsize;
53 rl.rlim_max = (rlim_t) cfg.rlimit_fsize; 53 rl.rlim_max = (rlim_t) cfg.rlimit_fsize;
@@ -59,7 +59,7 @@ void set_rlimits(void) {
59 if (arg_debug) 59 if (arg_debug)
60 printf("Config rlimit: maximum file size %llu\n", cfg.rlimit_fsize); 60 printf("Config rlimit: maximum file size %llu\n", cfg.rlimit_fsize);
61 } 61 }
62 62
63 if (arg_rlimit_sigpending) { 63 if (arg_rlimit_sigpending) {
64 rl.rlim_cur = (rlim_t) cfg.rlimit_sigpending; 64 rl.rlim_cur = (rlim_t) cfg.rlimit_sigpending;
65 rl.rlim_max = (rlim_t) cfg.rlimit_sigpending; 65 rl.rlim_max = (rlim_t) cfg.rlimit_sigpending;
diff --git a/src/firejail/run_symlink.c b/src/firejail/run_symlink.c
index 57f04485b..a9298a33f 100644
--- a/src/firejail/run_symlink.c
+++ b/src/firejail/run_symlink.c
@@ -24,7 +24,7 @@
24 24
25void run_symlink(int argc, char **argv) { 25void run_symlink(int argc, char **argv) {
26 EUID_ASSERT(); 26 EUID_ASSERT();
27 27
28 char *program = strrchr(argv[0], '/'); 28 char *program = strrchr(argv[0], '/');
29 if (program) 29 if (program)
30 program += 1; 30 program += 1;
@@ -40,7 +40,7 @@ void run_symlink(int argc, char **argv) {
40 fprintf(stderr, "Error: PATH environment variable not set\n"); 40 fprintf(stderr, "Error: PATH environment variable not set\n");
41 exit(1); 41 exit(1);
42 } 42 }
43 43
44 char *path = strdup(p); 44 char *path = strdup(p);
45 if (!path) 45 if (!path)
46 errExit("strdup"); 46 errExit("strdup");
@@ -105,8 +105,8 @@ void run_symlink(int argc, char **argv) {
105 a[i + 2] = argv[i + 1]; 105 a[i + 2] = argv[i + 1];
106 } 106 }
107 a[i + 2] = NULL; 107 a[i + 2] = NULL;
108 assert(getenv("LD_PRELOAD") == NULL); 108 assert(getenv("LD_PRELOAD") == NULL);
109 execvp(a[0], a); 109 execvp(a[0], a);
110 110
111 perror("execvp"); 111 perror("execvp");
112 exit(1); 112 exit(1);
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c
index 9640ef9ed..6cd58d78e 100644
--- a/src/firejail/sbox.c
+++ b/src/firejail/sbox.c
@@ -39,28 +39,28 @@ static struct sock_filter filter[] = {
39#endif 39#endif
40 40
41 // syscall list 41 // syscall list
42#ifdef SYS_mount 42#ifdef SYS_mount
43 BLACKLIST(SYS_mount), // mount/unmount filesystems 43 BLACKLIST(SYS_mount), // mount/unmount filesystems
44#endif 44#endif
45#ifdef SYS_umount2 45#ifdef SYS_umount2
46 BLACKLIST(SYS_umount2), 46 BLACKLIST(SYS_umount2),
47#endif 47#endif
48#ifdef SYS_ptrace 48#ifdef SYS_ptrace
49 BLACKLIST(SYS_ptrace), // trace processes 49 BLACKLIST(SYS_ptrace), // trace processes
50#endif 50#endif
51#ifdef SYS_kexec_file_load 51#ifdef SYS_kexec_file_load
52 BLACKLIST(SYS_kexec_file_load), 52 BLACKLIST(SYS_kexec_file_load),
53#endif 53#endif
54#ifdef SYS_kexec_load 54#ifdef SYS_kexec_load
55 BLACKLIST(SYS_kexec_load), // loading a different kernel 55 BLACKLIST(SYS_kexec_load), // loading a different kernel
56#endif 56#endif
57#ifdef SYS_name_to_handle_at 57#ifdef SYS_name_to_handle_at
58 BLACKLIST(SYS_name_to_handle_at), 58 BLACKLIST(SYS_name_to_handle_at),
59#endif 59#endif
60#ifdef SYS_open_by_handle_at 60#ifdef SYS_open_by_handle_at
61 BLACKLIST(SYS_open_by_handle_at), // open by handle 61 BLACKLIST(SYS_open_by_handle_at), // open by handle
62#endif 62#endif
63#ifdef SYS_init_module 63#ifdef SYS_init_module
64 BLACKLIST(SYS_init_module), // kernel module handling 64 BLACKLIST(SYS_init_module), // kernel module handling
65#endif 65#endif
66#ifdef SYS_finit_module // introduced in 2013 66#ifdef SYS_finit_module // introduced in 2013
@@ -69,31 +69,31 @@ static struct sock_filter filter[] = {
69#ifdef SYS_create_module 69#ifdef SYS_create_module
70 BLACKLIST(SYS_create_module), 70 BLACKLIST(SYS_create_module),
71#endif 71#endif
72#ifdef SYS_delete_module 72#ifdef SYS_delete_module
73 BLACKLIST(SYS_delete_module), 73 BLACKLIST(SYS_delete_module),
74#endif 74#endif
75#ifdef SYS_iopl 75#ifdef SYS_iopl
76 BLACKLIST(SYS_iopl), // io permissions 76 BLACKLIST(SYS_iopl), // io permissions
77#endif 77#endif
78#ifdef SYS_ioperm 78#ifdef SYS_ioperm
79 BLACKLIST(SYS_ioperm), 79 BLACKLIST(SYS_ioperm),
80#endif 80#endif
81#ifdef SYS_iopl 81#ifdef SYS_iopl
82 BLACKLIST(SYS_iopl), // io permissions 82 BLACKLIST(SYS_iopl), // io permissions
83#endif 83#endif
84#ifdef SYS_ioprio_set 84#ifdef SYS_ioprio_set
85 BLACKLIST(SYS_ioprio_set), 85 BLACKLIST(SYS_ioprio_set),
86#endif 86#endif
87#ifdef SYS_ni_syscall // new io permissions call on arm devices 87#ifdef SYS_ni_syscall // new io permissions call on arm devices
88 BLACKLIST(SYS_ni_syscall), 88 BLACKLIST(SYS_ni_syscall),
89#endif 89#endif
90#ifdef SYS_swapon 90#ifdef SYS_swapon
91 BLACKLIST(SYS_swapon), // swap on/off 91 BLACKLIST(SYS_swapon), // swap on/off
92#endif 92#endif
93#ifdef SYS_swapoff 93#ifdef SYS_swapoff
94 BLACKLIST(SYS_swapoff), 94 BLACKLIST(SYS_swapoff),
95#endif 95#endif
96#ifdef SYS_syslog 96#ifdef SYS_syslog
97 BLACKLIST(SYS_syslog), // kernel printk control 97 BLACKLIST(SYS_syslog), // kernel printk control
98#endif 98#endif
99 RETURN_ALLOW 99 RETURN_ALLOW
@@ -113,7 +113,7 @@ typedef struct sbox_config {
113 113
114int sbox_run(unsigned filter, int num, ...) { 114int sbox_run(unsigned filter, int num, ...) {
115 EUID_ROOT(); 115 EUID_ROOT();
116 116
117 int i; 117 int i;
118 va_list valist; 118 va_list valist;
119 va_start(valist, num); 119 va_start(valist, num);
@@ -124,7 +124,7 @@ int sbox_run(unsigned filter, int num, ...) {
124 arg[i] = va_arg(valist, char*); 124 arg[i] = va_arg(valist, char*);
125 arg[i] = NULL; 125 arg[i] = NULL;
126 va_end(valist); 126 va_end(valist);
127 127
128 if (arg_debug) { 128 if (arg_debug) {
129 printf("sbox run: "); 129 printf("sbox run: ");
130 for (i = 0; i <= num; i++) 130 for (i = 0; i <= num; i++)
@@ -138,7 +138,7 @@ int sbox_run(unsigned filter, int num, ...) {
138 if (child == 0) { 138 if (child == 0) {
139 // clean the new process 139 // clean the new process
140 clearenv(); 140 clearenv();
141 141
142 if (filter & SBOX_STDIN_FROM_FILE) { 142 if (filter & SBOX_STDIN_FROM_FILE) {
143 int fd; 143 int fd;
144 if((fd = open(SBOX_STDIN_FILE, O_RDONLY)) == -1) { 144 if((fd = open(SBOX_STDIN_FILE, O_RDONLY)) == -1) {
@@ -154,7 +154,7 @@ int sbox_run(unsigned filter, int num, ...) {
154 else // the user could run the sandbox without /dev/null 154 else // the user could run the sandbox without /dev/null
155 close(STDIN_FILENO); 155 close(STDIN_FILENO);
156 } 156 }
157 157
158 // close all other file descriptors 158 // close all other file descriptors
159 int max = 20; // getdtablesize() is overkill for a firejail process 159 int max = 20; // getdtablesize() is overkill for a firejail process
160 for (i = 3; i < max; i++) 160 for (i = 3; i < max; i++)
@@ -163,10 +163,10 @@ int sbox_run(unsigned filter, int num, ...) {
163 if (arg_debug) { 163 if (arg_debug) {
164 printf("sbox file descriptors:\n"); 164 printf("sbox file descriptors:\n");
165 int rv = system("ls -l /proc/self/fd"); 165 int rv = system("ls -l /proc/self/fd");
166 (void) rv; 166 (void) rv;
167 } 167 }
168 168
169 umask(027); 169 umask(027);
170 170
171 // apply filters 171 // apply filters
172 if (filter & SBOX_CAPS_NONE) { 172 if (filter & SBOX_CAPS_NONE) {
@@ -178,7 +178,7 @@ int sbox_run(unsigned filter, int num, ...) {
178 set |= ((uint64_t) 1) << CAP_NET_RAW; 178 set |= ((uint64_t) 1) << CAP_NET_RAW;
179 caps_set(set); 179 caps_set(set);
180#endif 180#endif
181 } 181 }
182 182
183 if (filter & SBOX_SECCOMP) { 183 if (filter & SBOX_SECCOMP) {
184 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 184 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
@@ -200,11 +200,11 @@ int sbox_run(unsigned filter, int num, ...) {
200 drop_privs(1); 200 drop_privs(1);
201 201
202 clearenv(); 202 clearenv();
203 203
204 // --quiet is passed as an environment variable 204 // --quiet is passed as an environment variable
205 if (arg_quiet) 205 if (arg_quiet)
206 setenv("FIREJAIL_QUIET", "yes", 1); 206 setenv("FIREJAIL_QUIET", "yes", 1);
207 207
208 if (arg[0]) // get rid of scan-build warning 208 if (arg[0]) // get rid of scan-build warning
209 execvp(arg[0], arg); 209 execvp(arg[0], arg);
210 else 210 else
@@ -221,6 +221,6 @@ int sbox_run(unsigned filter, int num, ...) {
221 fprintf(stderr, "Error: failed to run %s\n", arg[0]); 221 fprintf(stderr, "Error: failed to run %s\n", arg[0]);
222 exit(1); 222 exit(1);
223 } 223 }
224 224
225 return status; 225 return status;
226} 226}
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index 4ede003e3..72a5874f8 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -30,13 +30,13 @@ char *seccomp_check_list(const char *str) {
30 fprintf(stderr, "Error: empty syscall lists are not allowed\n"); 30 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
31 exit(1); 31 exit(1);
32 } 32 }
33 33
34 int len = strlen(str) + 1; 34 int len = strlen(str) + 1;
35 char *rv = malloc(len); 35 char *rv = malloc(len);
36 if (!rv) 36 if (!rv)
37 errExit("malloc"); 37 errExit("malloc");
38 memset(rv, 0, len); 38 memset(rv, 0, len);
39 39
40 const char *ptr1 = str; 40 const char *ptr1 = str;
41 char *ptr2 = rv; 41 char *ptr2 = rv;
42 while (*ptr1 != '\0') { 42 while (*ptr1 != '\0') {
@@ -47,14 +47,14 @@ char *seccomp_check_list(const char *str) {
47 exit(1); 47 exit(1);
48 } 48 }
49 } 49 }
50 50
51 return rv; 51 return rv;
52} 52}
53 53
54 54
55int seccomp_load(const char *fname) { 55int seccomp_load(const char *fname) {
56 assert(fname); 56 assert(fname);
57 57
58 // open filter file 58 // open filter file
59 int fd = open(fname, O_RDONLY); 59 int fd = open(fname, O_RDONLY);
60 if (fd == -1) 60 if (fd == -1)
@@ -82,7 +82,7 @@ int seccomp_load(const char *fname) {
82 goto errexit; 82 goto errexit;
83 rd += rv; 83 rd += rv;
84 } 84 }
85 85
86 // close file 86 // close file
87 close(fd); 87 close(fd);
88 88
@@ -97,9 +97,9 @@ int seccomp_load(const char *fname) {
97 err_printed = 1; 97 err_printed = 1;
98 return 1; 98 return 1;
99 } 99 }
100 100
101 return 0; 101 return 0;
102 102
103errexit: 103errexit:
104 fprintf(stderr, "Error: cannot read %s\n", fname); 104 fprintf(stderr, "Error: cannot read %s\n", fname);
105 exit(1); 105 exit(1);
@@ -142,7 +142,7 @@ int seccomp_filter_drop(int enforce_seccomp) {
142#endif 142#endif
143 if (arg_debug) 143 if (arg_debug)
144 printf("Build default+drop seccomp filter\n"); 144 printf("Build default+drop seccomp filter\n");
145 145
146 // build the seccomp filter as a regular user 146 // build the seccomp filter as a regular user
147 int rv; 147 int rv;
148 if (arg_allow_debuggers) 148 if (arg_allow_debuggers)
@@ -154,7 +154,7 @@ int seccomp_filter_drop(int enforce_seccomp) {
154 if (rv) 154 if (rv)
155 exit(rv); 155 exit(rv);
156 } 156 }
157 157
158 // drop list without defaults - secondary filters are not installed 158 // drop list without defaults - secondary filters are not installed
159 else if (cfg.seccomp_list == NULL && cfg.seccomp_list_drop) { 159 else if (cfg.seccomp_list == NULL && cfg.seccomp_list_drop) {
160 if (arg_debug) 160 if (arg_debug)
@@ -175,7 +175,7 @@ int seccomp_filter_drop(int enforce_seccomp) {
175 else { 175 else {
176 assert(0); 176 assert(0);
177 } 177 }
178 178
179 // load the filter 179 // load the filter
180 if (seccomp_load(RUN_SECCOMP_CFG) == 0) { 180 if (seccomp_load(RUN_SECCOMP_CFG) == 0) {
181 if (arg_debug) 181 if (arg_debug)
@@ -185,7 +185,7 @@ int seccomp_filter_drop(int enforce_seccomp) {
185 fprintf(stderr, "Error: a seccomp-enabled Linux kernel is required, exiting...\n"); 185 fprintf(stderr, "Error: a seccomp-enabled Linux kernel is required, exiting...\n");
186 exit(1); 186 exit(1);
187 } 187 }
188 188
189 if (arg_debug && access(PATH_FSECCOMP, X_OK) == 0) 189 if (arg_debug && access(PATH_FSECCOMP, X_OK) == 0)
190 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, 190 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3,
191 PATH_FSECCOMP, "print", RUN_SECCOMP_CFG); 191 PATH_FSECCOMP, "print", RUN_SECCOMP_CFG);
@@ -197,14 +197,14 @@ int seccomp_filter_drop(int enforce_seccomp) {
197int seccomp_filter_keep(void) { 197int seccomp_filter_keep(void) {
198 if (arg_debug) 198 if (arg_debug)
199 printf("Build drop seccomp filter\n"); 199 printf("Build drop seccomp filter\n");
200 200
201 // build the seccomp filter as a regular user 201 // build the seccomp filter as a regular user
202 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4, 202 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
203 PATH_FSECCOMP, "keep", RUN_SECCOMP_CFG, cfg.seccomp_list_keep); 203 PATH_FSECCOMP, "keep", RUN_SECCOMP_CFG, cfg.seccomp_list_keep);
204 if (arg_debug) 204 if (arg_debug)
205 printf("seccomp filter configured\n"); 205 printf("seccomp filter configured\n");
206 206
207 207
208 return seccomp_load(RUN_SECCOMP_CFG); 208 return seccomp_load(RUN_SECCOMP_CFG);
209} 209}
210 210
@@ -255,4 +255,3 @@ void seccomp_print_filter(pid_t pid) {
255} 255}
256 256
257#endif // HAVE_SECCOMP 257#endif // HAVE_SECCOMP
258
diff --git a/src/firejail/shutdown.c b/src/firejail/shutdown.c
index 3c150738b..f187960d5 100644
--- a/src/firejail/shutdown.c
+++ b/src/firejail/shutdown.c
@@ -25,7 +25,7 @@
25 25
26void shut(pid_t pid) { 26void shut(pid_t pid) {
27 EUID_ASSERT(); 27 EUID_ASSERT();
28 28
29 pid_t parent = pid; 29 pid_t parent = pid;
30 // if the pid is that of a firejail process, use the pid of a child process inside the sandbox 30 // if the pid is that of a firejail process, use the pid of a child process inside the sandbox
31 EUID_ROOT(); 31 EUID_ROOT();
@@ -57,11 +57,11 @@ void shut(pid_t pid) {
57 exit(1); 57 exit(1);
58 } 58 }
59 } 59 }
60 60
61 EUID_ROOT(); 61 EUID_ROOT();
62 printf("Sending SIGTERM to %u\n", pid); 62 printf("Sending SIGTERM to %u\n", pid);
63 kill(pid, SIGTERM); 63 kill(pid, SIGTERM);
64 64
65 // wait for not more than 10 seconds 65 // wait for not more than 10 seconds
66 sleep(2); 66 sleep(2);
67 int monsec = 8; 67 int monsec = 8;
@@ -76,7 +76,7 @@ void shut(pid_t pid) {
76 killdone = 1; 76 killdone = 1;
77 break; 77 break;
78 } 78 }
79 79
80 char c; 80 char c;
81 size_t count = fread(&c, 1, 1, fp); 81 size_t count = fread(&c, 1, 1, fp);
82 fclose(fp); 82 fclose(fp);
@@ -102,6 +102,6 @@ void shut(pid_t pid) {
102 kill(parent, SIGKILL); 102 kill(parent, SIGKILL);
103 } 103 }
104 } 104 }
105 105
106 clear_run_files(parent); 106 clear_run_files(parent);
107} 107}
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 54f83dccf..acbc19234 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -118,7 +118,7 @@ int mkpath_as_root(const char* path) {
118void fwarning(char* fmt, ...) { 118void fwarning(char* fmt, ...) {
119 if (arg_quiet) 119 if (arg_quiet)
120 return; 120 return;
121 121
122 va_list args; 122 va_list args;
123 va_start(args,fmt); 123 va_start(args,fmt);
124 fprintf(stderr, "Warning: "); 124 fprintf(stderr, "Warning: ");
@@ -786,7 +786,7 @@ static int remove_callback(const char *fpath, const struct stat *sb, int typefla
786 (void) sb; 786 (void) sb;
787 (void) typeflag; 787 (void) typeflag;
788 (void) ftwbuf; 788 (void) ftwbuf;
789 789
790 int rv = remove(fpath); 790 int rv = remove(fpath);
791 if (rv) 791 if (rv)
792 perror(fpath); 792 perror(fpath);
@@ -816,7 +816,7 @@ void create_empty_dir_as_root(const char *dir, mode_t mode) {
816 assert(dir); 816 assert(dir);
817 mode &= 07777; 817 mode &= 07777;
818 struct stat s; 818 struct stat s;
819 819
820 if (stat(dir, &s)) { 820 if (stat(dir, &s)) {
821 if (arg_debug) 821 if (arg_debug)
822 printf("Creating empty %s directory\n", dir); 822 printf("Creating empty %s directory\n", dir);
@@ -862,7 +862,7 @@ int set_perms(const char *fname, uid_t uid, gid_t gid, mode_t mode) {
862void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) { 862void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) {
863 assert(fname); 863 assert(fname);
864 mode &= 07777; 864 mode &= 07777;
865#if 0 865#if 0
866 printf("fname %s, uid %d, gid %d, mode %x - ", fname, uid, gid, (unsigned) mode); 866 printf("fname %s, uid %d, gid %d, mode %x - ", fname, uid, gid, (unsigned) mode);
867 if (S_ISLNK(mode)) 867 if (S_ISLNK(mode))
868 printf("l"); 868 printf("l");
@@ -886,7 +886,7 @@ void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) {
886 printf( (mode & S_IWOTH) ? "w" : "-"); 886 printf( (mode & S_IWOTH) ? "w" : "-");
887 printf( (mode & S_IXOTH) ? "x" : "-"); 887 printf( (mode & S_IXOTH) ? "x" : "-");
888 printf("\n"); 888 printf("\n");
889#endif 889#endif
890 if (mkdir(fname, mode) == -1 || 890 if (mkdir(fname, mode) == -1 ||
891 chmod(fname, mode) == -1 || 891 chmod(fname, mode) == -1 ||
892 chown(fname, uid, gid)) { 892 chown(fname, uid, gid)) {
@@ -899,7 +899,7 @@ void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) {
899 899
900char *read_text_file_or_exit(const char *fname) { 900char *read_text_file_or_exit(const char *fname) {
901 assert(fname); 901 assert(fname);
902 902
903 // open file 903 // open file
904 int fd = open(fname, O_RDONLY); 904 int fd = open(fname, O_RDONLY);
905 if (fd == -1) { 905 if (fd == -1) {
@@ -912,7 +912,7 @@ char *read_text_file_or_exit(const char *fname) {
912 goto errexit; 912 goto errexit;
913 if (lseek(fd, 0 , SEEK_SET) == -1) 913 if (lseek(fd, 0 , SEEK_SET) == -1)
914 goto errexit; 914 goto errexit;
915 915
916 // allocate memory 916 // allocate memory
917 char *data = malloc(size + 1); // + '\0' 917 char *data = malloc(size + 1); // + '\0'
918 if (data == NULL) 918 if (data == NULL)
@@ -928,11 +928,11 @@ char *read_text_file_or_exit(const char *fname) {
928 } 928 }
929 rd += rv; 929 rd += rv;
930 } 930 }
931 931
932 // close file 932 // close file
933 close(fd); 933 close(fd);
934 return data; 934 return data;
935 935
936errexit: 936errexit:
937 close(fd); 937 close(fd);
938 fprintf(stderr, "Error: cannot read %s\n", fname); 938 fprintf(stderr, "Error: cannot read %s\n", fname);
diff --git a/src/firejail/x11.c b/src/firejail/x11.c
index f1d45adef..5ce156603 100644
--- a/src/firejail/x11.c
+++ b/src/firejail/x11.c
@@ -639,7 +639,7 @@ void x11_start_xpra(int argc, char **argv) {
639 639
640 // build the start command 640 // build the start command
641 char *server_argv[256] = { // rest initialyzed to NULL 641 char *server_argv[256] = { // rest initialyzed to NULL
642 "xpra", "start", display_str, "--no-daemon", 642 "xpra", "start", display_str, "--no-daemon",
643 }; 643 };
644 unsigned pos = 0; 644 unsigned pos = 0;
645 while (server_argv[pos] != NULL) pos++; 645 while (server_argv[pos] != NULL) pos++;
@@ -696,7 +696,7 @@ void x11_start_xpra(int argc, char **argv) {
696 // no overrun 696 // no overrun
697 assert(pos < (sizeof(server_argv)/sizeof(*server_argv))); 697 assert(pos < (sizeof(server_argv)/sizeof(*server_argv)));
698 assert(server_argv[pos-1] == NULL); // last element is null 698 assert(server_argv[pos-1] == NULL); // last element is null
699 699
700 if (arg_debug) { 700 if (arg_debug) {
701 size_t i = 0; 701 size_t i = 0;
702 printf("\n*** Starting xpra server: "); 702 printf("\n*** Starting xpra server: ");
@@ -820,7 +820,7 @@ void x11_start_xpra(int argc, char **argv) {
820 printf("Xpra server pid %d, xpra client pid %d, jail %d\n", server, client, jail); 820 printf("Xpra server pid %d, xpra client pid %d, jail %d\n", server, client, jail);
821 821
822 sleep(1); // adding a delay in order to let the server start 822 sleep(1); // adding a delay in order to let the server start
823 823
824 // wait for jail or server to end 824 // wait for jail or server to end
825 while (1) { 825 while (1) {
826 pid_t pid = wait(NULL); 826 pid_t pid = wait(NULL);