Page MenuHomeFreeBSD

D35349.id106731.diff
No OneTemporary

D35349.id106731.diff

Index: sys/kern/imgact_elf.c
===================================================================
--- sys/kern/imgact_elf.c
+++ sys/kern/imgact_elf.c
@@ -209,6 +209,12 @@
__XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE))
": enable stack address randomization");
+static int __elfN(aslr_shared_page) = __ELF_WORD_SIZE == 64;
+SYSCTL_INT(ASLR_NODE_OID, OID_AUTO, shared_page, CTLFLAG_RWTUN,
+ &__elfN(aslr_shared_page), 0,
+ __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE))
+ ": enable shared page address randomization");
+
static int __elfN(sigfastblock) = 1;
SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO, sigfastblock,
CTLFLAG_RWTUN, &__elfN(sigfastblock), 0,
@@ -1305,6 +1311,8 @@
imgp->map_flags |= MAP_ASLR_IGNSTART;
if (__elfN(aslr_stack))
imgp->map_flags |= MAP_ASLR_STACK;
+ if (__elfN(aslr_shared_page))
+ imgp->imgp_flags |= IMGP_ASLR_SHARED_PAGE;
}
if ((!__elfN(allow_wx) && (fctl0 & NT_FREEBSD_FCTL_WXNEEDED) == 0 &&
Index: sys/kern/kern_exec.c
===================================================================
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -1110,8 +1110,7 @@
}
/*
- * Run down the current address space and install a new one. Map the shared
- * page.
+ * Run down the current address space and install a new one.
*/
int
exec_new_vmspace(struct image_params *imgp, struct sysentvec *sv)
@@ -1120,7 +1119,6 @@
struct proc *p = imgp->proc;
struct vmspace *vmspace = p->p_vmspace;
struct thread *td = curthread;
- vm_object_t obj;
vm_offset_t sv_minuser;
vm_map_t map;
@@ -1168,27 +1166,12 @@
}
map->flags |= imgp->map_flags;
- /* Map a shared page */
- obj = sv->sv_shared_page_obj;
- if (obj != NULL) {
- vm_object_reference(obj);
- error = vm_map_fixed(map, obj, 0,
- sv->sv_shared_page_base, sv->sv_shared_page_len,
- VM_PROT_READ | VM_PROT_EXECUTE,
- VM_PROT_READ | VM_PROT_EXECUTE,
- MAP_INHERIT_SHARE | MAP_ACC_NO_CHARGE);
- if (error != KERN_SUCCESS) {
- vm_object_deallocate(obj);
- return (vm_mmap_to_errno(error));
- }
- vmspace->vm_shp_base = sv->sv_shared_page_base;
- }
-
return (sv->sv_onexec != NULL ? sv->sv_onexec(p, imgp) : 0);
}
/*
* Compute the stack size limit and map the main process stack.
+ * Map the shared page.
*/
int
exec_map_stack(struct image_params *imgp)
@@ -1199,9 +1182,11 @@
vm_map_t map;
struct vmspace *vmspace;
vm_offset_t stack_addr, stack_top;
+ vm_offset_t sharedpage_addr;
u_long ssiz;
int error, find_space, stack_off;
vm_prot_t stack_prot;
+ vm_object_t obj;
p = imgp->proc;
sv = p->p_sysent;
@@ -1253,6 +1238,57 @@
stack_top -= rounddown2(stack_off & PAGE_MASK, sizeof(void *));
}
+ /* Map a shared page */
+ obj = sv->sv_shared_page_obj;
+ if (obj == NULL) {
+ sharedpage_addr = 0;
+ goto out;
+ }
+
+ sharedpage_addr = sv->sv_shared_page_base;
+ /*
+ * If randomization is disabled the vm logic maps it exactly
+ * to the specific address (VMFS_NO_SPACE).
+ * Otherwise it can choose any address above .data section.
+ * Same logic is used for stack address randomization.
+ * If the address randomization is applied map a guard page
+ * to the usual location of the shared page.
+ */
+ if ((imgp->imgp_flags & IMGP_ASLR_SHARED_PAGE) != 0) {
+ error = vm_map_find(map, NULL, 0,
+ &sharedpage_addr, sv->sv_shared_page_len,
+ sv->sv_maxuser, VMFS_NO_SPACE,
+ VM_PROT_NONE, VM_PROT_NONE, MAP_CREATE_GUARD);
+ if (error != KERN_SUCCESS) {
+ /*
+ * This is not fatal, so let's just print a warning
+ * and continue.
+ */
+ uprintf("%s: Mapping guard page at the usual location"
+ "of the shared page mach error %d errno %d",
+ __func__, error, vm_mmap_to_errno(error));
+ }
+ sharedpage_addr = round_page((vm_offset_t)p->p_vmspace->vm_daddr +
+ lim_max(curthread, RLIMIT_DATA));
+ find_space = VMFS_ANY_SPACE;
+ } else {
+ find_space = VMFS_NO_SPACE;
+ }
+ vm_object_reference(obj);
+ error = vm_map_find(map, obj, 0,
+ &sharedpage_addr, sv->sv_shared_page_len,
+ sv->sv_maxuser, find_space,
+ VM_PROT_READ | VM_PROT_EXECUTE,
+ VM_PROT_READ | VM_PROT_EXECUTE,
+ MAP_INHERIT_SHARE | MAP_ACC_NO_CHARGE);
+ if (error != KERN_SUCCESS) {
+ uprintf("%s: mapping shared page at addr: %p"
+ "failed, mach error %d errno %d\n", __func__,
+ (void *)sharedpage_addr, error, vm_mmap_to_errno(error));
+ vm_object_deallocate(obj);
+ return (vm_mmap_to_errno(error));
+ }
+out:
/*
* vm_ssize and vm_maxsaddr are somewhat antiquated concepts, but they
* are still used to enforce the stack rlimit on the process stack.
@@ -1260,6 +1296,7 @@
vmspace->vm_maxsaddr = (char *)stack_addr;
vmspace->vm_stacktop = stack_top;
vmspace->vm_ssize = sgrowsiz >> PAGE_SHIFT;
+ vmspace->vm_shp_base = sharedpage_addr;
return (0);
}
Index: sys/kern/kern_proc.c
===================================================================
--- sys/kern/kern_proc.c
+++ sys/kern/kern_proc.c
@@ -3245,6 +3245,9 @@
kvm.kvm_map_flags |= KMAP_FLAG_WXORX;
if ((vmspace->vm_map.flags & MAP_ASLR_STACK) != 0)
kvm.kvm_map_flags |= KMAP_FLAG_ASLR_STACK;
+ if (vmspace->vm_shp_base != p->p_sysent->sv_shared_page_base &&
+ PROC_HAS_SHP(p))
+ kvm.kvm_map_flags |= KMAP_FLAG_ASLR_SHARED_PAGE;
#ifdef COMPAT_FREEBSD32
if (SV_CURPROC_FLAG(SV_ILP32)) {
Index: sys/sys/imgact.h
===================================================================
--- sys/sys/imgact.h
+++ sys/sys/imgact.h
@@ -92,6 +92,8 @@
bool opened; /* we have opened executable vnode */
bool textset;
u_int map_flags;
+#define IMGP_ASLR_SHARED_PAGE 0x1
+ uint32_t imgp_flags;
};
#ifdef _KERNEL
Index: sys/sys/user.h
===================================================================
--- sys/sys/user.h
+++ sys/sys/user.h
@@ -625,6 +625,7 @@
#define KMAP_FLAG_ASLR_IGNSTART 0x04 /* ASLR may map into sbrk grow region */
#define KMAP_FLAG_WXORX 0x08 /* W^X mapping policy is enforced */
#define KMAP_FLAG_ASLR_STACK 0x10 /* the stack location is randomized */
+#define KMAP_FLAG_ASLR_SHARED_PAGE 0x20 /* the shared page location is randomized */
struct kinfo_vm_layout {
uintptr_t kvm_min_user_addr;
Index: tests/sys/kern/Makefile
===================================================================
--- tests/sys/kern/Makefile
+++ tests/sys/kern/Makefile
@@ -15,7 +15,6 @@
# No support for atomic_load_64 on i386 or (32-bit) powerpc
ATF_TESTS_C+= kcov
.endif
-ATF_TESTS_C+= kern_copyin
ATF_TESTS_C+= kern_descrip_test
ATF_TESTS_C+= fdgrowtable_test
ATF_TESTS_C+= kill_zombie
Index: tests/sys/kern/kern_copyin.c
===================================================================
--- tests/sys/kern/kern_copyin.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*-
- * Copyright (c) 2015, 2020 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
- * under sponsorship from the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/exec.h>
-#include <sys/sysctl.h>
-#include <sys/user.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <atf-c.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <machine/vmparam.h>
-
-static int scratch_file;
-
-static int
-copyin_checker(uintptr_t uaddr, size_t len)
-{
- ssize_t ret;
-
- ret = write(scratch_file, (const void *)uaddr, len);
- return (ret == -1 ? errno : 0);
-}
-
-#if __SIZEOF_POINTER__ == 8
-/*
- * A slightly more direct path to calling copyin(), but without the ability
- * to specify a length.
- */
-static int
-copyin_checker2(uintptr_t uaddr)
-{
- int ret;
-
- ret = fcntl(scratch_file, F_GETLK, (const void *)uaddr);
- return (ret == -1 ? errno : 0);
-}
-#endif
-
-#ifdef __amd64__
-static uintptr_t
-get_maxuser_address(void)
-{
- struct kinfo_vm_layout kvm;
- size_t len;
- int error, mib[4];
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_VM_LAYOUT;
- mib[3] = getpid();
- len = sizeof(kvm);
- error = sysctl(mib, nitems(mib), &kvm, &len, NULL, 0);
- if (error != 0)
- return (0);
-
- return (kvm.kvm_max_user_addr);
-}
-#endif
-
-#define FMAX ULONG_MAX
-#if __SIZEOF_POINTER__ == 8
-/* PR 257193 */
-#define ADDR_SIGNED 0x800000c000000000
-#endif
-
-ATF_TC_WITHOUT_HEAD(kern_copyin);
-ATF_TC_BODY(kern_copyin, tc)
-{
- char template[] = "copyin.XXXXXX";
- uintptr_t maxuser;
-
-#if defined(__mips__)
- /*
- * MIPS has different VM layout: the UVA map on mips ends the
- * highest mapped entry at the VM_MAXUSER_ADDRESS - PAGE_SIZE,
- * while all other arches map either stack or shared page up
- * to the VM_MAXUSER_ADDRESS.
- */
- maxuser = VM_MAXUSER_ADDRESS - PAGE_SIZE;
-#elif defined(__amd64__)
- maxuser = get_maxuser_address();
- ATF_REQUIRE(maxuser != 0);
-#else
- maxuser = VM_MAXUSER_ADDRESS;
-#endif
-
- scratch_file = mkstemp(template);
- ATF_REQUIRE(scratch_file != -1);
- unlink(template);
-
- ATF_CHECK(copyin_checker(0, 0) == 0);
- ATF_CHECK(copyin_checker(maxuser - 10, 9) == 0);
- ATF_CHECK(copyin_checker(maxuser - 10, 10) == 0);
- ATF_CHECK(copyin_checker(maxuser - 10, 11) == EFAULT);
- ATF_CHECK(copyin_checker(maxuser - 1, 1) == 0);
- ATF_CHECK(copyin_checker(maxuser, 0) == 0);
- ATF_CHECK(copyin_checker(maxuser, 1) == EFAULT);
- ATF_CHECK(copyin_checker(maxuser, 2) == EFAULT);
- ATF_CHECK(copyin_checker(maxuser + 1, 0) == 0);
- ATF_CHECK(copyin_checker(maxuser + 1, 2) == EFAULT);
- ATF_CHECK(copyin_checker(FMAX - 10, 9) == EFAULT);
- ATF_CHECK(copyin_checker(FMAX - 10, 10) == EFAULT);
- ATF_CHECK(copyin_checker(FMAX - 10, 11) == EFAULT);
-#if __SIZEOF_POINTER__ == 8
- ATF_CHECK(copyin_checker(ADDR_SIGNED, 1) == EFAULT);
- ATF_CHECK(copyin_checker2(ADDR_SIGNED) == EFAULT);
-#endif
-}
-
-ATF_TP_ADD_TCS(tp)
-{
-
- ATF_TP_ADD_TC(tp, kern_copyin);
- return (atf_no_error());
-}

File Metadata

Mime Type
text/plain
Expires
Fri, Feb 6, 11:13 PM (10 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28451233
Default Alt Text
D35349.id106731.diff (10 KB)

Event Timeline