diff --git a/libexec/rtld-elf/aarch64/reloc.c b/libexec/rtld-elf/aarch64/reloc.c --- a/libexec/rtld-elf/aarch64/reloc.c +++ b/libexec/rtld-elf/aarch64/reloc.c @@ -29,6 +29,8 @@ #include +#include + #include #include "debug.h" @@ -52,6 +54,51 @@ void _exit(int); +bool +arch_digest_note(struct Struct_Obj_Entry *obj __unused, const Elf_Note *note) +{ + const char *note_name; + const uint32_t *note_data; + + note_name = (const char *)(note + 1); + /* Only handle GNU notes */ + if (note->n_namesz != sizeof(ELF_NOTE_GNU) || + strncmp(note_name, ELF_NOTE_GNU, sizeof(ELF_NOTE_GNU)) != 0) + return (false); + + /* Only handle GNU property notes */ + if (note->n_type != NT_GNU_PROPERTY_TYPE_0) + return (false); + + /* + * note_data[0] - Type + * note_data[1] - Length + * note_data[2] - Data + * note_data[3] - Padding? + */ + note_data = (const uint32_t *)(note_name + note->n_namesz); + + /* Only handle AArch64 feature notes */ + if (note_data[0] != GNU_PROPERTY_AARCH64_FEATURE_1_AND) + return (false); + + /* We expect at least 4 bytes of data */ + if (note_data[1] < 4) + return (false); + + /* TODO: Only guard if HWCAP2_BTI is set */ + if ((note_data[2] & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) != 0) { + struct arm64_guard_page_args guard; + + guard.addr = (uintptr_t)obj->mapbase; + guard.len = obj->mapsize; + + sysarch(ARM64_GUARD_PAGE, &guard); + } + + return (true); +} + void init_pltgot(Obj_Entry *obj) { diff --git a/libexec/rtld-elf/aarch64/rtld_machdep.h b/libexec/rtld-elf/aarch64/rtld_machdep.h --- a/libexec/rtld-elf/aarch64/rtld_machdep.h +++ b/libexec/rtld-elf/aarch64/rtld_machdep.h @@ -45,6 +45,8 @@ (const Elf_Dyn *)_dynamic_addr; \ }) +bool arch_digest_note(struct Struct_Obj_Entry *obj, const Elf_Note *note); + Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj, const Elf_Rel *rel); diff --git a/libexec/rtld-elf/amd64/rtld_machdep.h b/libexec/rtld-elf/amd64/rtld_machdep.h --- a/libexec/rtld-elf/amd64/rtld_machdep.h +++ b/libexec/rtld-elf/amd64/rtld_machdep.h @@ -39,6 +39,9 @@ Elf_Dyn *rtld_dynamic_addr(void); #define rtld_dynamic(obj) rtld_dynamic_addr() +/* No architecture specific notes */ +#define arch_digest_note(obj, note) false + Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const struct Struct_Obj_Entry *obj, const struct Struct_Obj_Entry *refobj, const Elf_Rel *rel); diff --git a/libexec/rtld-elf/arm/rtld_machdep.h b/libexec/rtld-elf/arm/rtld_machdep.h --- a/libexec/rtld-elf/arm/rtld_machdep.h +++ b/libexec/rtld-elf/arm/rtld_machdep.h @@ -39,6 +39,9 @@ /* Return the address of the .dynamic section in the dynamic linker. */ #define rtld_dynamic(obj) (&_DYNAMIC) +/* No architecture specific notes */ +#define arch_digest_note(obj, note) false + Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj, const Elf_Rel *rel); diff --git a/libexec/rtld-elf/i386/rtld_machdep.h b/libexec/rtld-elf/i386/rtld_machdep.h --- a/libexec/rtld-elf/i386/rtld_machdep.h +++ b/libexec/rtld-elf/i386/rtld_machdep.h @@ -39,6 +39,9 @@ #define rtld_dynamic(obj) \ ((const Elf_Dyn *)((obj)->relocbase + (Elf_Addr)&_DYNAMIC)) +/* No architecture specific notes */ +#define arch_digest_note(obj, note) false + Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const struct Struct_Obj_Entry *obj, const struct Struct_Obj_Entry *refobj, const Elf_Rel *rel); diff --git a/libexec/rtld-elf/powerpc/rtld_machdep.h b/libexec/rtld-elf/powerpc/rtld_machdep.h --- a/libexec/rtld-elf/powerpc/rtld_machdep.h +++ b/libexec/rtld-elf/powerpc/rtld_machdep.h @@ -38,6 +38,9 @@ /* Return the address of the .dynamic section in the dynamic linker. */ #define rtld_dynamic(obj) (&_DYNAMIC) +/* No architecture specific notes */ +#define arch_digest_note(obj, note) false + Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj, const Elf_Rel *rel); diff --git a/libexec/rtld-elf/powerpc64/rtld_machdep.h b/libexec/rtld-elf/powerpc64/rtld_machdep.h --- a/libexec/rtld-elf/powerpc64/rtld_machdep.h +++ b/libexec/rtld-elf/powerpc64/rtld_machdep.h @@ -38,6 +38,9 @@ /* Return the address of the .dynamic section in the dynamic linker. */ #define rtld_dynamic(obj) (&_DYNAMIC) +/* No architecture specific notes */ +#define arch_digest_note(obj, note) false + Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj, const Elf_Rel *rel); diff --git a/libexec/rtld-elf/riscv/rtld_machdep.h b/libexec/rtld-elf/riscv/rtld_machdep.h --- a/libexec/rtld-elf/riscv/rtld_machdep.h +++ b/libexec/rtld-elf/riscv/rtld_machdep.h @@ -52,6 +52,9 @@ (const Elf_Dyn *)_dynamic_addr; \ }) +/* No architecture specific notes */ +#define arch_digest_note(obj, note) false + Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj, const Elf_Rel *rel); diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -1729,6 +1729,9 @@ note = (const Elf_Note *)((const char *)(note + 1) + roundup2(note->n_namesz, sizeof(Elf32_Addr)) + roundup2(note->n_descsz, sizeof(Elf32_Addr)))) { + if (arch_digest_note(obj, note)) + continue; + if (note->n_namesz != sizeof(NOTE_FREEBSD_VENDOR) || note->n_descsz != sizeof(int32_t)) continue;