mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 11:58:23 +08:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20e7c9d2cc | ||
|
|
a8aad403a6 | ||
|
|
f70dbaf7a1 | ||
|
|
a7833d6a29 | ||
|
|
f69c4d0439 | ||
|
|
3d0cab6a17 | ||
|
|
479a62fd3c | ||
|
|
72d607dcad | ||
|
|
26245e2725 | ||
|
|
f440d0a804 | ||
|
|
088a606441 | ||
|
|
d9c9571877 |
@@ -31,6 +31,18 @@ Major new features:
|
||||
pthread_attr_getsigmask_np have been added. They allow applications
|
||||
to specify the signal mask of a thread created with pthread_create.
|
||||
|
||||
* AArch64 now supports standard branch protection security hardening
|
||||
in glibc when it is built with a GCC that is configured with
|
||||
--enable-standard-branch-protection. This includes branch target
|
||||
identification (BTI) and pointer authentication for return addresses
|
||||
(PAC-RET). They require armv8.5-a and armv8.3-a architecture
|
||||
extensions respectively for the protection to be effective,
|
||||
otherwise the used instructions are nops. User code can use PAC-RET
|
||||
without libc support, but BTI requires a libc that is built with BTI
|
||||
support, otherwise runtime objects linked into user code will not be
|
||||
BTI compatible. It is recommended to use GCC 10 or newer when
|
||||
building glibc with branch protection.
|
||||
|
||||
Deprecated and removed features, and other changes affecting compatibility:
|
||||
|
||||
* The deprecated <sys/sysctl.h> header and the sysctl function have been
|
||||
|
||||
@@ -109,6 +109,12 @@
|
||||
/* AArch64 big endian ABI */
|
||||
#undef HAVE_AARCH64_BE
|
||||
|
||||
/* AArch64 BTI support enabled. */
|
||||
#define HAVE_AARCH64_BTI 0
|
||||
|
||||
/* AArch64 PAC-RET code generation is enabled. */
|
||||
#define HAVE_AARCH64_PAC_RET 0
|
||||
|
||||
/* C-SKY ABI version. */
|
||||
#undef CSKYABI
|
||||
|
||||
|
||||
@@ -53,6 +53,8 @@ offset length contents
|
||||
identify the earliest release of that OS that supports this ABI.
|
||||
See abi-tags (top level) for details. */
|
||||
|
||||
#include <link.h>
|
||||
#include <stdint.h>
|
||||
#include <config.h>
|
||||
#include <abi-tag.h> /* OS-specific ABI tag value */
|
||||
|
||||
@@ -60,13 +62,14 @@ offset length contents
|
||||
name begins with `.note' and creates a PT_NOTE program header entry
|
||||
pointing at it. */
|
||||
|
||||
.section ".note.ABI-tag", "a"
|
||||
.p2align 2
|
||||
.long 1f - 0f /* name length */
|
||||
.long 3f - 2f /* data length */
|
||||
.long 1 /* note type */
|
||||
0: .asciz "GNU" /* vendor name */
|
||||
1: .p2align 2
|
||||
2: .long __ABI_TAG_OS /* note data: the ABI tag */
|
||||
.long __ABI_TAG_VERSION
|
||||
3: .p2align 2 /* pad out section */
|
||||
__attribute__ ((used, aligned (4), section (".note.ABI-tag")))
|
||||
static const struct
|
||||
{
|
||||
ElfW(Nhdr) nhdr;
|
||||
char name[4];
|
||||
int32_t desc[4];
|
||||
} __abi_tag = {
|
||||
{ .n_namesz = 4, .n_descsz = 16, .n_type = 1 },
|
||||
"GNU",
|
||||
{ __ABI_TAG_OS, __ABI_TAG_VERSION }
|
||||
};
|
||||
@@ -1188,6 +1188,20 @@ _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 in
|
||||
case processing requires accessing those segments. */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (l->l_ld == 0)
|
||||
|
||||
@@ -1508,6 +1508,12 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
main_map->l_relro_size = ph->p_memsz;
|
||||
break;
|
||||
|
||||
case PT_GNU_PROPERTY:
|
||||
if (_dl_process_pt_gnu_property (main_map, ph))
|
||||
_dl_error_printf (
|
||||
"ERROR: '%s': cannot process GNU property segment.\n", _dl_argv[0]);
|
||||
break;
|
||||
|
||||
case PT_NOTE:
|
||||
if (_rtld_process_pt_note (main_map, ph))
|
||||
_dl_error_printf ("\
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
long-double-fcts = yes
|
||||
|
||||
ifeq ($(subdir),elf)
|
||||
sysdep-dl-routines += dl-bti
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),elf)
|
||||
sysdep-dl-routines += tlsdesc dl-tlsdesc
|
||||
gen-as-const-headers += dl-link.sym
|
||||
|
||||
Vendored
+81
@@ -172,3 +172,84 @@ else
|
||||
config_vars="$config_vars
|
||||
default-abi = lp64"
|
||||
fi
|
||||
|
||||
# Only consider BTI supported if -mbranch-protection=bti is
|
||||
# on by default in the compiler and the linker produces
|
||||
# binaries with GNU property notes in PT_GNU_PROPERTY segment.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BTI support" >&5
|
||||
$as_echo_n "checking for BTI support... " >&6; }
|
||||
if ${libc_cv_aarch64_bti+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat > conftest.c <<EOF
|
||||
void foo (void) { }
|
||||
EOF
|
||||
libc_cv_aarch64_bti=no
|
||||
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostdlib -nostartfiles $no_ssp -shared -fPIC -o conftest.so conftest.c'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; } \
|
||||
&& { ac_try='$READELF -lW conftest.so | grep -q GNU_PROPERTY'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; } \
|
||||
&& { ac_try='$READELF -nW conftest.so | grep -q "NT_GNU_PROPERTY_TYPE_0.*AArch64 feature:.* BTI"'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }
|
||||
then
|
||||
libc_cv_aarch64_bti=yes
|
||||
fi
|
||||
rm -rf conftest.*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aarch64_bti" >&5
|
||||
$as_echo "$libc_cv_aarch64_bti" >&6; }
|
||||
if test $libc_cv_aarch64_bti = yes; then
|
||||
$as_echo "#define HAVE_AARCH64_BTI 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
# Check if glibc is built with return address signing, i.e.
|
||||
# if -mbranch-protection=pac-ret is on. We need this because
|
||||
# pac-ret relies on unwinder support so it's not safe to use
|
||||
# it in assembly code unconditionally, but there is no
|
||||
# feature test macro for it in gcc.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if pac-ret is enabled" >&5
|
||||
$as_echo_n "checking if pac-ret is enabled... " >&6; }
|
||||
if ${libc_cv_aarch64_pac_ret+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat > conftest.c <<EOF
|
||||
int bar (void);
|
||||
int foo (void) { return bar () + 1; }
|
||||
EOF
|
||||
libc_cv_aarch64_pac_ret=no
|
||||
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S -o conftest.s conftest.c'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; } \
|
||||
&& { ac_try='grep -q -E '\''(hint( | )+25|paciasp)'\'' conftest.s'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }
|
||||
then
|
||||
libc_cv_aarch64_pac_ret=yes
|
||||
fi
|
||||
rm -rf conftest.*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aarch64_pac_ret" >&5
|
||||
$as_echo "$libc_cv_aarch64_pac_ret" >&6; }
|
||||
if test $libc_cv_aarch64_pac_ret = yes; then
|
||||
$as_echo "#define HAVE_AARCH64_PAC_RET 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
@@ -20,3 +20,43 @@ if test $libc_cv_aarch64_be = yes; then
|
||||
else
|
||||
LIBC_CONFIG_VAR([default-abi], [lp64])
|
||||
fi
|
||||
|
||||
# Only consider BTI supported if -mbranch-protection=bti is
|
||||
# on by default in the compiler and the linker produces
|
||||
# binaries with GNU property notes in PT_GNU_PROPERTY segment.
|
||||
AC_CACHE_CHECK([for BTI support], [libc_cv_aarch64_bti], [dnl
|
||||
cat > conftest.c <<EOF
|
||||
void foo (void) { }
|
||||
EOF
|
||||
libc_cv_aarch64_bti=no
|
||||
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostdlib -nostartfiles $no_ssp -shared -fPIC -o conftest.so conftest.c]) \
|
||||
&& AC_TRY_COMMAND([$READELF -lW conftest.so | grep -q GNU_PROPERTY]) \
|
||||
&& AC_TRY_COMMAND([$READELF -nW conftest.so | grep -q "NT_GNU_PROPERTY_TYPE_0.*AArch64 feature:.* BTI"])
|
||||
then
|
||||
libc_cv_aarch64_bti=yes
|
||||
fi
|
||||
rm -rf conftest.*])
|
||||
if test $libc_cv_aarch64_bti = yes; then
|
||||
AC_DEFINE(HAVE_AARCH64_BTI)
|
||||
fi
|
||||
|
||||
# Check if glibc is built with return address signing, i.e.
|
||||
# if -mbranch-protection=pac-ret is on. We need this because
|
||||
# pac-ret relies on unwinder support so it's not safe to use
|
||||
# it in assembly code unconditionally, but there is no
|
||||
# feature test macro for it in gcc.
|
||||
AC_CACHE_CHECK([if pac-ret is enabled], [libc_cv_aarch64_pac_ret], [dnl
|
||||
cat > conftest.c <<EOF
|
||||
int bar (void);
|
||||
int foo (void) { return bar () + 1; }
|
||||
EOF
|
||||
libc_cv_aarch64_pac_ret=no
|
||||
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -S -o conftest.s conftest.c]) \
|
||||
&& AC_TRY_COMMAND([grep -q -E '\''(hint( | )+25|paciasp)'\'' conftest.s])
|
||||
then
|
||||
libc_cv_aarch64_pac_ret=yes
|
||||
fi
|
||||
rm -rf conftest.*])
|
||||
if test $libc_cv_aarch64_pac_ret = yes; then
|
||||
AC_DEFINE(HAVE_AARCH64_PAC_RET)
|
||||
fi
|
||||
|
||||
@@ -75,6 +75,11 @@ call_weak_fn:
|
||||
.hidden _init
|
||||
.type _init, %function
|
||||
_init:
|
||||
#if HAVE_AARCH64_PAC_RET
|
||||
PACIASP
|
||||
#else
|
||||
BTI_C
|
||||
#endif
|
||||
stp x29, x30, [sp, -16]!
|
||||
mov x29, sp
|
||||
#if PREINIT_FUNCTION_WEAK
|
||||
@@ -89,5 +94,10 @@ _init:
|
||||
.hidden _fini
|
||||
.type _fini, %function
|
||||
_fini:
|
||||
#if HAVE_AARCH64_PAC_RET
|
||||
PACIASP
|
||||
#else
|
||||
BTI_C
|
||||
#endif
|
||||
stp x29, x30, [sp, -16]!
|
||||
mov x29, sp
|
||||
|
||||
@@ -37,10 +37,18 @@
|
||||
/* crtn.S puts function epilogues in the .init and .fini sections
|
||||
corresponding to the prologues in crti.S. */
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
.section .init,"ax",%progbits
|
||||
ldp x29, x30, [sp], 16
|
||||
#if HAVE_AARCH64_PAC_RET
|
||||
AUTIASP
|
||||
#endif
|
||||
RET
|
||||
|
||||
.section .fini,"ax",%progbits
|
||||
ldp x29, x30, [sp], 16
|
||||
#if HAVE_AARCH64_PAC_RET
|
||||
AUTIASP
|
||||
#endif
|
||||
RET
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/* AArch64 BTI functions.
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <libintl.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
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 (errno, map->l_name, "dlopen",
|
||||
N_("mprotect failed to turn on BTI"));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable BTI for L if required. */
|
||||
|
||||
void
|
||||
_dl_bti_check (struct link_map *l, const char *program)
|
||||
{
|
||||
if (GLRO(dl_aarch64_cpu_features).bti && l->l_mach.bti)
|
||||
enable_bti (l, program);
|
||||
}
|
||||
@@ -125,6 +125,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
.globl _dl_start_user \n\
|
||||
.type _dl_start_user, %function \n\
|
||||
_start: \n\
|
||||
// bti c \n\
|
||||
hint 34 \n\
|
||||
mov " PTR "0, " PTR_SP " \n\
|
||||
bl _dl_start \n\
|
||||
// returns user entry point in x0 \n\
|
||||
@@ -178,7 +180,8 @@ _dl_start_user: \n\
|
||||
adrp x0, _dl_fini \n\
|
||||
add " PTR "0, " PTR "0, #:lo12:_dl_fini \n\
|
||||
// jump to the user_s entry point \n\
|
||||
br x21 \n\
|
||||
mov x16, x21 \n\
|
||||
br x16 \n\
|
||||
");
|
||||
|
||||
#define elf_machine_type_class(type) \
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/* Support for GNU properties. AArch64 version.
|
||||
Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _DL_PROP_H
|
||||
#define _DL_PROP_H
|
||||
|
||||
#include <not-cancel.h>
|
||||
|
||||
extern void _dl_bti_check (struct link_map *, const char *)
|
||||
attribute_hidden;
|
||||
|
||||
static inline void __attribute__ ((always_inline))
|
||||
_rtld_main_check (struct link_map *m, const char *program)
|
||||
{
|
||||
_dl_bti_check (m, program);
|
||||
}
|
||||
|
||||
static inline void __attribute__ ((always_inline))
|
||||
_dl_open_check (struct link_map *m)
|
||||
{
|
||||
_dl_bti_check (m, NULL);
|
||||
}
|
||||
|
||||
static inline void __attribute__ ((unused))
|
||||
_dl_process_aarch64_property (struct link_map *l,
|
||||
const ElfW(Nhdr) *note,
|
||||
const ElfW(Addr) size,
|
||||
const ElfW(Addr) align)
|
||||
{
|
||||
/* The NT_GNU_PROPERTY_TYPE_0 note must be aligned to 4 bytes in
|
||||
32-bit objects and to 8 bytes in 64-bit objects. Skip notes
|
||||
with incorrect alignment. */
|
||||
if (align != (__ELF_NATIVE_CLASS / 8))
|
||||
return;
|
||||
|
||||
const ElfW(Addr) start = (ElfW(Addr)) note;
|
||||
|
||||
unsigned int feature_1 = 0;
|
||||
unsigned int last_type = 0;
|
||||
|
||||
while ((ElfW(Addr)) (note + 1) - start < size)
|
||||
{
|
||||
/* Find the NT_GNU_PROPERTY_TYPE_0 note. */
|
||||
if (note->n_namesz == 4
|
||||
&& note->n_type == NT_GNU_PROPERTY_TYPE_0
|
||||
&& memcmp (note + 1, "GNU", 4) == 0)
|
||||
{
|
||||
/* Check for invalid property. */
|
||||
if (note->n_descsz < 8
|
||||
|| (note->n_descsz % sizeof (ElfW(Addr))) != 0)
|
||||
return;
|
||||
|
||||
/* Start and end of property array. */
|
||||
unsigned char *ptr = (unsigned char *) (note + 1) + 4;
|
||||
unsigned char *ptr_end = ptr + note->n_descsz;
|
||||
|
||||
do
|
||||
{
|
||||
unsigned int type = *(unsigned int *) ptr;
|
||||
unsigned int datasz = *(unsigned int *) (ptr + 4);
|
||||
|
||||
/* Property type must be in ascending order. */
|
||||
if (type < last_type)
|
||||
return;
|
||||
|
||||
ptr += 8;
|
||||
if ((ptr + datasz) > ptr_end)
|
||||
return;
|
||||
|
||||
last_type = type;
|
||||
|
||||
if (type == GNU_PROPERTY_AARCH64_FEATURE_1_AND)
|
||||
{
|
||||
/* The size of GNU_PROPERTY_AARCH64_FEATURE_1_AND is 4
|
||||
bytes. When seeing GNU_PROPERTY_AARCH64_FEATURE_1_AND,
|
||||
we stop the search regardless if its size is correct
|
||||
or not. There is no point to continue if this note
|
||||
is ill-formed. */
|
||||
if (datasz != 4)
|
||||
return;
|
||||
|
||||
feature_1 = *(unsigned int *) ptr;
|
||||
if ((feature_1 & GNU_PROPERTY_AARCH64_FEATURE_1_BTI))
|
||||
l->l_mach.bti = true;
|
||||
|
||||
/* Stop if we found the property note. */
|
||||
return;
|
||||
}
|
||||
else if (type > GNU_PROPERTY_AARCH64_FEATURE_1_AND)
|
||||
{
|
||||
/* Stop since property type is in ascending order. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check the next property item. */
|
||||
ptr += ALIGN_UP (datasz, sizeof (ElfW(Addr)));
|
||||
}
|
||||
while ((ptr_end - ptr) >= 8);
|
||||
}
|
||||
|
||||
note = ((const void *) note
|
||||
+ ELF_NOTE_NEXT_OFFSET (note->n_namesz, note->n_descsz,
|
||||
align));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FILEBUF_SIZE
|
||||
static inline int __attribute__ ((always_inline))
|
||||
_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph,
|
||||
int fd, struct filebuf *fbp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int __attribute__ ((always_inline))
|
||||
_rtld_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_dl_process_pt_gnu_property (struct link_map *l, const ElfW(Phdr) *ph)
|
||||
{
|
||||
const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr);
|
||||
_dl_process_aarch64_property (l, note, ph->p_memsz, ph->p_align);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _DL_PROP_H */
|
||||
@@ -74,6 +74,7 @@
|
||||
cfi_startproc
|
||||
.align 2
|
||||
_dl_tlsdesc_return:
|
||||
BTI_C
|
||||
DELOUSE (0)
|
||||
ldr PTR_REG (0), [x0, #PTR_SIZE]
|
||||
RET
|
||||
@@ -95,6 +96,7 @@ _dl_tlsdesc_return:
|
||||
cfi_startproc
|
||||
.align 2
|
||||
_dl_tlsdesc_undefweak:
|
||||
BTI_C
|
||||
str x1, [sp, #-16]!
|
||||
cfi_adjust_cfa_offset (16)
|
||||
DELOUSE (0)
|
||||
@@ -142,6 +144,7 @@ _dl_tlsdesc_undefweak:
|
||||
cfi_startproc
|
||||
.align 2
|
||||
_dl_tlsdesc_dynamic:
|
||||
BTI_C
|
||||
DELOUSE (0)
|
||||
|
||||
/* Save just enough registers to support fast path, if we fall
|
||||
@@ -180,6 +183,10 @@ _dl_tlsdesc_dynamic:
|
||||
callee will trash. */
|
||||
|
||||
/* Save the remaining registers that we must treat as caller save. */
|
||||
# if HAVE_AARCH64_PAC_RET
|
||||
PACIASP
|
||||
cfi_window_save
|
||||
# endif
|
||||
# define NSAVEXREGPAIRS 8
|
||||
stp x29, x30, [sp,#-16*NSAVEXREGPAIRS]!
|
||||
cfi_adjust_cfa_offset (16*NSAVEXREGPAIRS)
|
||||
@@ -230,6 +237,10 @@ _dl_tlsdesc_dynamic:
|
||||
cfi_adjust_cfa_offset (-16*NSAVEXREGPAIRS)
|
||||
cfi_restore (x29)
|
||||
cfi_restore (x30)
|
||||
# if HAVE_AARCH64_PAC_RET
|
||||
AUTIASP
|
||||
cfi_window_save
|
||||
# endif
|
||||
b 1b
|
||||
cfi_endproc
|
||||
.size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
cfi_startproc
|
||||
.align 2
|
||||
_dl_runtime_resolve:
|
||||
BTI_C
|
||||
/* AArch64 we get called with:
|
||||
ip0 &PLTGOT[2]
|
||||
ip1 temp(dl resolver entry point)
|
||||
@@ -126,6 +127,12 @@ _dl_runtime_resolve:
|
||||
cfi_startproc
|
||||
.align 2
|
||||
_dl_runtime_profile:
|
||||
# if HAVE_AARCH64_PAC_RET
|
||||
PACIASP
|
||||
cfi_window_save
|
||||
# else
|
||||
BTI_C
|
||||
# endif
|
||||
/* AArch64 we get called with:
|
||||
ip0 &PLTGOT[2]
|
||||
ip1 temp(dl resolver entry point)
|
||||
@@ -237,8 +244,17 @@ _dl_runtime_profile:
|
||||
cfi_restore(x29)
|
||||
cfi_restore(x30)
|
||||
|
||||
# if HAVE_AARCH64_PAC_RET
|
||||
add sp, sp, SF_SIZE
|
||||
cfi_adjust_cfa_offset (-SF_SIZE)
|
||||
AUTIASP
|
||||
cfi_window_save
|
||||
add sp, sp, 16
|
||||
cfi_adjust_cfa_offset (-16)
|
||||
# else
|
||||
add sp, sp, SF_SIZE + 16
|
||||
cfi_adjust_cfa_offset (- SF_SIZE - 16)
|
||||
# endif
|
||||
|
||||
/* Jump to the newly found address. */
|
||||
br ip0
|
||||
@@ -285,6 +301,10 @@ _dl_runtime_profile:
|
||||
/* LR from within La_aarch64_reg */
|
||||
ldr lr, [x29, #OFFSET_RG + DL_OFFSET_RG_LR]
|
||||
cfi_restore(lr)
|
||||
# if HAVE_AARCH64_PAC_RET
|
||||
/* Note: LR restored from La_aarch64_reg has no PAC. */
|
||||
cfi_window_save
|
||||
# endif
|
||||
mov sp, x29
|
||||
cfi_def_cfa_register (sp)
|
||||
ldr x29, [x29, #0]
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct link_map_machine
|
||||
{
|
||||
ElfW(Addr) plt; /* Address of .plt */
|
||||
void *tlsdesc_table; /* Address of TLS descriptor hash table. */
|
||||
bool bti; /* Branch Target Identification is enabled. */
|
||||
};
|
||||
|
||||
@@ -27,8 +27,9 @@ static void mcount_internal (u_long frompc, u_long selfpc);
|
||||
#define _MCOUNT_DECL(frompc, selfpc) \
|
||||
static inline void mcount_internal (u_long frompc, u_long selfpc)
|
||||
|
||||
/* Note: strip_pac is needed for frompc because of gcc PR target/94791. */
|
||||
#define MCOUNT \
|
||||
void __mcount (void *frompc) \
|
||||
{ \
|
||||
mcount_internal ((u_long) frompc, (u_long) RETURN_ADDRESS (0)); \
|
||||
mcount_internal ((u_long) strip_pac (frompc), (u_long) RETURN_ADDRESS (0)); \
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
.globl _start
|
||||
.type _start,#function
|
||||
_start:
|
||||
BTI_C
|
||||
/* Create an initial frame with 0 LR and FP */
|
||||
mov x29, #0
|
||||
mov x30, #0
|
||||
|
||||
@@ -35,18 +35,72 @@
|
||||
|
||||
#define PTR_SIZE (1<<PTR_LOG_SIZE)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/* Strip pointer authentication code from pointer p. */
|
||||
static inline void *
|
||||
strip_pac (void *p)
|
||||
{
|
||||
register void *ra asm ("x30") = (p);
|
||||
asm ("hint 7 // xpaclri" : "+r"(ra));
|
||||
return ra;
|
||||
}
|
||||
|
||||
/* This is needed when glibc is built with -mbranch-protection=pac-ret
|
||||
with a gcc that is affected by PR target/95891. */
|
||||
# if HAVE_AARCH64_PAC_RET
|
||||
# undef RETURN_ADDRESS
|
||||
# define RETURN_ADDRESS(n) strip_pac (__builtin_return_address (n))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
|
||||
/* Syntactic details of assembler. */
|
||||
|
||||
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
|
||||
|
||||
/* Branch Target Identitication support. */
|
||||
#define BTI_C hint 34
|
||||
#define BTI_J hint 36
|
||||
|
||||
/* Return address signing support (pac-ret). */
|
||||
#define PACIASP hint 25
|
||||
#define AUTIASP hint 29
|
||||
|
||||
/* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code. */
|
||||
#define FEATURE_1_AND 0xc0000000
|
||||
#define FEATURE_1_BTI 1
|
||||
#define FEATURE_1_PAC 2
|
||||
|
||||
/* Add a NT_GNU_PROPERTY_TYPE_0 note. */
|
||||
#define GNU_PROPERTY(type, value) \
|
||||
.section .note.gnu.property, "a"; \
|
||||
.p2align 3; \
|
||||
.word 4; \
|
||||
.word 16; \
|
||||
.word 5; \
|
||||
.asciz "GNU"; \
|
||||
.word type; \
|
||||
.word 4; \
|
||||
.word value; \
|
||||
.word 0; \
|
||||
.text
|
||||
|
||||
/* Add GNU property note with the supported features to all asm code
|
||||
where sysdep.h is included. */
|
||||
#if HAVE_AARCH64_BTI && HAVE_AARCH64_PAC_RET
|
||||
GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI|FEATURE_1_PAC)
|
||||
#elif HAVE_AARCH64_BTI
|
||||
GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI)
|
||||
#endif
|
||||
|
||||
/* Define an entry point visible from C. */
|
||||
#define ENTRY(name) \
|
||||
.globl C_SYMBOL_NAME(name); \
|
||||
.type C_SYMBOL_NAME(name),%function; \
|
||||
.align 4; \
|
||||
C_LABEL(name) \
|
||||
BTI_C; \
|
||||
cfi_startproc; \
|
||||
CALL_MCOUNT
|
||||
|
||||
@@ -56,6 +110,7 @@
|
||||
.type C_SYMBOL_NAME(name),%function; \
|
||||
.p2align align; \
|
||||
C_LABEL(name) \
|
||||
BTI_C; \
|
||||
cfi_startproc; \
|
||||
CALL_MCOUNT
|
||||
|
||||
@@ -68,10 +123,11 @@
|
||||
.globl C_SYMBOL_NAME(name); \
|
||||
.type C_SYMBOL_NAME(name),%function; \
|
||||
.p2align align; \
|
||||
.rep padding; \
|
||||
.rep padding - 1; /* -1 for bti c. */ \
|
||||
nop; \
|
||||
.endr; \
|
||||
C_LABEL(name) \
|
||||
BTI_C; \
|
||||
cfi_startproc; \
|
||||
CALL_MCOUNT
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/* Tag_ABI_align8_preserved: This code preserves 8-byte
|
||||
alignment in any callee. */
|
||||
.eabi_attribute 25, 1
|
||||
/* Tag_ABI_align8_needed: This code may require 8-byte alignment from
|
||||
the caller. */
|
||||
.eabi_attribute 24, 1
|
||||
|
||||
#include <csu/abi-note.S>
|
||||
@@ -20,11 +20,11 @@
|
||||
#define _DL_PROP_H
|
||||
|
||||
/* The following functions are used by the dynamic loader and the
|
||||
dlopen machinery to process PT_NOTE entries in the binary or
|
||||
shared object. The notes can be used to change the behaviour of
|
||||
the loader, and as such offer a flexible mechanism for hooking in
|
||||
various checks related to ABI tags or implementing "flag day" ABI
|
||||
transitions. */
|
||||
dlopen machinery to process PT_NOTE and PT_GNU_PROPERTY entries in
|
||||
the binary or shared object. The notes can be used to change the
|
||||
behaviour of the loader, and as such offer a flexible mechanism
|
||||
for hooking in various checks related to ABI tags or implementing
|
||||
"flag day" ABI transitions. */
|
||||
|
||||
static inline void __attribute__ ((always_inline))
|
||||
_rtld_main_check (struct link_map *m, const char *program)
|
||||
@@ -51,4 +51,10 @@ _rtld_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int __attribute__ ((always_inline))
|
||||
_dl_process_pt_gnu_property (struct link_map *l, const ElfW(Phdr) *ph)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _DL_PROP_H */
|
||||
|
||||
@@ -72,3 +72,4 @@
|
||||
#define HWCAP2_BF16 (1 << 14)
|
||||
#define HWCAP2_DGH (1 << 15)
|
||||
#define HWCAP2_RNG (1 << 16)
|
||||
#define HWCAP2_BTI (1 << 17)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Definitions for POSIX memory map interface. Linux/AArch64 version.
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _SYS_MMAN_H
|
||||
# error "Never use <bits/mman.h> directly; include <sys/mman.h> instead."
|
||||
#endif
|
||||
|
||||
/* AArch64 specific definitions, should be in sync with
|
||||
arch/arm64/include/uapi/asm/mman.h. */
|
||||
|
||||
#define PROT_BTI 0x10
|
||||
|
||||
#include <bits/mman-map-flags-generic.h>
|
||||
|
||||
/* Include generic Linux declarations. */
|
||||
#include <bits/mman-linux.h>
|
||||
@@ -83,4 +83,7 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||
|
||||
if ((dczid & DCZID_DZP_MASK) == 0)
|
||||
cpu_features->zva_size = 4 << (dczid & DCZID_BS_MASK);
|
||||
|
||||
/* Check if BTI is supported. */
|
||||
cpu_features->bti = GLRO (dl_hwcap2) & HWCAP2_BTI;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define _CPU_FEATURES_AARCH64_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MIDR_PARTNUM_SHIFT 4
|
||||
#define MIDR_PARTNUM_MASK (0xfff << MIDR_PARTNUM_SHIFT)
|
||||
@@ -64,6 +65,7 @@ struct cpu_features
|
||||
{
|
||||
uint64_t midr_el1;
|
||||
unsigned zva_size;
|
||||
bool bti;
|
||||
};
|
||||
|
||||
#endif /* _CPU_FEATURES_AARCH64_H */
|
||||
|
||||
@@ -28,8 +28,12 @@
|
||||
.text
|
||||
ENTRY(__swapcontext)
|
||||
DELOUSE (0)
|
||||
/* Set the value returned when swapcontext() returns in this context. */
|
||||
str xzr, [x0, oX0 + 0 * SZREG]
|
||||
/* Set the value returned when swapcontext() returns in this context.
|
||||
And set up x1 to become the return address of the caller, so we
|
||||
can return there with a normal RET instead of an indirect jump. */
|
||||
stp xzr, x30, [x0, oX0 + 0 * SZREG]
|
||||
/* Arrange the oucp context to return to 2f. */
|
||||
adr x30, 2f
|
||||
|
||||
stp x18, x19, [x0, oX0 + 18 * SZREG]
|
||||
stp x20, x21, [x0, oX0 + 20 * SZREG]
|
||||
@@ -97,5 +101,11 @@ ENTRY(__swapcontext)
|
||||
|
||||
1:
|
||||
b C_SYMBOL_NAME(__syscall_error)
|
||||
2:
|
||||
/* The oucp context is restored here via an indirect branch,
|
||||
x1 must be restored too which has the real return address. */
|
||||
BTI_J
|
||||
mov x30, x1
|
||||
RET
|
||||
PSEUDO_END (__swapcontext)
|
||||
weak_alias (__swapcontext, swapcontext)
|
||||
|
||||
@@ -191,4 +191,10 @@ _rtld_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int __attribute__ ((always_inline))
|
||||
_dl_process_pt_gnu_property (struct link_map *l, const ElfW(Phdr) *ph)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _DL_PROP_H */
|
||||
|
||||
Reference in New Issue
Block a user