Skip to content
Open
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
4 changes: 1 addition & 3 deletions docs/internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -593,9 +593,7 @@ correctly. `elf_resolve_interp()` in `src/core/elf.c` is shared between

### Known Limitations

- `timeout` fails: it uses `fork`/`clone` to create a child process with a
timer, and the forked child inherits the dynamic-linker state but the
fork+exec path has issues in interpreter space.
None currently tracked for the aarch64-linux dynamic-linker path.

## GDB Stub

Expand Down
29 changes: 23 additions & 6 deletions src/core/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,30 @@ int elf_map_segments(const elf_info_t *info,
return -1;
}

/* The host memset zeros PAGE_ALIGN_UP(memsz) bytes, not just memsz,
* so the infra-overlap check has to use the same rounded extent.
* Without the rounding here, a segment that ends just below
* infra_lo passes the check and still spills up to PAGE_SIZE-1
* bytes of zero into the infra reserve via the page tail.
/* PT_LOAD with memsz == 0 maps no bytes, but the page-tail zero
* extent below still rounds up to the next page boundary. For an
* unaligned gpa that means a crafted ELF could splat zeros across
* the tail of a previously loaded segment in the same page, or
* trip the infra-overlap check with no live mapping behind it.
* Linux ignores zero-memsz PT_LOADs; mirror that here.
*/
uint64_t zero_len = PAGE_ALIGN_UP(memsz);
if (memsz == 0) {
seg_idx++;
continue;
}

/* The host memset zeros up to the next page boundary AFTER the
* segment ends, so the infra-overlap check has to use the same
* rounded extent. The end is PAGE_ALIGN_UP(gpa + memsz) rather
* than gpa + PAGE_ALIGN_UP(memsz) because gpa is not always
* page-aligned (e.g. ld.so's RW segment at vaddr 0x2f650): with
* the older bytes-from-gpa formula the page covering the last
* memsz byte kept its mid-page tail untouched, and execve into a
* dynamic-linked target then read stale state from the prior
* incarnation of the same interpreter at offsets ld.so allocates
* from beyond memsz (e.g. the first link_map in _dl_new_object).
*/
uint64_t zero_len = PAGE_ALIGN_UP(gpa + memsz) - gpa;
if (gpa + zero_len > guest_size)
zero_len = guest_size - gpa;
if (infra_active && gpa < infra_hi && gpa + zero_len > infra_lo) {
Expand Down
14 changes: 14 additions & 0 deletions src/syscall/fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -1488,6 +1488,20 @@ bool fuse_path_matches_mount(const char *path)
return matched;
}

int fuse_path_mount_id(const char *path)
{
if (!path || path[0] != '/')
return -1;
char canon[LINUX_PATH_MAX];
if (fuse_canonical_abs(path, canon, sizeof(canon)) < 0)
return -1;
pthread_mutex_lock(&fuse_lock);
fuse_mount_t *m = fuse_mount_for_path_locked(canon, NULL);
int id = m ? m->mount_id : -1;
pthread_mutex_unlock(&fuse_lock);
return id;
}

/* Resolve a guest-absolute path to a (session, mount_id, nodeid, attr).
* retain_final_lookup controls whether the terminal LOOKUP's nlookup is kept
* alive for a later open/release cycle, or forgotten before return for
Expand Down
5 changes: 5 additions & 0 deletions src/syscall/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ int fuse_proc_stat(struct stat *st);

int64_t fuse_open_path(guest_t *g, const char *path, int linux_flags, int mode);
bool fuse_path_matches_mount(const char *path);
/* Returns the mount_id of the FUSE mount containing path, or -1 if path is
* not inside any live or tombstoned FUSE mount. Distinct FUSE mounts have
* distinct mount_ids; used by RESOLVE_NO_XDEV to detect cross-mount paths.
*/
int fuse_path_mount_id(const char *path);
/* Stat a FUSE-mounted path. at_flags carries the Linux AT_* mask from the
* caller; only LINUX_AT_SYMLINK_NOFOLLOW is consulted today. When the
* daemon returns S_IFLNK for the final component and the caller did not
Expand Down
Loading
Loading