[PATCH v3 09/13] aarch64: enable BTI at runtime

Szabolcs Nagy szabolcs.nagy@arm.com
Tue May 26 11:20:22 GMT 2020


The 05/25/2020 16:53, Adhemerval Zanella wrote:
> On 15/05/2020 11:40, Szabolcs Nagy wrote:
> > From: Sudakshina Das <sudi.das@arm.com>
> > 
> > Binaries can opt-in to using BTI via an ELF object file marking.
> > The dynamic linker has to then mprotect the executable segments
> > with PROT_BTI. In case of static linked executables or in case
> > of the dynamic linker itself, PROT_BTI protection is done by the
> > operating system.
> > 
> > On AArch64 glibc uses PT_GNU_PROPERTY instead of PT_NOTE to check
> > the properties of a binary because PT_NOTE can be unreliable with
> > old linkers (old linkers just append the notes of input objects
> > together and add them to the output without checking them for
> > consistency which means multiple incompatible GNU property notes
> > can be present in PT_NOTE). A new _dl_process_pt_gnu_property
> > hook is introduced in dl-prop.h and to keep it maintainable the
> > rtld and dlopen code paths use the same function (if the main
> > map needs special treatment, that should be inferred by the hook
> > from the link map). Unlike the _dt_process_pt_note hook this one
> > is called after segments are mapped to avoid unbounded allocation
> > and additional read syscall. Otherwise the AArch64 logic follows
> > the x86 logic for handling GNU properties (but the code is not
> > shared because x86 needs to manage internal CET state and look
> > out for multiple property notes).
> > 
> > BTI property is handled in the loader even if glibc is not built
> > with BTI support, so in theory user code can be BTI protected
> > independently of glibc. In practice though user binaries are not
> > marked with the BTI property if glibc has no support because the
> > static linked libc objects (crt files, libc_nonshared.a) are
> > unmarked.
> > 
> > This patch relies on Linux userspace API that is scheduled to be
> > merged in Linux 5.8 and now it is in the for-next/bti-user branch
> > of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git.
> > 
> > Co-authored-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
> 
> LGTM with a just a nit below.
> 
> Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

thanks for the review.

> > @@ -1188,6 +1188,19 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
> >  				  maplength, has_holes, loader);
> >      if (__glibc_unlikely (errstring != NULL))
> >        goto call_lose;
> > +
> > +    /* Process program headers again after load segments are mapped.  */
> 
> Maybe add a brief explanation of why it is done after load segment mapping?
> 
> > +    for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
> > +      switch (ph->p_type)
> > +	{
> > +	case PT_GNU_PROPERTY:
> > +	  if (_dl_process_pt_gnu_property (l, ph))
> > +	    {
> > +	      errstring = N_("cannot process GNU property segment");
> > +	      goto call_lose;
> > +	    }
> > +	  break;
> > +	}

btw i think the _dl_process_pt_note callback should
be done here too and x86 fixed up accordingly so it
does not need unbounded allocation + pread_nocancel
to process the notes.

> > +static int
> > +enable_bti (struct link_map *map, const char *program)
> > +{
> > +  const ElfW(Phdr) *phdr;
> > +  unsigned prot = PROT_READ | PROT_EXEC | PROT_BTI;
> > +
> > +  for (phdr = map->l_phdr; phdr < &map->l_phdr[map->l_phnum]; ++phdr)
> > +    if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
> > +      {
> > +	ElfW(Addr) start = phdr->p_vaddr + map->l_addr;
> > +	ElfW(Addr) len = phdr->p_memsz;
> > +	if (__mprotect ((void *) start, len, prot) < 0)
> > +	  {
> > +	    if (program)
> > +	      _dl_fatal_printf ("%s: mprotect failed to turn on BTI\n",
> > +				map->l_name);
> > +	    else
> > +	      _dl_signal_error (EINVAL, map->l_name, "dlopen",
> > +				N_("mprotect failed to turn on BTI"));
> 
> Is EINVAL the only possible error here (EACCES or ENOMEM might be still
> possible)?

no, i think passing errno makes more sense here.
i'll fix it.


More information about the Libc-alpha mailing list