about summary refs log tree commit diff
path: root/library/std/src/sys
diff options
context:
space:
mode:
authorTheodore Cipicchio <okready@users.noreply.github.com>2020-09-04 09:34:11 -0700
committerTheodore Cipicchio <okready@users.noreply.github.com>2020-09-04 13:58:59 -0700
commitc989de52b8ad76439f6178170d94ead64ee3ffc7 (patch)
treec8d80a2b0f3c718b0311fee018404ad459160845 /library/std/src/sys
parentd2454643e137bde519786ee9e650c455d7ad6f34 (diff)
downloadrust-c989de52b8ad76439f6178170d94ead64ee3ffc7.tar.gz
rust-c989de52b8ad76439f6178170d94ead64ee3ffc7.zip
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.
Diffstat (limited to 'library/std/src/sys')
-rw-r--r--library/std/src/sys/sgx/abi/mem.rs42
1 files changed, 34 insertions, 8 deletions
diff --git a/library/std/src/sys/sgx/abi/mem.rs b/library/std/src/sys/sgx/abi/mem.rs
index 57fd7efdd49..09f5a4fb760 100644
--- a/library/std/src/sys/sgx/abi/mem.rs
+++ b/library/std/src/sys/sgx/abi/mem.rs
@@ -28,20 +28,46 @@ pub fn image_base() -> u64 {
 
 /// Returns `true` if the specified memory range is in the enclave.
 ///
-/// `p + len` must not overflow.
+/// For safety, this function also checks whether the range given overflows,
+/// returning `false` if so.
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn is_enclave_range(p: *const u8, len: usize) -> bool {
-    let start = p as u64;
-    let end = start + (len as u64);
-    start >= image_base() && end <= image_base() + (unsafe { ENCLAVE_SIZE } as u64) // unsafe ok: link-time constant
+    let start = p as usize;
+
+    // Subtract one from `len` when calculating `end` in case `p + len` is
+    // exactly at the end of addressable memory (`p + len` would overflow, but
+    // the range is still valid).
+    let end = if len == 0 {
+        start
+    } else if let Some(end) = start.checked_add(len - 1) {
+        end
+    } else {
+        return false;
+    };
+
+    let base = image_base() as usize;
+    start >= base && end <= base + (unsafe { ENCLAVE_SIZE } - 1) // unsafe ok: link-time constant
 }
 
 /// Returns `true` if the specified memory range is in userspace.
 ///
-/// `p + len` must not overflow.
+/// For safety, this function also checks whether the range given overflows,
+/// returning `false` if so.
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn is_user_range(p: *const u8, len: usize) -> bool {
-    let start = p as u64;
-    let end = start + (len as u64);
-    end <= image_base() || start >= image_base() + (unsafe { ENCLAVE_SIZE } as u64) // unsafe ok: link-time constant
+    let start = p as usize;
+
+    // Subtract one from `len` when calculating `end` in case `p + len` is
+    // exactly at the end of addressable memory (`p + len` would overflow, but
+    // the range is still valid).
+    let end = if len == 0 {
+        start
+    } else if let Some(end) = start.checked_add(len - 1) {
+        end
+    } else {
+        return false;
+    };
+
+    let base = image_base() as usize;
+    end < base || start > base + (unsafe { ENCLAVE_SIZE } - 1) // unsafe ok: link-time constant
 }