aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2018-08-30 00:06:12 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2018-08-30 00:06:12 +0200
commit1d18b57644b0429437deb94c056ca36162d79f7c (patch)
treeec56a23312cdb275224d6be222492cdec64c914b
parentmore silencing of /sys umount warnings (diff)
downloadfirejail-1d18b57644b0429437deb94c056ca36162d79f7c.tar.gz
firejail-1d18b57644b0429437deb94c056ca36162d79f7c.tar.zst
firejail-1d18b57644b0429437deb94c056ca36162d79f7c.zip
reject chroot if it is world-writable, related enhancements
-rw-r--r--src/firejail/fs.c60
-rw-r--r--src/firejail/main.c2
2 files changed, 43 insertions, 19 deletions
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 825f004cc..ed0131b1d 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -1160,7 +1160,8 @@ void fs_check_chroot_dir(const char *rootdir) {
1160 exit(1); 1160 exit(1);
1161 } 1161 }
1162 1162
1163 // rootdir has to be owned by root 1163 // rootdir has to be owned by root and is not allowed to be world-writable
1164 // we checked already if it is a directory
1164 if (stat(rootdir, &s) != 0) { 1165 if (stat(rootdir, &s) != 0) {
1165 fprintf(stderr, "Error: cannot find chroot directory\n"); 1166 fprintf(stderr, "Error: cannot find chroot directory\n");
1166 exit(1); 1167 exit(1);
@@ -1169,6 +1170,10 @@ void fs_check_chroot_dir(const char *rootdir) {
1169 fprintf(stderr, "Error: chroot directory should be owned by root\n"); 1170 fprintf(stderr, "Error: chroot directory should be owned by root\n");
1170 exit(1); 1171 exit(1);
1171 } 1172 }
1173 if ((S_IWOTH & s.st_mode) != 0) {
1174 fprintf(stderr, "Error: chroot directory is not allowed to be world-writable\n");
1175 exit(1);
1176 }
1172 1177
1173 // check /dev 1178 // check /dev
1174 if (asprintf(&name, "%s/dev", rootdir) == -1) 1179 if (asprintf(&name, "%s/dev", rootdir) == -1)
@@ -1177,8 +1182,8 @@ void fs_check_chroot_dir(const char *rootdir) {
1177 fprintf(stderr, "Error: cannot find /dev in chroot directory\n"); 1182 fprintf(stderr, "Error: cannot find /dev in chroot directory\n");
1178 exit(1); 1183 exit(1);
1179 } 1184 }
1180 if (s.st_uid != 0) { 1185 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) {
1181 fprintf(stderr, "Error: chroot /dev directory should be owned by root\n"); 1186 fprintf(stderr, "Error: chroot /dev should be a directory owned by root\n");
1182 exit(1); 1187 exit(1);
1183 } 1188 }
1184 free(name); 1189 free(name);
@@ -1190,8 +1195,8 @@ void fs_check_chroot_dir(const char *rootdir) {
1190 fprintf(stderr, "Error: cannot find /var/tmp in chroot directory\n"); 1195 fprintf(stderr, "Error: cannot find /var/tmp in chroot directory\n");
1191 exit(1); 1196 exit(1);
1192 } 1197 }
1193 if (s.st_uid != 0) { 1198 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) {
1194 fprintf(stderr, "Error: chroot /var/tmp directory should be owned by root\n"); 1199 fprintf(stderr, "Error: chroot /var/tmp should be a directory owned by root\n");
1195 exit(1); 1200 exit(1);
1196 } 1201 }
1197 free(name); 1202 free(name);
@@ -1203,8 +1208,8 @@ void fs_check_chroot_dir(const char *rootdir) {
1203 fprintf(stderr, "Error: cannot find /proc in chroot directory\n"); 1208 fprintf(stderr, "Error: cannot find /proc in chroot directory\n");
1204 exit(1); 1209 exit(1);
1205 } 1210 }
1206 if (s.st_uid != 0) { 1211 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) {
1207 fprintf(stderr, "Error: chroot /proc directory should be owned by root\n"); 1212 fprintf(stderr, "Error: chroot /proc should be a directory owned by root\n");
1208 exit(1); 1213 exit(1);
1209 } 1214 }
1210 free(name); 1215 free(name);
@@ -1216,8 +1221,8 @@ void fs_check_chroot_dir(const char *rootdir) {
1216 fprintf(stderr, "Error: cannot find /tmp in chroot directory\n"); 1221 fprintf(stderr, "Error: cannot find /tmp in chroot directory\n");
1217 exit(1); 1222 exit(1);
1218 } 1223 }
1219 if (s.st_uid != 0) { 1224 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) {
1220 fprintf(stderr, "Error: chroot /tmp directory should be owned by root\n"); 1225 fprintf(stderr, "Error: chroot /tmp should be a directory owned by root\n");
1221 exit(1); 1226 exit(1);
1222 } 1227 }
1223 free(name); 1228 free(name);
@@ -1229,8 +1234,12 @@ void fs_check_chroot_dir(const char *rootdir) {
1229 fprintf(stderr, "Error: cannot find /etc in chroot directory\n"); 1234 fprintf(stderr, "Error: cannot find /etc in chroot directory\n");
1230 exit(1); 1235 exit(1);
1231 } 1236 }
1232 if (s.st_uid != 0) { 1237 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) {
1233 fprintf(stderr, "Error: chroot /etc directory should be owned by root\n"); 1238 fprintf(stderr, "Error: chroot /etc should be a directory owned by root\n");
1239 exit(1);
1240 }
1241 if ((S_IWOTH & s.st_mode) != 0) {
1242 fprintf(stderr, "Error: chroot /etc is not allowed to be world-writable\n");
1234 exit(1); 1243 exit(1);
1235 } 1244 }
1236 free(name); 1245 free(name);
@@ -1272,8 +1281,8 @@ void fs_check_chroot_dir(const char *rootdir) {
1272 fprintf(stderr, "Error: cannot find /tmp/.X11-unix in chroot directory\n"); 1281 fprintf(stderr, "Error: cannot find /tmp/.X11-unix in chroot directory\n");
1273 exit(1); 1282 exit(1);
1274 } 1283 }
1275 if (s.st_uid != 0) { 1284 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) {
1276 fprintf(stderr, "Error: chroot /tmp/.X11-unix directory should be owned by root\n"); 1285 fprintf(stderr, "Error: chroot /tmp/.X11-unix should be a directory owned by root\n");
1277 exit(1); 1286 exit(1);
1278 } 1287 }
1279 free(name); 1288 free(name);
@@ -1308,16 +1317,29 @@ void fs_chroot(const char *rootdir) {
1308 1317
1309 // some older distros don't have a /run directory 1318 // some older distros don't have a /run directory
1310 // create one by default 1319 // create one by default
1311 // create /run/firejail directory in chroot
1312 char *rundir; 1320 char *rundir;
1313 if (asprintf(&rundir, "%s/run", rootdir) == -1) 1321 if (asprintf(&rundir, "%s/run", rootdir) == -1)
1314 errExit("asprintf"); 1322 errExit("asprintf");
1315 if (is_link(rundir)) { 1323 struct stat s;
1316 fprintf(stderr, "Error: invalid run directory inside chroot\n"); 1324 if (lstat(rundir, &s) == 0) {
1317 exit(1); 1325 if (S_ISLNK(s.st_mode)) {
1326 fprintf(stderr, "Error: chroot /run is a symbolic link\n");
1327 exit(1);
1328 }
1329 if (!S_ISDIR(s.st_mode) || s.st_uid != 0) {
1330 fprintf(stderr, "Error: chroot /run should be a directory owned by root\n");
1331 exit(1);
1332 }
1333 if ((S_IWOTH & s.st_mode) != 0) {
1334 fprintf(stderr, "Error: chroot /run is not allowed to be world-writable\n");
1335 exit(1);
1336 }
1318 } 1337 }
1319 create_empty_dir_as_root(rundir, 0755); 1338 else
1339 create_empty_dir_as_root(rundir, 0755);
1320 free(rundir); 1340 free(rundir);
1341
1342 // create /run/firejail directory in chroot
1321 if (asprintf(&rundir, "%s/run/firejail", rootdir) == -1) 1343 if (asprintf(&rundir, "%s/run/firejail", rootdir) == -1)
1322 errExit("asprintf"); 1344 errExit("asprintf");
1323 create_empty_dir_as_root(rundir, 0755); 1345 create_empty_dir_as_root(rundir, 0755);
@@ -1329,6 +1351,7 @@ void fs_chroot(const char *rootdir) {
1329 create_empty_dir_as_root(rundir, 0755); 1351 create_empty_dir_as_root(rundir, 0755);
1330 if (mount(RUN_MNT_DIR, rundir, NULL, MS_BIND|MS_REC, NULL) < 0) 1352 if (mount(RUN_MNT_DIR, rundir, NULL, MS_BIND|MS_REC, NULL) < 0)
1331 errExit("mount bind"); 1353 errExit("mount bind");
1354 free(rundir);
1332 1355
1333 // copy /etc/resolv.conf in chroot directory 1356 // copy /etc/resolv.conf in chroot directory
1334 char *fname; 1357 char *fname;
@@ -1339,6 +1362,7 @@ void fs_chroot(const char *rootdir) {
1339 unlink(fname); 1362 unlink(fname);
1340 if (copy_file("/etc/resolv.conf", fname, 0, 0, 0644) == -1) // root needed 1363 if (copy_file("/etc/resolv.conf", fname, 0, 0, 0644) == -1) // root needed
1341 fwarning("/etc/resolv.conf not initialized\n"); 1364 fwarning("/etc/resolv.conf not initialized\n");
1365 free(fname);
1342 1366
1343 // chroot into the new directory 1367 // chroot into the new directory
1344#ifdef HAVE_GCOV 1368#ifdef HAVE_GCOV
diff --git a/src/firejail/main.c b/src/firejail/main.c
index ba952b1cb..435c04d76 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -1502,7 +1502,7 @@ int main(int argc, char **argv) {
1502 1502
1503 // check chroot dirname exists 1503 // check chroot dirname exists
1504 if (strstr(cfg.chrootdir, "..") || !is_dir(cfg.chrootdir) || is_link(cfg.chrootdir)) { 1504 if (strstr(cfg.chrootdir, "..") || !is_dir(cfg.chrootdir) || is_link(cfg.chrootdir)) {
1505 fprintf(stderr, "Error: invalid directory %s\n", cfg.chrootdir); 1505 fprintf(stderr, "Error: invalid chroot directory %s\n", cfg.chrootdir);
1506 return 1; 1506 return 1;
1507 } 1507 }
1508 1508