summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2023-06-26 02:11:36 +0300
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-07-03 01:41:25 +0200
commitf214d0723240cbbe0f1ccb90af8d1b0bb095837f (patch)
treea8dc6f3b100c338028cda0cc56af429beca53be8
parent005212e56eb02f01ff732eaa44b360eb8e126d03 (diff)
exec: On 64-bit, map lower 4 GB inaccessible for PIEs
We want to map the whole lower 4 GB of address space inaccessible to catch accidental pointer truncation. We can only do this when the executable (as well as the interpreter, if any) is compiled as PIC/PIE, since otherwise we would violate the ABI requirement. Fortunately most distributions have already switched to using PIE by default, so this should not be an issue. Message-Id: <20230625231137.403096-3-bugaevc@gmail.com>
-rw-r--r--exec/exec.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/exec/exec.c b/exec/exec.c
index 2e5fbfcd..4415fa50 100644
--- a/exec/exec.c
+++ b/exec/exec.c
@@ -1263,8 +1263,21 @@ do_exec (file_t file,
/* Map page zero redzoned. */
{
vm_address_t addr = 0;
+ vm_size_t size = vm_page_size;
+
+#ifdef __LP64__
+ /* On 64-bit, map the entire lower 4 GB redzoned to catch pointer
+ truncation, but only if the program is fine with being loaded at an
+ arbitrary address -- otherwise we'd violate the assumption of the small
+ code model (-mcmodel=small, which is the default) that all symbols are
+ located in the lower 2 GB of the address space. */
+ if (e.info.elf.anywhere && (interp.file == MACH_PORT_NULL
+ || interp.info.elf.anywhere))
+ size = (vm_size_t) 1 << 32;
+#endif
+
e.error = vm_map (newtask,
- &addr, vm_page_size, 0, 0, MACH_PORT_NULL, 0, 1,
+ &addr, size, 0, 0, MACH_PORT_NULL, 0, 1,
VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY);
if (e.error)
goto out;