Bug
shmat_syscall misinterprets any attached user address ≥ 0x80000000 as an error, silently returning a bogus value and skipping the vmmap entry registration.
Root Cause
|
let result = vmmap.sys_to_user(result); |
|
drop(vmmap); |
|
|
|
// If the syscall succeeded, update the vmmap entry. |
|
if result as i32 >= 0 { |
|
// Ensure the syscall attached the segment at the expected address. |
|
if result as u32 != useraddr { |
|
panic!("shmat did not attach at the expected address"); |
|
} |
|
let mut vmmap = cage.vmmap.write(); |
|
let backing = MemoryBackingType::SharedMemory(shmid as u64); |
|
// Use the effective protection (prot) for both the current and maximum protection. |
|
let maxprot = prot; |
|
// Add a new vmmap entry for the shared memory segment. |
|
// Since shared memory is not file-backed, there are no extra mapping flags |
|
// or file offset parameters to consider; thus, we pass 0 for both. |
|
vmmap |
|
.add_entry_with_overwrite( |
|
useraddr >> PAGESHIFT, |
|
(rounded_length >> PAGESHIFT) as u32, |
|
prot, |
|
maxprot, |
|
0, // No flags for shared memory mapping |
|
backing, |
|
0, // Offset is not applicable for shared memory |
|
len as i64, |
|
cageid, |
|
) |
|
.expect("shmat: failed to add vmmap entry"); |
|
} else { |
|
// If the syscall failed, propagate the error. |
|
return result as i32; |
- sys_to_user returns a full u32 wasm address (src/cage/src/memory/vmmap.rs:348).
- result as i32 >= 0 is false for any user address with the top bit set (≥ 0x80000000).
- The else branch returns the u32 as a negative i32, which glibc's shmat wrapper reinterprets as a pointer, so callers see a seemingly-valid return.
Bug
shmat_syscall misinterprets any attached user address ≥ 0x80000000 as an error, silently returning a bogus value and skipping the vmmap entry registration.
Root Cause
lind-wasm/src/rawposix/src/fs_calls.rs
Lines 4291 to 4322 in 1b1f6ed