From f1fd55d06bc3660a784d0af5af9b3e2459184c04 Mon Sep 17 00:00:00 2001 From: Trung Date: Fri, 17 Jul 2026 12:25:42 +0700 Subject: [PATCH] sysroot bypass hardcoded /etc/passwd and /etc/group intercepts When a custom guest sysroot is configured, hardcoded intercepts on /etc/passwd and /etc/group shadow the actual files in the guest rootfs. This prevents guest processes from resolving users and groups that were added during package provisioning. We now check if a sysroot is active in path_might_use_open_intercept() and bypass the synthetic intercepts in that case, allowing the guest to read the actual user/group database from its rootfs. Fix #188 --- mk/tests.mk | 2 ++ src/syscall/path.c | 16 ++++++++++++++-- tests/test-sysroot-host-fallback.c | 16 ++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) 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; }