diff --git a/mk/tests.mk b/mk/tests.mk index 85c3e456..5f07a44c 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -257,6 +257,8 @@ test-sysroot-host-fallback: $(ELFUSE_BIN) $(BUILD_DIR)/test-sysroot-host-fallbac printf 'host-final\n' > "$$mirror/final.txt"; \ printf 'host-loses\n' > "$$mirror/both.txt"; \ printf 'sysroot-wins\n' > "$$sysroot$$mirror/both.txt"; \ + mkdir -p "$$sysroot/etc"; \ + printf 'guest-passwd\n' > "$$sysroot/etc/passwd"; \ $(ELFUSE_BIN) --sysroot "$$sysroot" \ $(BUILD_DIR)/test-sysroot-host-fallback \ "$$hostdir" "$$mirror/final.txt" "$$mirror/both.txt" diff --git a/src/syscall/path.c b/src/syscall/path.c index 2888a023..46a7053a 100644 --- a/src/syscall/path.c +++ b/src/syscall/path.c @@ -56,9 +56,21 @@ bool path_might_use_open_intercept(const char *path) return true; if (path_prefix_match(path, SYSFS_CPU_PREFIX, sizeof(SYSFS_CPU_PREFIX) - 1)) return true; - if (!strcmp(path, "/etc/mtab") || !strcmp(path, "/etc/passwd") || - !strcmp(path, "/etc/group")) + if (!strcmp(path, "/etc/mtab")) return true; + if (!strcmp(path, "/etc/passwd") || !strcmp(path, "/etc/group")) { + char sr[LINUX_PATH_MAX]; + if (proc_sysroot_snapshot(sr, sizeof(sr))) { + char sysroot_file[LINUX_PATH_MAX]; + if (snprintf(sysroot_file, sizeof(sysroot_file), "%s%s", sr, path) < + (int) sizeof(sysroot_file)) { + struct stat st; + if (stat(sysroot_file, &st) == 0) + return false; + } + } + return true; + } if (!strcmp(path, "/var/run/utmp") || !strcmp(path, "/run/utmp")) return true; diff --git a/tests/test-sysroot-host-fallback.c b/tests/test-sysroot-host-fallback.c index 3f4119cb..27c6d0cd 100644 --- a/tests/test-sysroot-host-fallback.c +++ b/tests/test-sysroot-host-fallback.c @@ -133,6 +133,22 @@ int main(int argc, char **argv) else PASS(); + TEST("sysroot passwd file wins over synthetic intercept"); + if (read_file_nul("/etc/passwd", buf, sizeof(buf)) <= 0) + FAIL("read /etc/passwd failed"); + else if (strcmp(buf, "guest-passwd\n")) + FAIL("did not bypass /etc/passwd synthetic intercept"); + else + PASS(); + + TEST("absent sysroot group file falls back to synthetic intercept"); + if (read_file_nul("/etc/group", buf, sizeof(buf)) <= 0) + FAIL("read /etc/group failed"); + else if (strncmp(buf, "root:x:0:\nstaff:x:20:\nuser:x:1000:\n", 32)) + FAIL("did not fall back to synthetic group intercept"); + else + PASS(); + SUMMARY("test-sysroot-host-fallback"); return fails > 0 ? 1 : 0; }