Skip to content

Commit c989de5

Browse files
committed
Add is_enclave_range/is_user_range overflow checks
Functions such as `is_enclave_range` and `is_user_range` in `sgx::os::fortanix_sgx::mem` are often used to make sure memory ranges passed to an enclave from untrusted code or passed to other trusted code functions are safe to use for their intended purpose. Currently, these functions do not perform any checks to make sure the range provided doesn't overflow when adding the range length to the base address. While debug builds will panic if overflow occurs, release builds will simply wrap the result, leading to false positive results for either function. The burden is placed on application authors to know to perform overflow checks on their own before calling these functions, which can easily lead to security vulnerabilities if omitted. Additionally, since such checks are performed in the Intel SGX SDK versions of these functions, developers migrating from Intel SGX SDK code may expect these functions to operate the same. This commit adds explicit overflow checking to `is_enclave_range` and `is_user_range`, returning `false` if overflow occurs in order to prevent misuse of invalid memory ranges. It also alters the checks to account for ranges that lie exactly at the end of the address space, where calculating `p + len` would overflow despite the range being valid.
1 parent d245464 commit c989de5

File tree

1 file changed

+34
-8
lines changed
  • library/std/src/sys/sgx/abi

1 file changed

+34
-8
lines changed

library/std/src/sys/sgx/abi/mem.rs

+34-8
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,46 @@ pub fn image_base() -> u64 {
2828

2929
/// Returns `true` if the specified memory range is in the enclave.
3030
///
31-
/// `p + len` must not overflow.
31+
/// For safety, this function also checks whether the range given overflows,
32+
/// returning `false` if so.
3233
#[unstable(feature = "sgx_platform", issue = "56975")]
3334
pub fn is_enclave_range(p: *const u8, len: usize) -> bool {
34-
let start = p as u64;
35-
let end = start + (len as u64);
36-
start >= image_base() && end <= image_base() + (unsafe { ENCLAVE_SIZE } as u64) // unsafe ok: link-time constant
35+
let start = p as usize;
36+
37+
// Subtract one from `len` when calculating `end` in case `p + len` is
38+
// exactly at the end of addressable memory (`p + len` would overflow, but
39+
// the range is still valid).
40+
let end = if len == 0 {
41+
start
42+
} else if let Some(end) = start.checked_add(len - 1) {
43+
end
44+
} else {
45+
return false;
46+
};
47+
48+
let base = image_base() as usize;
49+
start >= base && end <= base + (unsafe { ENCLAVE_SIZE } - 1) // unsafe ok: link-time constant
3750
}
3851

3952
/// Returns `true` if the specified memory range is in userspace.
4053
///
41-
/// `p + len` must not overflow.
54+
/// For safety, this function also checks whether the range given overflows,
55+
/// returning `false` if so.
4256
#[unstable(feature = "sgx_platform", issue = "56975")]
4357
pub fn is_user_range(p: *const u8, len: usize) -> bool {
44-
let start = p as u64;
45-
let end = start + (len as u64);
46-
end <= image_base() || start >= image_base() + (unsafe { ENCLAVE_SIZE } as u64) // unsafe ok: link-time constant
58+
let start = p as usize;
59+
60+
// Subtract one from `len` when calculating `end` in case `p + len` is
61+
// exactly at the end of addressable memory (`p + len` would overflow, but
62+
// the range is still valid).
63+
let end = if len == 0 {
64+
start
65+
} else if let Some(end) = start.checked_add(len - 1) {
66+
end
67+
} else {
68+
return false;
69+
};
70+
71+
let base = image_base() as usize;
72+
end < base || start > base + (unsafe { ENCLAVE_SIZE } - 1) // unsafe ok: link-time constant
4773
}

0 commit comments

Comments
 (0)