tech-kern archive

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

Re: PaX: Heritage bug - Take 2



I've committed it.


Le 06/08/2015 17:26, Maxime Villard a écrit :
> Updated diff
> 
> 
> Index: kern/exec_elf.c
> ===================================================================
> RCS file: /cvsroot/src/sys/kern/exec_elf.c,v
> retrieving revision 1.75
> diff -u -r1.75 exec_elf.c
> --- kern/exec_elf.c	5 Aug 2015 15:58:01 -0000	1.75
> +++ kern/exec_elf.c	6 Aug 2015 15:23:51 -0000
> @@ -116,8 +116,7 @@
>  #define	ELF_TRUNC(a, b)		((a) & ~((b) - 1))
> 
>  static void
> -elf_placedynexec(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh,
> -    Elf_Phdr *ph)
> +elf_placedynexec(struct exec_package *epp, Elf_Ehdr *eh, Elf_Phdr *ph)
>  {
>  	Elf_Addr align, offset;
>  	int i;
> @@ -127,7 +126,7 @@
>  			align = ph[i].p_align;
> 
>  #ifdef PAX_ASLR
> -	if (pax_aslr_active(l)) {
> +	if (pax_aslr_epp_active(epp)) {
>  		size_t pax_align, l2, delta;
>  		uint32_t r;
> 
> @@ -717,12 +716,8 @@
>  		pos = (Elf_Addr)startp;
>  	}
> 
> -#if defined(PAX_MPROTECT) || defined(PAX_SEGVGUARD) || defined(PAX_ASLR)
> -	pax_setup_elf_flags(l, epp->ep_pax_flags);
> -#endif /* PAX_MPROTECT || PAX_SEGVGUARD || PAX_ASLR */
> -
>  	if (is_dyn)
> -		elf_placedynexec(l, epp, eh, ph);
> +		elf_placedynexec(epp, eh, ph);
> 
>  	/*
>  	 * Load all the necessary sections
> @@ -947,8 +942,15 @@
>  			    np->n_descsz == ELF_NOTE_PAX_DESCSZ &&
>  			    memcmp(ndata, ELF_NOTE_PAX_NAME,
>  			    ELF_NOTE_PAX_NAMESZ) == 0) {
> -				memcpy(&epp->ep_pax_flags, ndesc,
> -				    sizeof(epp->ep_pax_flags));
> +				uint32_t flags;
> +				memcpy(&flags, ndesc, sizeof(flags));
> +#if defined(PAX_MPROTECT) || defined(PAX_SEGVGUARD) || defined(PAX_ASLR)
> +				/* Convert the flags and insert them into
> +				 * the exec package. */
> +				pax_setup_elf_flags(epp, flags);
> +#else
> +				(void)flags; /* UNUSED */
> +#endif /* PAX_MPROTECT || PAX_SEGVGUARD || PAX_ASLR */
>  				break;
>  			}
>  			BADNOTE("PaX tag");
> Index: kern/exec_subr.c
> ===================================================================
> RCS file: /cvsroot/src/sys/kern/exec_subr.c,v
> retrieving revision 1.71
> diff -u -r1.71 exec_subr.c
> --- kern/exec_subr.c	29 Mar 2014 09:31:11 -0000	1.71
> +++ kern/exec_subr.c	6 Aug 2015 15:23:51 -0000
> @@ -408,7 +408,7 @@
>  	    max_stack_size);
> 
>  #ifdef PAX_ASLR
> -	pax_aslr_stack(l, epp, &max_stack_size);
> +	pax_aslr_stack(epp, &max_stack_size);
>  #endif /* PAX_ASLR */
> 
>  	l->l_proc->p_stackbase = epp->ep_minsaddr;
> Index: kern/kern_exec.c
> ===================================================================
> RCS file: /cvsroot/src/sys/kern/kern_exec.c,v
> retrieving revision 1.413
> diff -u -r1.413 kern_exec.c
> --- kern/kern_exec.c	31 Jul 2015 07:37:17 -0000	1.413
> +++ kern/kern_exec.c	6 Aug 2015 15:23:51 -0000
> @@ -705,9 +705,9 @@
>  	 */
> 
>  #ifdef PAX_ASLR
> -#define	ASLR_GAP(l)	(pax_aslr_active(l) ? (cprng_fast32() % PAGE_SIZE) : 0)
> +#define	ASLR_GAP(epp)	(pax_aslr_epp_active(epp) ? (cprng_fast32() %
> PAGE_SIZE) : 0)
>  #else
> -#define	ASLR_GAP(l)	0
> +#define	ASLR_GAP(epp)	0
>  #endif
> 
>  #ifdef __MACHINE_STACK_GROWS_UP
> @@ -725,7 +725,7 @@
> 
>  	data->ed_argslen = calcargs(data, argenvstrlen);
> 
> -	const size_t len = calcstack(data, ASLR_GAP(l) + RTLD_GAP);
> +	const size_t len = calcstack(data, ASLR_GAP(epp) + RTLD_GAP);
> 
>  	if (len > epp->ep_ssize) {
>  		/* in effect, compare to initial limit */
> @@ -1097,6 +1097,9 @@
>  	/* Remove POSIX timers */
>  	timers_free(p, TIMERS_POSIX);
> 
> +	/* Set the PaX flags. */
> +	p->p_pax = epp->ep_pax_flags;
> +
>  	/*
>  	 * Do whatever is necessary to prepare the address space
>  	 * for remapping.  Note that this might replace the current
> Index: kern/kern_pax.c
> ===================================================================
> RCS file: /cvsroot/src/sys/kern/kern_pax.c,v
> retrieving revision 1.31
> diff -u -r1.31 kern_pax.c
> --- kern/kern_pax.c	4 Aug 2015 18:28:09 -0000	1.31
> +++ kern/kern_pax.c	6 Aug 2015 15:23:51 -0000
> @@ -285,7 +285,7 @@
>  }
> 
>  void
> -pax_setup_elf_flags(struct lwp *l, uint32_t elf_flags)
> +pax_setup_elf_flags(struct exec_package *epp, uint32_t elf_flags)
>  {
>  	uint32_t flags = 0;
> 
> @@ -305,7 +305,7 @@
>  	}
>  #endif
> 
> -	l->l_proc->p_pax = flags;
> +	epp->ep_pax_flags = flags;
>  }
> 
>  #if defined(PAX_MPROTECT) || defined(PAX_SEGVGUARD) || defined(PAX_ASLR)
> @@ -372,6 +372,12 @@
>  }
> 
>  bool
> +pax_aslr_epp_active(struct exec_package *epp)
> +{
> +	return pax_flags_active(epp->ep_pax_flags, P_PAX_ASLR);
> +}
> +
> +bool
>  pax_aslr_active(struct lwp *l)
>  {
>  	return pax_flags_active(l->l_proc->p_pax, P_PAX_ASLR);
> @@ -408,9 +414,9 @@
>  }
> 
>  void
> -pax_aslr_stack(struct lwp *l, struct exec_package *epp, u_long
> *max_stack_size)
> +pax_aslr_stack(struct exec_package *epp, u_long *max_stack_size)
>  {
> -	if (!pax_aslr_active(l))
> +	if (!pax_aslr_epp_active(epp))
>  		return;
> 
>  	u_long d = PAX_ASLR_DELTA(cprng_fast32(),
> Index: sys/pax.h
> ===================================================================
> RCS file: /cvsroot/src/sys/sys/pax.h,v
> retrieving revision 1.14
> diff -u -r1.14 pax.h
> --- sys/pax.h	4 Aug 2015 18:28:10 -0000	1.14
> +++ sys/pax.h	6 Aug 2015 15:23:51 -0000
> @@ -50,7 +50,7 @@
>  #endif /* PAX_ASLR */
> 
>  void pax_init(void);
> -void pax_setup_elf_flags(struct lwp *, uint32_t);
> +void pax_setup_elf_flags(struct exec_package *, uint32_t);
>  void pax_adjust(struct lwp *, uint32_t);
> 
>  void pax_mprotect(struct lwp *, vm_prot_t *, vm_prot_t *);
> @@ -58,9 +58,11 @@
> 
>  #define	PAX_ASLR_DELTA(delta, lsb, len)	\
>      (((delta) & ((1UL << (len)) - 1)) << (lsb))
> +
> +bool pax_aslr_epp_active(struct exec_package *);
>  bool pax_aslr_active(struct lwp *);
>  void pax_aslr_init_vm(struct lwp *, struct vmspace *);
> -void pax_aslr_stack(struct lwp *, struct exec_package *, u_long *);
> +void pax_aslr_stack(struct exec_package *, u_long *);
>  void pax_aslr_mmap(struct lwp *, vaddr_t *, vaddr_t, int);
> 
>  #endif /* !_SYS_PAX_H_ */
> 
> 
> 
> 
> 
> 
> 
> 
> Le 03/08/2015 10:53, Maxime Villard a écrit :
>> [I sent this mail some days ago, but it didn't reach tech-kern@.]
>>
>> 	http://marc.info/?l=netbsd-tech-kern&m=142486844004373&w=2
>>
>> Here is a new patch. Now, the PaX flag is converted and registered
>> into the exec package by the loaders (only one loader does that, the
>> native ELF). And right before launching the process, the flag is set
>> in the proc structure - if it fails, the process is aborted, so this
>> is not that bad. In the meantime, all the PaX operations read the
>> exec package's flag instead of the LWP's.
>>
>> Important note, for the record:
>> In exec_subr.c, exec_setup_stack() is called from the loaders, so it
>> must read the exec package's flag. However, the other vmcmd_xx()
>> functions are called when setting up the proc address space, which is
>> done way later in execve_dovmcmds(); and they must therefore read the
>> LWP's flag. A particular order must be followed:
>>  - The loaders set the exec package's PaX flag
>>  - The loaders call exec_setup_stack(), which does not require a PaX
>>    initialization. Which is perfectly fine, since nothing has been
>>    initialized for the moment.
>>  - Here, if the loaders return an error, the calling process's PaX
>>    flag is not overwritten.
>>  - Later, the proc's PaX flag is overwritten. It is set right after
>>    killing the LWPs associated to that proc, and right before calling
>>    pax_aslr_init_vm(). pax_aslr_init_vm() reads the proc's PaX flag,
>>    so that's fine.
>>  - Right after pax_aslr_init_vm(), execve_dovmcmds() is called, and
>>    reads the proc's PaX flag, and expects PaX to be initialized. Which
>>    is perfectly fine too.
>>  - So now everything is ok; and if the execution fails, the process is
>>    aborted.
>>
>> Please review this change before I commit it (if you understood
>> something). Thanks.
>>
> 



Home | Main Index | Thread Index | Old Index