diff options
author | 2019-01-19 22:40:13 +0100 | |
---|---|---|
committer | 2019-01-19 22:40:13 +0100 | |
commit | d6ed2e783a32385e94b8cbbe1673498ab4aa1ebb (patch) | |
tree | 9ea1f535b00154abbd321715191b42e2ce18885b | |
parent | flameshot.profile: remove memory-deny-write-execute (diff) | |
download | firejail-d6ed2e783a32385e94b8cbbe1673498ab4aa1ebb.tar.gz firejail-d6ed2e783a32385e94b8cbbe1673498ab4aa1ebb.tar.zst firejail-d6ed2e783a32385e94b8cbbe1673498ab4aa1ebb.zip |
improve chroot error handling
-rw-r--r-- | src/firejail/fs.c | 81 |
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) { | |||
1215 | void fs_check_chroot_dir(const char *rootdir) { | 1216 | void 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 | ||
1377 | error1: | 1353 | error1: |
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); |
1380 | error2: | 1361 | error2: |
1381 | perror("open"); | ||
1382 | fprintf(stderr, "Error: cannot open /%s in chroot directory\n", dir); | ||
1383 | exit(1); | ||
1384 | error3: | ||
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 | } |