-
Notifications
You must be signed in to change notification settings - Fork 18
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 23 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 |
|---|---|---|
| @@ -1,7 +1,6 @@ | ||
| use crate::threei_const; | ||
| use std::collections::{hash_map::Entry, HashMap}; | ||
| use std::collections::HashMap; | ||
| use std::sync::Mutex; | ||
| use sysdefs::constants::lind_platform_const; | ||
|
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. Is this linter cleanup? |
||
|
|
||
| /// HANDLERTABLE: | ||
| /// A nested hash map used to define fine-grained per-syscall interposition rules. | ||
|
|
@@ -73,7 +72,7 @@ pub fn _check_cage_handler_exists(cageid: u64) -> bool { | |
| /// ## Panics: | ||
| /// - If no entry exists for `self_cageid`. | ||
| /// - If no entry exists for `syscall_num`. | ||
| pub fn _get_handler(self_cageid: u64, syscall_num: u64, target_cageid: u64) -> Option<(u64, u64)> { | ||
| pub fn _get_handler(self_cageid: u64, syscall_num: u64, _target_cageid: u64) -> Option<(u64, u64)> { | ||
|
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. Are you making the linter happy, or...?
Contributor
Author
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. yeah |
||
| let handler_table = HANDLERTABLE.lock().unwrap(); | ||
|
|
||
| let call_map = handler_table.get(&self_cageid).unwrap_or_else(|| { | ||
|
|
@@ -109,8 +108,8 @@ pub fn _get_handler(self_cageid: u64, syscall_num: u64, target_cageid: u64) -> O | |
| /// todo: a more efficient way to do clean up | ||
| pub fn _rm_grate_from_handler(grateid: u64) { | ||
| let mut table = HANDLERTABLE.lock().unwrap(); | ||
| for (_, callmap) in table.iter_mut() { | ||
| for (_, target_map) in callmap.iter_mut() { | ||
| for (_self_cageid, callmap) in table.iter_mut() { | ||
| for (_callnum, target_map) in callmap.iter_mut() { | ||
| target_map.retain(|dest_grateid, _| *dest_grateid != grateid); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -260,6 +260,29 @@ pub fn sc_convert_to_u8_mut(arg: u64, arg_cageid: u64, cageid: u64) -> *mut u8 { | |
| arg as *mut u8 | ||
| } | ||
|
|
||
| /// Inverse of `sc_convert_uaddr_to_host` — 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_host_to_uaddr(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 | ||
| /// | ||
|
|
@@ -273,15 +296,22 @@ pub fn sc_convert_buf(buf_arg: u64, _arg_cageid: u64, _cageid: u64) -> *const u8 | |
| buf_arg as *const u8 | ||
| } | ||
|
|
||
| // TODO: This function can be removed/revamped significantly | ||
| // Leaving it in for now since it is used threei/ | ||
| /// ## Arguments: | ||
| /// - `uaddr`: The user address to convert (u64). | ||
| /// - `addr_cageid`: The cage ID associated with the address. | ||
| /// - `cageid`: The calling cage ID (used for validation in secure mode). | ||
| /// Resolve a `(uaddr, addr_cageid)` syscall arg to a host system address. | ||
| /// | ||
| /// ## Returns: | ||
| /// - The host address as u64, or 0 if the address is null. | ||
| /// Robust to either input form, distinguished by comparing against the named | ||
| /// cage's base: | ||
| /// | ||
| /// - `uaddr < base_addr`: a cage-relative address in `addr_cageid`'s linear | ||
| /// memory. Translate by adding the base. `uaddr == 0` falls in this branch | ||
| /// and resolves to the cage's base — that's what `early_init_stack`-style | ||
| /// `MAP_FIXED at 0` mmaps need. | ||
| /// - `uaddr >= base_addr`: a pre-translated host pointer (e.g. glibc's | ||
| /// `TRANSLATE_*_TO_HOST` already ran inside a grate-forwarded call with | ||
| /// `GRATE_MEMORY_FLAG` set). Pass through unchanged. | ||
| /// | ||
| /// `addr_cageid` picks the right cage's base: for a cage-userland call it's | ||
| /// the calling cage; for a grate-forwarded call (FLAG stripped by glibc) it's | ||
| /// the grate's id, which is what produced the host pointer in the first place. | ||
| pub fn sc_convert_uaddr_to_host(uaddr: u64, addr_cageid: u64, _cageid: u64) -> u64 { | ||
| #[cfg(feature = "secure")] | ||
| { | ||
|
|
@@ -290,21 +320,14 @@ pub fn sc_convert_uaddr_to_host(uaddr: u64, addr_cageid: u64, _cageid: u64) -> u | |
| } | ||
| } | ||
|
|
||
| // Do not convert on NULL. | ||
| if uaddr == 0 { | ||
| return uaddr; | ||
| } | ||
|
|
||
| let cage = get_cage(addr_cageid).unwrap(); | ||
| let vmmap = cage.vmmap.read(); | ||
| let base_addr = vmmap.base_address.unwrap() as u64; | ||
|
|
||
| // Only convert to host if not already converted. | ||
| if uaddr >= base_addr { | ||
|
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. I think this should check if the top bits match the base_addr, not this. In practice, you should have a helper function for this to handle situations where we do not have 32 bit aligned 4GB regions. |
||
| panic!( | ||
| "sc_convert_uaddr_to_host: invalid uaddr {:#x} - expected a cage-relative address", | ||
| uaddr | ||
| ); | ||
| // Already a host pointer — caller (e.g. glibc's TRANSLATE_*_TO_HOST) | ||
| // resolved it. Pass through. | ||
| return uaddr; | ||
| } | ||
|
|
||
| uaddr + base_addr | ||
|
|
||
| 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