-
Notifications
You must be signed in to change notification settings - Fork 21
Honor GRATE_MEMORY_FLAG in mmap_syscall and brk_syscall #1185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 12 commits
afa13ba
1d2d47b
9dcdcb0
8b78e00
45ea1bb
7f1f583
ae73bd8
790917c
1d7004a
c4ba2a7
304f5a4
ef4846f
3829f3a
a11fad8
d1b9877
2368331
0192789
64e92c0
d2ec548
310c803
de012db
d64f844
f706ed6
619179d
7b65359
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,13 @@ pub const MAXFD: usize = 1024; // Maximum file descriptors per cage | |
| pub const MAX_LINEAR_MEMORY_SIZE: u64 = 0xFFFF_FFFF; | ||
| /// Placeholder for unused syscall argument | ||
| pub const UNUSED_ARG: u64 = 0xDEADBEEF_DEADBEEF; | ||
| /// MSB of a syscall arg's cageid: signals that the arg should be treated as a | ||
| /// host-side reference into the named cage's linear memory, not as a uaddr | ||
| /// in the calling cage's memory. Mirrors `LIND_ARG_TRANSLATE_FLAG` in | ||
| /// `src/glibc/lind_syscall/addr_translation.h`. | ||
| pub const GRATE_MEMORY_FLAG: u64 = 1u64 << 63; | ||
| /// Mask to recover the actual cageid by clearing `GRATE_MEMORY_FLAG`. | ||
| pub const LIND_ARG_CAGEID_MASK: u64 = !GRATE_MEMORY_FLAG; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be better to make a macro that uses this? |
||
| /// Placeholder for unused cage/grate ID | ||
| pub const UNUSED_ID: u64 = 0xCAFEBABE_CAFEBABE; | ||
| /// Placeholder for unused syscall name | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -260,6 +260,89 @@ pub fn sc_convert_to_u8_mut(arg: u64, arg_cageid: u64, cageid: u64) -> *mut u8 { | |
| arg as *mut u8 | ||
| } | ||
|
|
||
| /// Resolve a (uaddr, cageid) pair to a host system address, honoring | ||
| /// `GRATE_MEMORY_FLAG`. | ||
| /// | ||
| /// For path-style buffer args the runtime can just dereference the address as | ||
| /// a host pointer (see `get_cstr`) — bytes are bytes. For address args that | ||
| /// the runtime *interprets* rather than dereferences (mmap, munmap, mprotect, | ||
| /// brk, shmat, shmdt), we need the actual host system address. | ||
| /// | ||
| /// Distinguishes which form of address `arg` carries: | ||
| /// | ||
| /// - **u32 range (`arg <= u32::MAX`)**: a uaddr in the calling cage's linear | ||
| /// memory. This is what cage-side glibc wrappers (e.g. `mmap.c`'s | ||
| /// `(uintptr_t) addr`) pass — wasm32 uaddrs fit in u32. We translate via | ||
| /// the calling cage's vmmap base. | ||
| /// - **Above u32 range**: a host system address already, produced by glibc's | ||
| /// `TRANSLATE_ARG_TO_HOST` macro inside `make_threei_call` (e.g. when a | ||
| /// grate forwards with `GRATE_MEMORY_FLAG` set). By the time the runtime | ||
| /// sees the call, the FLAG bit has been stripped from `arg_cageid` and the | ||
| /// arg is the resolved host pointer. Use as-is. | ||
| /// | ||
| /// The ranges don't overlap: cage linear memory occupies `[base, base + 4GB]` | ||
| /// on the host, and host bases are typically far above 4GB. | ||
| /// | ||
| /// arg=0 is special-cased to "start of the calling cage's memory" — a NULL | ||
| /// host pointer would be meaningless. | ||
| /// | ||
| /// ## Returns | ||
| /// - `Ok(sysaddr)` host system address. | ||
| /// - `Err(Errno::EINVAL)` if the calling cage can't be looked up or its vmmap | ||
| /// has no base address yet (only on the uaddr branch). | ||
| pub fn sc_convert_addr_to_sys(arg: u64, arg_cageid: u64, cageid: u64) -> Result<usize, Errno> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we already have a |
||
| #[cfg(feature = "secure")] | ||
| { | ||
| if !validate_cageid(arg_cageid, cageid) { | ||
| return Err(Errno::EINVAL); | ||
| } | ||
| } | ||
| let _ = arg_cageid; // FLAG is consumed glibc-side; runtime distinguishes by value range. | ||
|
|
||
| // arg=0 has cage-relative "start of cage memory" meaning — a NULL host | ||
| // pointer would be meaningless. Anchor to the calling cage's base so | ||
| // early_init_stack-style mmaps (addr=0, MAP_FIXED) work. | ||
| if arg == 0 { | ||
| let cage = get_cage(cageid).ok_or(Errno::EINVAL)?; | ||
| let vmmap = cage.vmmap.read(); | ||
| let base = vmmap.base_address.ok_or(Errno::EINVAL)?; | ||
| return Ok(base); | ||
| } | ||
|
|
||
| // Distinguish uaddr (≤ u32::MAX) from host sysaddr (above). See doc above. | ||
| if arg <= u32::MAX as u64 { | ||
| let cage = get_cage(cageid).ok_or(Errno::EINVAL)?; | ||
| let vmmap = cage.vmmap.read(); | ||
| let base = vmmap.base_address.ok_or(Errno::EINVAL)?; | ||
| return Ok(base + arg as usize); | ||
| } | ||
|
|
||
| Ok(arg as usize) | ||
| } | ||
|
|
||
| /// Inverse of `sc_convert_addr_to_sys` — translate a host system address back | ||
| /// to a uaddr in the named cage's linear memory. Used for return values of | ||
| /// mmap-family syscalls and for bookkeeping into the cage's vmmap. | ||
| /// | ||
| /// ## Arguments | ||
| /// - `sysaddr`: the host system address. | ||
| /// - `cageid`: the cage whose user-address space we want. | ||
| /// | ||
| /// ## Returns | ||
| /// - `Ok(uaddr)` truncated to u32 (cage user addresses fit in 32 bits on | ||
| /// wasm32 lind). | ||
| /// - `Err(Errno::EINVAL)` if the cage can't be looked up, its vmmap has no | ||
| /// base, or `sysaddr` is below the cage's base. | ||
| pub fn sc_convert_sys_to_user(sysaddr: usize, cageid: u64) -> Result<u32, Errno> { | ||
| let cage = get_cage(cageid).ok_or(Errno::EINVAL)?; | ||
| let vmmap = cage.vmmap.read(); | ||
| let base = vmmap.base_address.ok_or(Errno::EINVAL)?; | ||
| if sysaddr < base { | ||
| return Err(Errno::EINVAL); | ||
| } | ||
| Ok((sysaddr - base) as u32) | ||
| } | ||
|
|
||
| /// This function translates the buffer pointer from user buffer address to system address, because we are | ||
| /// transferring between 32-bit WASM environment to 64-bit kernel | ||
| /// | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| /* Cage side of the mmap-with-GRATE_MEMORY_FLAG test. | ||
| * | ||
| * fd-backed mmap → write → read → munmap round-trip. The companion | ||
| * grate forwards this call to RawPOSIX with `arg1cage | GRATE_MEMORY_FLAG`, | ||
| * exercising the runtime's flag-aware path in mmap_syscall. | ||
| * | ||
| * Anonymous mmaps (including the runtime's own pre-main stack setup) | ||
| * are forwarded by the grate without the flag and aren't exercised here. | ||
| */ | ||
|
|
||
| #include <fcntl.h> | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
| #include <sys/mman.h> | ||
| #include <unistd.h> | ||
|
|
||
| #define FILE_PATH "mmap-flag.tmp" | ||
|
|
||
| int main(void) { | ||
| const size_t size = 4096; | ||
|
|
||
| int fd = open(FILE_PATH, O_RDWR | O_CREAT | O_TRUNC, 0666); | ||
| if (fd < 0) { | ||
| return 1; | ||
| } | ||
| if (ftruncate(fd, size) != 0) { | ||
| return 1; | ||
| } | ||
|
|
||
| void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); | ||
| if (p == MAP_FAILED) { | ||
| return 1; | ||
| } | ||
|
|
||
| memset(p, 0x42, size); | ||
| for (size_t i = 0; i < size; i++) { | ||
| if (((unsigned char *)p)[i] != 0x42) { | ||
| return 1; | ||
| } | ||
| } | ||
|
|
||
| if (munmap(p, size) != 0) { | ||
| return 1; | ||
| } | ||
|
|
||
| close(fd); | ||
| unlink(FILE_PATH); | ||
|
|
||
| printf("[Cage|mmap-flag] PASS\n"); | ||
| return 0; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand this. Need to discuss