Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
16 changes: 14 additions & 2 deletions src/syscall/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -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")) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path_might_use_open_intercept() only checks that a sysroot is configured
(proc_sysroot_snapshot()), not that the sysroot actually contains
/etc/passwd / /etc/group. When it doesn't, the request falls through to
proc_resolve_sysroot_path_flags()'s host-literal fallback, which resolves
the literal host path — on macOS that's the real /etc/passwd /
/etc/group on the machine running elfuse.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix Details

  1. Added Existence Checks: Updated path_might_use_open_intercept in path.c to perform a stat existence check on the guest sysroot-resolved files (${sysroot}/etc/passwd / ${sysroot}/etc/group). The synthetic intercept is bypassed only when the file is present in the sysroot.
  2. Updated Test Harness: Modified tests.mk to only stage passwd in the fallback test's guest sysroot, leaving group absent.
  3. Added Assertions: Updated test-sysroot-host-fallback.c to verify that the absent guest group file falls back to the synthetic group intercept instead of resolving to the host machine's /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;

Expand Down
16 changes: 16 additions & 0 deletions tests/test-sysroot-host-fallback.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Loading