NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/50469: PaX ASLR breaks netbsd32 emulation



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

			Hi Martin, (Christos)

On 11/25/15 09:20, Martin Husemann wrote:
>> size += pageoff;			/* add offset */ size =
>> (vsize_t)round_page(size);	/* round up */
>> 
>> +#ifdef PAX_ASLR +	pax_aslr(l, &addr, orig_addr, flags); +#endif
>> /* PAX_ASLR */
> 
> You need to explain this a bit - the PAX_ASLR code is obfuscated
> (for example nxr can not even find the pax_aslr() definition).

It isn't obfuscated (see sys/kern/kern_pax.c).

> If you move the ASLR up this far, you may break addr == 0 handling
> further down?

Yes, as I mentioned, the commit attached was wrong.

> A better fix probably is to
> 
> a) make the pax_aslr() call emulation specific
> 
> or
> 
> b) fix pax_aslr() to respect the the emulation specifics/VA
> settings of the passed lwp (including VM_MAP_TOPDOWN and the
> limits)

I finally managed to do enough of this to fix 32-bits emulation.

I am attaching a patch here, and adding the underlying log below.
(or see
http://git.edgebsd.org/gitweb/?p=edgebsd-src.git;a=log;h=refs/heads/khor
ben/pax-aslr-mmap)

Ok to commit?

commit f5e48327700df06086286b11e37ca54b3c76f8a1
Author: Pierre Pronchery <khorben%EdgeBSD.org@localhost>
Date:   Sun Mar 20 00:51:24 2016 +0100

    Let PaX ASLR know about the current emulation

    This effectively fixes PaX ASLR with 32-bits emulation on 64-bits
    platforms. Without this knowledge, the offset applied for 32-bits
    programs was really meant for a 64-bits address space - thus
    shifting the address up to 12 bits, with a success rate of about
    1/4096. This offset is calculated once in the lifetime of the
    process, which therefore behaved normally when able to start.

commit f691057c2fd010f497ce112a68739f3592a1dce3
Author: Pierre Pronchery <khorben%EdgeBSD.org@localhost>
Date:   Sun Mar 20 00:57:55 2016 +0100

    Remove pax_adjust() as it is not used anywhere

commit bfb172bc14dfa13b1a99c7fed949b6f8c5c1d65d
Author: Pierre Pronchery <khorben%EdgeBSD.org@localhost>
Date:   Sun Mar 20 00:58:36 2016 +0100

    Detect failures in PaX ASLR earlier

commit a061a231df2265dfcfb0828b630f4f1f0ae5854f
Author: Pierre Pronchery <khorben%EdgeBSD.org@localhost>
Date:   Sun Mar 20 01:01:21 2016 +0100

    Avoid a few casts in debugging code

commit e032672d5f9b5d2370e853c5a64c76aae1ba5ca8
Author: Pierre Pronchery <khorben%EdgeBSD.org@localhost>
Date:   Sun Mar 20 01:01:35 2016 +0100

    Typo

- -- 
khorben
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBAgAGBQJW7esWAAoJEDA4y9uYhpcD2H8QAJ2qufPLu3tYICnZbQ+JW5gZ
cePrMJJVtJZyElhW6eNITK1W4f86feb/RBjcsAC3NliE87Tez/gZevjKBhVyQ+Z3
ez81Sx9Zngx+t0k3gcEXU3bnryK8U+zrzNfz7cUNYGBC8KSeRUobJcnsDPpqtunW
24IixcQWTNZQtp6d9r7t9Q3OSdpZV0Q0QLgZrmPi6Bu6cU30IdEnrKNAs9Pym9vR
8RJXpPFoP+W9I2Yc6IncCUnXCiqvMSHx+2e7aXjFJ24jzE3vQpSEMnXgF1juIM8u
Z8vRA4edNAOiIPMJnGytby2P/ouMbpvU7Faz4RqYkWQCBIhyWVkqt9uBaC67C6qX
Tz7+bAObxp7r4Z3Ex0NffWjiACn/snIp21rHrE39M87Gd+MLsny8scr7rZBWezlX
P6iVDlsCbvWs+vUU9B5zTMGjrVk2MB5lIxqdYuTkohhxwH09HEEdqVjkzNt2MBtc
ECS0cV1VmmzNJj925UOV+/GQJ4zzTx+uGQOtKkQ3UG06GyVNXgBA8IAif35Qau7z
ETWTijmdTKj67LBBg01kwZ9b+mE8Og8Zrn2ogHODfCVY43Vr/s6n++yFj6TGh81d
t4UxiSnKStRWyfam/gg2fz0m9Nj6XuFeBNfBMjhII07DkwFKHfPg6gLoE+eCP5nI
PB+eMiDZiRvRezaz+FMl
=tReU
-----END PGP SIGNATURE-----
diff --git a/sys/compat/netbsd32/netbsd32_netbsd.c b/sys/compat/netbsd32/netbsd32_netbsd.c
index d9b44741..1a18205 100644
--- a/sys/compat/netbsd32/netbsd32_netbsd.c
+++ b/sys/compat/netbsd32/netbsd32_netbsd.c
@@ -1491,6 +1491,22 @@ netbsd32_setrlimit(struct lwp *l, const struct netbsd32_setrlimit_args *uap, reg
 	return (dosetrlimit(l, l->l_proc, which, &alim));
 }
 
+static int
+netbsd32_mmap_recover(struct lwp *l, u_long addr, long len)
+{
+	struct sys_munmap_args ua;
+	register_t retval = 0;
+	int error;
+
+	SCARG(&ua, addr) = (void *)addr;
+	SCARG(&ua, len) = len;
+	error = sys_munmap(l, &ua, &retval);
+	if (error)
+		printf("netbsd32_mmap_recover: error %d (addr=0x%lx, len=0x%lx)\n",
+				error, addr, len, error);
+	return EOVERFLOW;
+}
+
 int
 netbsd32_mmap(struct lwp *l, const struct netbsd32_mmap_args *uap, register_t *retval)
 {
@@ -1530,9 +1546,12 @@ netbsd32_mmap(struct lwp *l, const struct netbsd32_mmap_args *uap, register_t *r
 #endif
 	error = sys_mmap(l, &ua, retval);
 	if ((u_long)*retval > (u_long)UINT_MAX) {
+#ifdef DEBUG_MMAP
 		printf("netbsd32_mmap: retval out of range: 0x%lx\n",
 		    (u_long)*retval);
-		/* Should try to recover and return an error here. */
+#endif
+		/* try to recover and return an error */
+		error = netbsd32_mmap_recover(l, *retval, SCARG(&ua, len));
 	}
 	return (error);
 }
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index befccae..8c2a138 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1124,7 +1124,7 @@ execve_runproc(struct lwp *l, struct execve_data * restrict data,
 	vm->vm_minsaddr = (void *)epp->ep_minsaddr;
 
 #ifdef PAX_ASLR
-	pax_aslr_init(l, vm);
+	pax_aslr_init(l, vm, epp->ep_flags);
 #endif /* PAX_ASLR */
 
 	/* Now map address space. */
diff --git a/sys/kern/kern_pax.c b/sys/kern/kern_pax.c
index 796b908..589f7c1 100644
--- a/sys/kern/kern_pax.c
+++ b/sys/kern/kern_pax.c
@@ -300,13 +300,17 @@ pax_aslr_active(struct lwp *l)
 }
 
 void
-pax_aslr_init(struct lwp *l, struct vmspace *vm)
+pax_aslr_init(struct lwp *l, struct vmspace *vm, u_int ep_flags)
 {
 	if (!pax_aslr_active(l))
 		return;
 
-	vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(cprng_fast32(),
-	    PAX_ASLR_DELTA_MMAP_LSB, PAX_ASLR_DELTA_MMAP_LEN);
+	if (ep_flags & EXEC_32)
+		vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(cprng_fast32(),
+			PAX_ASLR_DELTA_MMAP_LSB, PAX_ASLR_DELTA_MMAP_LEN / 2);
+	else
+		vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(cprng_fast32(),
+			PAX_ASLR_DELTA_MMAP_LSB, PAX_ASLR_DELTA_MMAP_LEN);
 }
 
 void
@@ -317,21 +321,23 @@ pax_aslr(struct lwp *l, vaddr_t *addr, vaddr_t orig_addr, int f)
 
 	if (!(f & MAP_FIXED) && ((orig_addr == 0) || !(f & MAP_ANON))) {
 #ifdef PAX_ASLR_DEBUG
-		uprintf("applying to 0x%lx orig_addr=0x%lx f=%x\n",
-		    (unsigned long)*addr, (unsigned long)orig_addr, f);
+		uprintf("applying to 0x%" PRIxVADDR
+				" orig_addr=0x%" PRIxVADDR " f=0x%x\n",
+		    *addr, orig_addr, f);
 #endif
 		if (!(l->l_proc->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN))
 			*addr += l->l_proc->p_vmspace->vm_aslr_delta_mmap;
 		else
 			*addr -= l->l_proc->p_vmspace->vm_aslr_delta_mmap;
 #ifdef PAX_ASLR_DEBUG
-		uprintf("result 0x%lx\n", *addr);
+		uprintf("result 0x%" PRIxVADDR "\n", *addr);
 #endif
 	}
 #ifdef PAX_ASLR_DEBUG
 	else
-	    uprintf("not applying to 0x%lx orig_addr=0x%lx f=%x\n",
-		(unsigned long)*addr, (unsigned long)orig_addr, f);
+	    uprintf("not applying to 0x%" PRIxVADDR
+			    " orig_addr=0x%" PRIxVADDR " f=0x%x\n",
+		*addr, orig_addr, f);
 #endif
 }
 
@@ -343,7 +349,8 @@ pax_aslr_stack(struct lwp *l, struct exec_package *epp, u_long *max_stack_size)
 		    PAX_ASLR_DELTA_STACK_LSB,
 		    PAX_ASLR_DELTA_STACK_LEN);
 #ifdef PAX_ASLR_DEBUG
-		uprintf("stack 0x%lx d=0x%lx 0x%lx\n",
+		uprintf("stack 0x%" PRIxVADDR " d=0x%lx"
+				" 0x%" PRIxVADDR "\n",
 		    epp->ep_minsaddr, d, epp->ep_minsaddr - d);
 #endif
 		epp->ep_minsaddr -= d;
diff --git a/sys/sys/pax.h b/sys/sys/pax.h
index 5ae228d..c80e583 100644
--- a/sys/sys/pax.h
+++ b/sys/sys/pax.h
@@ -46,7 +46,6 @@ struct vmspace;
 #endif /* PAX_ASLR */
 
 void pax_init(void);
-void pax_adjust(struct lwp *, uint32_t);
 
 void pax_mprotect(struct lwp *, vm_prot_t *, vm_prot_t *);
 int pax_segvguard(struct lwp *, struct vnode *, const char *, bool);
@@ -54,7 +53,7 @@ int pax_segvguard(struct lwp *, struct vnode *, const char *, bool);
 #define	PAX_ASLR_DELTA(delta, lsb, len)	\
     (((delta) & ((1UL << (len)) - 1)) << (lsb))
 bool pax_aslr_active(struct lwp *);
-void pax_aslr_init(struct lwp *, struct vmspace *);
+void pax_aslr_init(struct lwp *, struct vmspace *, u_int);
 void pax_aslr_stack(struct lwp *, struct exec_package *, u_long *);
 void pax_aslr(struct lwp *, vaddr_t *, vaddr_t, int);
 
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index dd34d8e..b24ec61 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -180,7 +180,7 @@ struct emul {
 };
 
 /*
- * Emulation miscelaneous flags
+ * Emulation miscellaneous flags
  */
 #define	EMUL_HAS_SYS___syscall	0x001	/* Has SYS___syscall */
 
diff --git a/sys/uvm/uvm_mmap.c b/sys/uvm/uvm_mmap.c
index cbb45be..8043f0f 100644
--- a/sys/uvm/uvm_mmap.c
+++ b/sys/uvm/uvm_mmap.c
@@ -352,10 +352,12 @@ sys_mmap(struct lwp *l, const struct sys_mmap_args *uap, register_t *retval)
 		if (addr & PAGE_MASK)
 			return (EINVAL);
 
+#ifndef PAX_ASLR
 		error = range_test(addr, size, true);
 		if (error) {
 			return error;
 		}
+#endif
 
 	} else if (addr == 0 || !(flags & MAP_TRYFIXED)) {
 
@@ -419,6 +421,11 @@ sys_mmap(struct lwp *l, const struct sys_mmap_args *uap, register_t *retval)
 
 #ifdef PAX_ASLR
 	pax_aslr(l, &addr, orig_addr, flags);
+
+	error = range_test(addr, size, true);
+	if (error) {
+		goto out;
+	}
 #endif /* PAX_ASLR */
 
 	/*


Home | Main Index | Thread Index | Old Index