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



The following reply was made to PR kern/50469; it has been noted by GNATS.

From: Pierre Pronchery <khorben%defora.org@localhost>
To: gnats-bugs%NetBSD.org@localhost, kern-bug-people%netbsd.org@localhost,
 gnats-admin%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost
Cc: Christos Zoulas <christos%zoulas.com@localhost>
Subject: Re: kern/50469: PaX ASLR breaks netbsd32 emulation
Date: Sun, 20 Mar 2016 01:13:10 +0100

 This is a multi-part message in MIME format.
 --------------010207040706070009060308
 Content-Type: text/plain; charset=windows-1252
 Content-Transfer-Encoding: 8bit
 
 -----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-----
 
 --------------010207040706070009060308
 Content-Type: text/x-patch;
  name="patch-pax_aslr_emul32.diff"
 Content-Transfer-Encoding: quoted-printable
 Content-Disposition: attachment;
  filename="patch-pax_aslr_emul32.diff"
 
 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 net=
 bsd32_setrlimit_args *uap, reg
  	return (dosetrlimit(l, l->l_proc, which, &alim));
  }
 =20
 +static int
 +netbsd32_mmap_recover(struct lwp *l, u_long addr, long len)
 +{
 +	struct sys_munmap_args ua;
 +	register_t retval =3D 0;
 +	int error;
 +
 +	SCARG(&ua, addr) =3D (void *)addr;
 +	SCARG(&ua, len) =3D len;
 +	error =3D sys_munmap(l, &ua, &retval);
 +	if (error)
 +		printf("netbsd32_mmap_recover: error %d (addr=3D0x%lx, len=3D0x%lx)\n"=
 ,
 +				error, addr, len, error);
 +	return EOVERFLOW;
 +}
 +
  int
  netbsd32_mmap(struct lwp *l, const struct netbsd32_mmap_args *uap, regis=
 ter_t *retval)
  {
 @@ -1530,9 +1546,12 @@ netbsd32_mmap(struct lwp *l, const struct netbsd32=
 _mmap_args *uap, register_t *r
  #endif
  	error =3D 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 =3D 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 =3D (void *)epp->ep_minsaddr;
 =20
  #ifdef PAX_ASLR
 -	pax_aslr_init(l, vm);
 +	pax_aslr_init(l, vm, epp->ep_flags);
  #endif /* PAX_ASLR */
 =20
  	/* 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)
  }
 =20
  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;
 =20
 -	vm->vm_aslr_delta_mmap =3D 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 =3D PAX_ASLR_DELTA(cprng_fast32(),
 +			PAX_ASLR_DELTA_MMAP_LSB, PAX_ASLR_DELTA_MMAP_LEN / 2);
 +	else
 +		vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(cprng_fast32(),
 +			PAX_ASLR_DELTA_MMAP_LSB, PAX_ASLR_DELTA_MMAP_LEN);
  }
 =20
  void
 @@ -317,21 +321,23 @@ pax_aslr(struct lwp *l, vaddr_t *addr, vaddr_t orig=
 _addr, int f)
 =20
  	if (!(f & MAP_FIXED) && ((orig_addr =3D=3D 0) || !(f & MAP_ANON))) {
  #ifdef PAX_ASLR_DEBUG
 -		uprintf("applying to 0x%lx orig_addr=3D0x%lx f=3D%x\n",
 -		    (unsigned long)*addr, (unsigned long)orig_addr, f);
 +		uprintf("applying to 0x%" PRIxVADDR
 +				" orig_addr=3D0x%" PRIxVADDR " f=3D0x%x\n",
 +		    *addr, orig_addr, f);
  #endif
  		if (!(l->l_proc->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN))
  			*addr +=3D l->l_proc->p_vmspace->vm_aslr_delta_mmap;
  		else
  			*addr -=3D 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=3D0x%lx f=3D%x\n",
 -		(unsigned long)*addr, (unsigned long)orig_addr, f);
 +	    uprintf("not applying to 0x%" PRIxVADDR
 +			    " orig_addr=3D0x%" PRIxVADDR " f=3D0x%x\n",
 +		*addr, orig_addr, f);
  #endif
  }
 =20
 @@ -343,7 +349,8 @@ pax_aslr_stack(struct lwp *l, struct exec_package *ep=
 p, u_long *max_stack_size)
  		    PAX_ASLR_DELTA_STACK_LSB,
  		    PAX_ASLR_DELTA_STACK_LEN);
  #ifdef PAX_ASLR_DEBUG
 -		uprintf("stack 0x%lx d=3D0x%lx 0x%lx\n",
 +		uprintf("stack 0x%" PRIxVADDR " d=3D0x%lx"
 +				" 0x%" PRIxVADDR "\n",
  		    epp->ep_minsaddr, d, epp->ep_minsaddr - d);
  #endif
  		epp->ep_minsaddr -=3D 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 */
 =20
  void pax_init(void);
 -void pax_adjust(struct lwp *, uint32_t);
 =20
  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 c=
 har *, 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);
 =20
 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 {
  };
 =20
  /*
 - * Emulation miscelaneous flags
 + * Emulation miscellaneous flags
   */
  #define	EMUL_HAS_SYS___syscall	0x001	/* Has SYS___syscall */
 =20
 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);
 =20
 +#ifndef PAX_ASLR
  		error =3D range_test(addr, size, true);
  		if (error) {
  			return error;
  		}
 +#endif
 =20
  	} else if (addr =3D=3D 0 || !(flags & MAP_TRYFIXED)) {
 =20
 @@ -419,6 +421,11 @@ sys_mmap(struct lwp *l, const struct sys_mmap_args *=
 uap, register_t *retval)
 =20
  #ifdef PAX_ASLR
  	pax_aslr(l, &addr, orig_addr, flags);
 +
 +	error =3D range_test(addr, size, true);
 +	if (error) {
 +		goto out;
 +	}
  #endif /* PAX_ASLR */
 =20
  	/*
 
 --------------010207040706070009060308--
 


Home | Main Index | Thread Index | Old Index