aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@protonmail.com>2021-02-24 10:45:29 -0500
committerLibravatar GitHub <noreply@github.com>2021-02-24 10:45:29 -0500
commit9a47e2de8e7aa050b0579424c693b38fc812b036 (patch)
treec30e68b2ce7273dce6f1cbaaa29e1d3e90a89140 /src
parentMerge pull request #4001 from kmk3/fix-signal-xdg-ignore (diff)
parentAdd checks to fs_private_dir_mount (diff)
downloadfirejail-9a47e2de8e7aa050b0579424c693b38fc812b036.tar.gz
firejail-9a47e2de8e7aa050b0579424c693b38fc812b036.tar.zst
firejail-9a47e2de8e7aa050b0579424c693b38fc812b036.zip
Merge pull request #3998 from Tomin1/first_fixes
Upstreaming a set of fixes from Sailfish's packaging
Diffstat (limited to 'src')
-rw-r--r--src/fcopy/main.c56
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/fs_etc.c20
-rw-r--r--src/firejail/fs_mkdir.c4
-rw-r--r--src/firejail/main.c2
-rw-r--r--src/firejail/network_main.c2
-rw-r--r--src/firejail/sandbox.c25
7 files changed, 96 insertions, 15 deletions
diff --git a/src/fcopy/main.c b/src/fcopy/main.c
index 01633be59..d863b537b 100644
--- a/src/fcopy/main.c
+++ b/src/fcopy/main.c
@@ -172,6 +172,47 @@ static void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) {
172 } 172 }
173} 173}
174 174
175static char *proc_pid_to_self(const char *target)
176{
177 char *use_target = 0;
178 char *proc_pid = 0;
179
180 if (!(use_target = canonicalize_file_name(target)))
181 goto done;
182
183 // target is under /proc/<PID>?
184 static const char proc[] = "/proc/";
185 if (strncmp(use_target, proc, sizeof proc - 1))
186 goto done;
187
188 int digit = use_target[sizeof proc - 1];
189 if (digit < '1' || digit > '9')
190 goto done;
191
192 // check where /proc/self points to
193 static const char proc_self[] = "/proc/self";
194 if (!(proc_pid = canonicalize_file_name(proc_self)))
195 goto done;
196
197 // redirect /proc/PID/xxx -> /proc/self/XXX
198 size_t pfix = strlen(proc_pid);
199 if (strncmp(use_target, proc_pid, pfix))
200 goto done;
201
202 if (use_target[pfix] != 0 && use_target[pfix] != '/')
203 goto done;
204
205 char *tmp;
206 if (asprintf(&tmp, "%s%s", proc_self, use_target + pfix) != -1) {
207 if (arg_debug)
208 fprintf(stderr, "SYMLINK %s\n --> %s\n", use_target, tmp);
209 free(use_target), use_target = tmp;
210 }
211
212done:
213 free(proc_pid);
214 return use_target;
215}
175 216
176void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) { 217void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) {
177 (void) mode; 218 (void) mode;
@@ -183,7 +224,7 @@ void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid,
183 if (lstat(linkpath, &s) == 0) 224 if (lstat(linkpath, &s) == 0)
184 return; 225 return;
185 226
186 char *rp = realpath(target, NULL); 227 char *rp = proc_pid_to_self(target);
187 if (rp) { 228 if (rp) {
188 if (symlink(rp, linkpath) == -1) { 229 if (symlink(rp, linkpath) == -1) {
189 free(rp); 230 free(rp);
@@ -227,16 +268,14 @@ static int fs_copydir(const char *infname, const struct stat *st, int ftype, str
227 first = 0; 268 first = 0;
228 else if (!arg_quiet) 269 else if (!arg_quiet)
229 fprintf(stderr, "Warning fcopy: skipping %s, file already present\n", infname); 270 fprintf(stderr, "Warning fcopy: skipping %s, file already present\n", infname);
230 free(outfname); 271 goto out;
231 return 0;
232 } 272 }
233 273
234 // extract mode and ownership 274 // extract mode and ownership
235 if (stat(infname, &s) != 0) { 275 if (stat(infname, &s) != 0) {
236 if (!arg_quiet) 276 if (!arg_quiet)
237 fprintf(stderr, "Warning fcopy: skipping %s, cannot find inode\n", infname); 277 fprintf(stderr, "Warning fcopy: skipping %s, cannot find inode\n", infname);
238 free(outfname); 278 goto out;
239 return 0;
240 } 279 }
241 uid_t uid = s.st_uid; 280 uid_t uid = s.st_uid;
242 gid_t gid = s.st_gid; 281 gid_t gid = s.st_gid;
@@ -246,8 +285,7 @@ static int fs_copydir(const char *infname, const struct stat *st, int ftype, str
246 if ((s.st_size + size_cnt) > copy_limit) { 285 if ((s.st_size + size_cnt) > copy_limit) {
247 fprintf(stderr, "Error fcopy: size limit of %lu MB reached\n", (copy_limit / 1024) / 1024); 286 fprintf(stderr, "Error fcopy: size limit of %lu MB reached\n", (copy_limit / 1024) / 1024);
248 size_limit_reached = 1; 287 size_limit_reached = 1;
249 free(outfname); 288 goto out;
250 return 0;
251 } 289 }
252 290
253 file_cnt++; 291 file_cnt++;
@@ -262,7 +300,8 @@ static int fs_copydir(const char *infname, const struct stat *st, int ftype, str
262 else if (ftype == FTW_SL) { 300 else if (ftype == FTW_SL) {
263 copy_link(infname, outfname, mode, uid, gid); 301 copy_link(infname, outfname, mode, uid, gid);
264 } 302 }
265 303out:
304 free(outfname);
266 return(0); 305 return(0);
267} 306}
268 307
@@ -295,6 +334,7 @@ static char *check(const char *src) {
295 return rsrc; // normal exit from the function 334 return rsrc; // normal exit from the function
296 335
297errexit: 336errexit:
337 free(rsrc);
298 fprintf(stderr, "Error fcopy: invalid file %s\n", src); 338 fprintf(stderr, "Error fcopy: invalid file %s\n", src);
299 exit(1); 339 exit(1);
300} 340}
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 719cd74ae..36340ff2c 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -649,6 +649,8 @@ void network_set_run_file(pid_t pid);
649 649
650// fs_etc.c 650// fs_etc.c
651void fs_machineid(void); 651void fs_machineid(void);
652void fs_private_dir_copy(const char *private_dir, const char *private_run_dir, const char *private_list);
653void fs_private_dir_mount(const char *private_dir, const char *private_run_dir);
652void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list); 654void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list);
653 655
654// no_sandbox.c 656// no_sandbox.c
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c
index d152ed2f6..b9ed81db3 100644
--- a/src/firejail/fs_etc.c
+++ b/src/firejail/fs_etc.c
@@ -138,7 +138,7 @@ static void duplicate(const char *fname, const char *private_dir, const char *pr
138} 138}
139 139
140 140
141void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list) { 141void fs_private_dir_copy(const char *private_dir, const char *private_run_dir, const char *private_list) {
142 assert(private_dir); 142 assert(private_dir);
143 assert(private_run_dir); 143 assert(private_run_dir);
144 assert(private_list); 144 assert(private_list);
@@ -185,6 +185,19 @@ void fs_private_dir_list(const char *private_dir, const char *private_run_dir, c
185 free(dlist); 185 free(dlist);
186 fs_logger_print(); 186 fs_logger_print();
187 } 187 }
188}
189
190void fs_private_dir_mount(const char *private_dir, const char *private_run_dir) {
191 assert(private_dir);
192 assert(private_run_dir);
193
194 // nothing to do if directory does not exist
195 struct stat s;
196 if (stat(private_dir, &s) == -1) {
197 if (arg_debug)
198 printf("Cannot find %s\n", private_dir);
199 return;
200 }
188 201
189 if (arg_debug) 202 if (arg_debug)
190 printf("Mount-bind %s on top of %s\n", private_run_dir, private_dir); 203 printf("Mount-bind %s on top of %s\n", private_run_dir, private_dir);
@@ -199,3 +212,8 @@ void fs_private_dir_list(const char *private_dir, const char *private_run_dir, c
199 212
200 fmessage("Private %s installed in %0.2f ms\n", private_dir, timetrace_end()); 213 fmessage("Private %s installed in %0.2f ms\n", private_dir, timetrace_end());
201} 214}
215
216void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list) {
217 fs_private_dir_copy(private_dir, private_run_dir, private_list);
218 fs_private_dir_mount(private_dir, private_run_dir);
219}
diff --git a/src/firejail/fs_mkdir.c b/src/firejail/fs_mkdir.c
index d1b3b5629..8cfeea582 100644
--- a/src/firejail/fs_mkdir.c
+++ b/src/firejail/fs_mkdir.c
@@ -46,7 +46,7 @@ static void mkdir_recursive(char *path) {
46 struct stat s; 46 struct stat s;
47 47
48 if (chdir("/")) { 48 if (chdir("/")) {
49 fprintf(stderr, "Error: can't chdir to /"); 49 fprintf(stderr, "Error: can't chdir to /\n");
50 return; 50 return;
51 } 51 }
52 52
@@ -63,7 +63,7 @@ static void mkdir_recursive(char *path) {
63 return; 63 return;
64 } 64 }
65 if (chdir(subdir)) { 65 if (chdir(subdir)) {
66 fprintf(stderr, "Error: can't chdir to %s", subdir); 66 fprintf(stderr, "Error: can't chdir to %s\n", subdir);
67 return; 67 return;
68 } 68 }
69 69
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 61533fcd9..ef8166204 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -297,7 +297,7 @@ static void check_network(Bridge *br) {
297 else if (br->ipsandbox) { // for macvlan check network range 297 else if (br->ipsandbox) { // for macvlan check network range
298 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask); 298 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask);
299 if (rv) { 299 if (rv) {
300 fprintf(stderr, "%s", rv); 300 fprintf(stderr, "%s\n", rv);
301 exit(1); 301 exit(1);
302 } 302 }
303 } 303 }
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c
index f1ad6430a..ee3c00872 100644
--- a/src/firejail/network_main.c
+++ b/src/firejail/network_main.c
@@ -120,7 +120,7 @@ void net_configure_sandbox_ip(Bridge *br) {
120 // check network range 120 // check network range
121 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask); 121 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask);
122 if (rv) { 122 if (rv) {
123 fprintf(stderr, "%s", rv); 123 fprintf(stderr, "%s\n", rv);
124 exit(1); 124 exit(1);
125 } 125 }
126 // send an ARP request and check if there is anybody on this IP address 126 // send an ARP request and check if there is anybody on this IP address
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 9a4be5cc0..ff5f4cb1e 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -969,8 +969,29 @@ int sandbox(void* sandbox_arg) {
969 else if (arg_overlay) 969 else if (arg_overlay)
970 fwarning("private-etc feature is disabled in overlay\n"); 970 fwarning("private-etc feature is disabled in overlay\n");
971 else { 971 else {
972 fs_private_dir_list("/etc", RUN_ETC_DIR, cfg.etc_private_keep); 972 /* Current /etc/passwd and /etc/group files are bind
973 fs_private_dir_list("/usr/etc", RUN_USR_ETC_DIR, cfg.etc_private_keep); // openSUSE 973 * mounted filtered versions of originals. Leaving
974 * them underneath private-etc mount causes problems
975 * in devices with older kernels, e.g. attempts to
976 * update the real /etc/passwd file yield EBUSY.
977 *
978 * As we do want to retain filtered /etc content:
979 * 1. duplicate /etc content to RUN_ETC_DIR
980 * 2. unmount bind mounts from /etc
981 * 3. mount RUN_ETC_DIR at /etc
982 */
983 fs_private_dir_copy("/etc", RUN_ETC_DIR, cfg.etc_private_keep);
984 fs_private_dir_copy("/usr/etc", RUN_USR_ETC_DIR, cfg.etc_private_keep); // openSUSE
985
986 if (umount2("/etc/group", MNT_DETACH) == -1)
987 fprintf(stderr, "/etc/group: unmount: %m\n");
988
989 if (umount2("/etc/passwd", MNT_DETACH) == -1)
990 fprintf(stderr, "/etc/passwd: unmount: %m\n");
991
992 fs_private_dir_mount("/etc", RUN_ETC_DIR);
993 fs_private_dir_mount("/usr/etc", RUN_USR_ETC_DIR);
994
974 // create /etc/ld.so.preload file again 995 // create /etc/ld.so.preload file again
975 if (need_preload) 996 if (need_preload)
976 fs_trace_preload(); 997 fs_trace_preload();