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