aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2019-01-19 22:40:13 +0100
committerLibravatar smitsohu <smitsohu@gmail.com>2019-01-19 22:40:13 +0100
commitd6ed2e783a32385e94b8cbbe1673498ab4aa1ebb (patch)
tree9ea1f535b00154abbd321715191b42e2ce18885b
parentflameshot.profile: remove memory-deny-write-execute (diff)
downloadfirejail-d6ed2e783a32385e94b8cbbe1673498ab4aa1ebb.tar.gz
firejail-d6ed2e783a32385e94b8cbbe1673498ab4aa1ebb.tar.zst
firejail-d6ed2e783a32385e94b8cbbe1673498ab4aa1ebb.zip
improve chroot error handling
-rw-r--r--src/firejail/fs.c81
1 files changed, 29 insertions, 52 deletions
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 5edcdd58f..ce2b1a8bc 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -30,6 +30,7 @@
30#include <fcntl.h> 30#include <fcntl.h>
31 31
32#define MAX_BUF 4096 32#define MAX_BUF 4096
33#define EMPTY_STRING ("")
33// check noblacklist statements not matched by a proper blacklist in disable-*.inc files 34// check noblacklist statements not matched by a proper blacklist in disable-*.inc files
34//#define TEST_NO_BLACKLIST_MATCHING 35//#define TEST_NO_BLACKLIST_MATCHING
35 36
@@ -1215,9 +1216,8 @@ void fs_overlayfs(void) {
1215void fs_check_chroot_dir(const char *rootdir) { 1216void fs_check_chroot_dir(const char *rootdir) {
1216 EUID_ASSERT(); 1217 EUID_ASSERT();
1217 assert(rootdir); 1218 assert(rootdir);
1219 char *dir = EMPTY_STRING;
1218 struct stat s; 1220 struct stat s;
1219 int fd = -1;
1220 int parentfd = -1;
1221 1221
1222 char *overlay; 1222 char *overlay;
1223 if (asprintf(&overlay, "%s/.firejail", cfg.homedir) == -1) 1223 if (asprintf(&overlay, "%s/.firejail", cfg.homedir) == -1)
@@ -1229,7 +1229,7 @@ void fs_check_chroot_dir(const char *rootdir) {
1229 free(overlay); 1229 free(overlay);
1230 1230
1231 // fails if there is any symlink or if rootdir is not a directory 1231 // fails if there is any symlink or if rootdir is not a directory
1232 parentfd = safe_fd(rootdir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 1232 int parentfd = safe_fd(rootdir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
1233 if (parentfd == -1) { 1233 if (parentfd == -1) {
1234 fprintf(stderr, "Error: invalid chroot directory %s\n", rootdir); 1234 fprintf(stderr, "Error: invalid chroot directory %s\n", rootdir);
1235 exit(1); 1235 exit(1);
@@ -1248,78 +1248,58 @@ void fs_check_chroot_dir(const char *rootdir) {
1248 } 1248 }
1249 1249
1250 // check /dev 1250 // check /dev
1251 char *dir = "dev"; 1251 dir = "dev";
1252 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); 1252 int fd = openat(parentfd, dir, O_PATH|O_CLOEXEC);
1253 if (fd == -1) { 1253 if (fd == -1)
1254 if (errno == ENOENT) 1254 goto error1;
1255 goto error1;
1256 else
1257 goto error2;
1258 }
1259 if (fstat(fd, &s) == -1) 1255 if (fstat(fd, &s) == -1)
1260 errExit("fstat"); 1256 errExit("fstat");
1261 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) 1257 if (!S_ISDIR(s.st_mode) || s.st_uid != 0)
1262 goto error3; 1258 goto error2;
1263 close(fd); 1259 close(fd);
1264 1260
1265 // check /var/tmp 1261 // check /var/tmp
1266 dir = "var/tmp"; 1262 dir = "var/tmp";
1267 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); 1263 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC);
1268 if (fd == -1) { 1264 if (fd == -1)
1269 if (errno == ENOENT) 1265 goto error1;
1270 goto error1;
1271 else
1272 goto error2;
1273 }
1274 if (fstat(fd, &s) == -1) 1266 if (fstat(fd, &s) == -1)
1275 errExit("fstat"); 1267 errExit("fstat");
1276 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) 1268 if (!S_ISDIR(s.st_mode) || s.st_uid != 0)
1277 goto error3; 1269 goto error2;
1278 close(fd); 1270 close(fd);
1279 1271
1280 // check /proc 1272 // check /proc
1281 dir = "proc"; 1273 dir = "proc";
1282 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); 1274 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC);
1283 if (fd == -1) { 1275 if (fd == -1)
1284 if (errno == ENOENT) 1276 goto error1;
1285 goto error1;
1286 else
1287 goto error2;
1288 }
1289 if (fstat(fd, &s) == -1) 1277 if (fstat(fd, &s) == -1)
1290 errExit("fstat"); 1278 errExit("fstat");
1291 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) 1279 if (!S_ISDIR(s.st_mode) || s.st_uid != 0)
1292 goto error3; 1280 goto error2;
1293 close(fd); 1281 close(fd);
1294 1282
1295 // check /tmp 1283 // check /tmp
1296 dir = "tmp"; 1284 dir = "tmp";
1297 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); 1285 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC);
1298 if (fd == -1) { 1286 if (fd == -1)
1299 if (errno == ENOENT) 1287 goto error1;
1300 goto error1;
1301 else
1302 goto error2;
1303 }
1304 if (fstat(fd, &s) == -1) 1288 if (fstat(fd, &s) == -1)
1305 errExit("fstat"); 1289 errExit("fstat");
1306 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) 1290 if (!S_ISDIR(s.st_mode) || s.st_uid != 0)
1307 goto error3; 1291 goto error2;
1308 close(fd); 1292 close(fd);
1309 1293
1310 // check /etc 1294 // check /etc
1311 dir = "etc"; 1295 dir = "etc";
1312 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); 1296 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC);
1313 if (fd == -1) { 1297 if (fd == -1)
1314 if (errno == ENOENT) 1298 goto error1;
1315 goto error1;
1316 else
1317 goto error2;
1318 }
1319 if (fstat(fd, &s) == -1) 1299 if (fstat(fd, &s) == -1)
1320 errExit("fstat"); 1300 errExit("fstat");
1321 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) 1301 if (!S_ISDIR(s.st_mode) || s.st_uid != 0)
1322 goto error3; 1302 goto error2;
1323 if (((S_IWGRP|S_IWOTH) & s.st_mode) != 0) { 1303 if (((S_IWGRP|S_IWOTH) & s.st_mode) != 0) {
1324 fprintf(stderr, "Error: only root user should be given write permission on chroot /etc\n"); 1304 fprintf(stderr, "Error: only root user should be given write permission on chroot /etc\n");
1325 exit(1); 1305 exit(1);
@@ -1358,16 +1338,12 @@ void fs_check_chroot_dir(const char *rootdir) {
1358 if (getenv("FIREJAIL_X11")) { 1338 if (getenv("FIREJAIL_X11")) {
1359 dir = "tmp/.X11-unix"; 1339 dir = "tmp/.X11-unix";
1360 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); 1340 fd = openat(parentfd, dir, O_PATH|O_CLOEXEC);
1361 if (fd == -1) { 1341 if (fd == -1)
1362 if (errno == ENOENT) 1342 goto error1;
1363 goto error1;
1364 else
1365 goto error2;
1366 }
1367 if (fstat(fd, &s) == -1) 1343 if (fstat(fd, &s) == -1)
1368 errExit("fstat"); 1344 errExit("fstat");
1369 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) 1345 if (!S_ISDIR(s.st_mode) || s.st_uid != 0)
1370 goto error3; 1346 goto error2;
1371 close(fd); 1347 close(fd);
1372 } 1348 }
1373 1349
@@ -1375,13 +1351,14 @@ void fs_check_chroot_dir(const char *rootdir) {
1375 return; 1351 return;
1376 1352
1377error1: 1353error1:
1378 fprintf(stderr, "Error: cannot find /%s in chroot directory\n", dir); 1354 if (errno == ENOENT)
1355 fprintf(stderr, "Error: cannot find /%s in chroot directory\n", dir);
1356 else {
1357 perror("open");
1358 fprintf(stderr, "Error: cannot open /%s in chroot directory\n", dir);
1359 }
1379 exit(1); 1360 exit(1);
1380error2: 1361error2:
1381 perror("open");
1382 fprintf(stderr, "Error: cannot open /%s in chroot directory\n", dir);
1383 exit(1);
1384error3:
1385 fprintf(stderr, "Error: chroot /%s should be a directory owned by root\n", dir); 1362 fprintf(stderr, "Error: chroot /%s should be a directory owned by root\n", dir);
1386 exit(1); 1363 exit(1);
1387} 1364}