aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/fs.c')
-rw-r--r--src/firejail/fs.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 0562c7424..8db45f967 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -1340,3 +1340,56 @@ void fs_private_tmp(void) {
1340 1340
1341 1341
1342} 1342}
1343
1344// this function is called from sandbox.c before blacklist/whitelist functions
1345void fs_private_cache(void) {
1346 char *cache;
1347 if (asprintf(&cache, "%s/.cache", cfg.homedir) == -1)
1348 errExit("asprintf");
1349 // check if ~/.cache is a valid destination
1350 struct stat s;
1351 if (is_link(cache)) {
1352 fwarning("~/.cache is a symbolic link, tmpfs not mounted\n");
1353 return;
1354 }
1355 if (stat(cache, &s) == -1 || !S_ISDIR(s.st_mode)) {
1356 fwarning("no ~/.cache directory found, tmpfs not mounted\n");
1357 return;
1358 }
1359 if (s.st_uid != getuid()) {
1360 fwarning("~/.cache is not owned by user, tmpfs not mounted\n");
1361 return;
1362 }
1363
1364 // get a file descriptor for ~/.cache, fails if there is any symlink
1365 int fd = safe_fd(cache, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
1366 if (fd == -1)
1367 errExit("safe_fd");
1368 // confirm that actual mount destination is owned by the user
1369 if (fstat(fd, &s) == -1 || s.st_uid != getuid())
1370 errExit("fstat");
1371
1372 // mount a tmpfs on ~/.cache via the symbolic link in /proc/self/fd
1373 char *proc;
1374 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
1375 errExit("asprintf");
1376 if (mount("tmpfs", proc, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, 0) < 0)
1377 errExit("mounting tmpfs");
1378 fs_logger2("tmpfs", cache);
1379 free(proc);
1380 close(fd);
1381 // check the last mount operation
1382 MountData *mdata = get_last_mount();
1383 assert(mdata);
1384 if (strcmp(mdata->fstype, "tmpfs") != 0 || strcmp(mdata->dir, cache) != 0)
1385 errLogExit("invalid .cache mount");
1386
1387 // get a new file descriptor for ~/.cache, the old directory is masked by the tmpfs
1388 fd = safe_fd(cache, O_RDONLY|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
1389 if (fd == -1)
1390 errExit("safe_fd");
1391 free(cache);
1392 // restore permissions
1393 SET_PERMS_FD(fd, s.st_uid, s.st_gid, s.st_mode);
1394 close(fd);
1395}