diff options
Diffstat (limited to 'src/firejail')
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 | ||
43 | distclean: clean | 43 | distclean: 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 | ||
31 | static char *devloop = NULL; // device file | 31 | static char *devloop = NULL; // device file |
32 | static char *mntdir = NULL; // mount point in /tmp directory | 32 | static char *mntdir = NULL; // mount point in /tmp directory |
33 | 33 | ||
34 | static void err_loop(void) { | 34 | static 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 | ||
53 | 8. --private=dirname | 53 | 8. --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 | ||
62 | 9. --private-home=filelist | 62 | 9. --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 | ||
70 | 10. --netfilter=filename | 70 | 10. --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 | ||
78 | 11. --shell=filename | 78 | 11. --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 | ||
75 | void ifbw_remove(IFBW *r) { | 75 | void 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 |
257 | void bandwidth_remove(pid_t pid, const char *dev) { | 257 | void 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 | ||
224 | errexit: | 224 | errexit: |
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 | ||
229 | void caps_print(void) { | 229 | void 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 | ||
301 | errexit: | 301 | errexit: |
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 | ||
306 | void caps_drop_all(void) { | 306 | void caps_drop_all(void) { |
@@ -359,7 +359,7 @@ void caps_keep_list(const char *clist) { | |||
359 | #define MAXBUF 4098 | 359 | #define MAXBUF 4098 |
360 | static uint64_t extract_caps(int pid) { | 360 | static 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 | ||
386 | errexit: | 386 | errexit: |
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 | ||
392 | void caps_print_filter(pid_t pid) { | 392 | void 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 @@ | |||
25 | void save_cgroup(void) { | 25 | void 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 | ||
42 | errout: | 42 | errout: |
@@ -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 | ||
72 | void set_cgroup(const char *path) { | 72 | void 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 | ||
113 | errout: | 113 | errout: |
114 | fprintf(stderr, "Error: invalid cgroup\n"); | 114 | fprintf(stderr, "Error: invalid cgroup\n"); |
115 | exit(1); | 115 | exit(1); |
116 | errout2: | 116 | errout2: |
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 | ||
361 | errout: | 361 | errout: |
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 | ||
29 | static int cmdline_length(int argc, char **argv, int index) { | 29 | static 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 @@ | |||
26 | static void set_cpu(const char *str) { | 26 | static 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 | ||
42 | void read_cpu_list(const char *str) { | 42 | void 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 | ||
165 | void cpu_print_filter(pid_t pid) { | 165 | void 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 | ||
34 | static void env_add(Env *env) { | 34 | static 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 |
154 | void env_store(const char *str, ENV_OP op) { | 154 | void 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 | ||
190 | errexit: | 190 | errexit: |
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 |
196 | void env_apply(void) { | 196 | void 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 |
619 | void fs_basic_fs(void) { | 619 | void 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 |
992 | void fs_check_chroot_dir(const char *rootdir) { | 992 | void 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 |
1111 | void fs_chroot(const char *rootdir) { | 1111 | void 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 |
40 | static char *check_dir_or_file(const char *name) { | 40 | static 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) { | |||
123 | void fs_private_bin_list(void) { | 123 | void 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 | ||
96 | errexit: | 96 | errexit: |
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) { | |||
322 | void fs_check_private_dir(void) { | 322 | void 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 | ||
28 | void fs_hostname(const char *hostname) { | 28 | void 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) { | |||
91 | void fs_logger_print(void) { | 91 | void 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 | ||
58 | void fs_mkdir(const char *name) { | 58 | void 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 | ||
94 | doexit: | 94 | doexit: |
95 | free(expanded); | 95 | free(expanded); |
96 | } | 96 | } |
97 | 97 | ||
98 | void fs_mkfile(const char *name) { | 98 | void 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 | ||
119 | doexit: | 119 | doexit: |
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 | ||
52 | static void build_list(const char *srcdir) { | 52 | static 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 | ||
106 | void fs_var_log(void) { | 106 | void 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 | ||
149 | void fs_var_lib(void) { | 149 | void 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 | ||
199 | void fs_var_cache(void) { | 199 | void 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 | ||
233 | void dbg_test_dir(const char *dir) { | 233 | void 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 | ||
138 | static int mkpath(const char* path, mode_t mode) { | 138 | static 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 | ||
814 | errexit: | 814 | errexit: |
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 | ||
60 | void git_install(void) { | 60 | void 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 | ||
37 | static void print_file_or_dir(const char *path, const char *fname, int separator) { | 37 | static 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 | ||
165 | static void print_directory(const char *path) { | 165 | static 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 = | |||
46 | void check_netfilter_file(const char *fname) { | 46 | void 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) { | |||
113 | void netfilter6(const char *fname) { | 113 | void 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 | ||
249 | void net_config_interface(const char *dev, uint32_t ip, uint32_t mask, int mtu) { | 249 | void 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 | ****************************************************** |
78 | Configure a macvlan interface | 78 | Configure 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 |
40 | int check_namespace_virt(void) { | 40 | int 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 | ||
25 | void check_output(int argc, char **argv) { | 25 | void 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 | ||
35 | void protocol_filter_load(const char *fname) { | 35 | void 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 |
62 | void protocol_print_filter(pid_t pid) { | 62 | void 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 @@ | |||
27 | static void disable_file(const char *path, const char *file) { | 27 | static 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 |
100 | void pulseaudio_init(void) { | 100 | void 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 | ||
63 | static void sanitize_home(void) { | 63 | static 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 | ||
114 | static void sanitize_passwd(void) { | 114 | static 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 | ||
196 | errout: | 196 | errout: |
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 | ||
324 | errout: | 324 | errout: |
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: | |||
332 | void restrict_users(void) { | 332 | void 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 | ||
25 | void run_symlink(int argc, char **argv) { | 25 | void 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 | ||
114 | int sbox_run(unsigned filter, int num, ...) { | 114 | int 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 | ||
55 | int seccomp_load(const char *fname) { | 55 | int 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 | ||
103 | errexit: | 103 | errexit: |
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) { | |||
197 | int seccomp_filter_keep(void) { | 197 | int 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 | ||
26 | void shut(pid_t pid) { | 26 | void 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) { | |||
118 | void fwarning(char* fmt, ...) { | 118 | void 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) { | |||
862 | void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) { | 862 | void 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 | ||
900 | char *read_text_file_or_exit(const char *fname) { | 900 | char *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 | ||
936 | errexit: | 936 | errexit: |
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); |