aboutsummaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2023-04-05 12:44:31 +0000
committerAndrew Turner <andrew@FreeBSD.org>2024-04-12 14:30:44 +0000
commitd8925a5f42b517131f926d665538be95db710c4a (patch)
treec50287a875104a14eaa9d6c474f6b573e7bf6fe7 /libexec
parent38cc6c3d95d4d1156960a9c5ba69c360e36f9976 (diff)
downloadsrc-d8925a5f42b517131f926d665538be95db710c4a.tar.gz
src-d8925a5f42b517131f926d665538be95db710c4a.zip
Support BTI in rtld
Read the elf note to decide when to set the guard page on arm64. Reviewed by: kib Sponsored by: Arm Ltd Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D39452
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/aarch64/reloc.c47
-rw-r--r--libexec/rtld-elf/aarch64/rtld_machdep.h2
-rw-r--r--libexec/rtld-elf/amd64/rtld_machdep.h3
-rw-r--r--libexec/rtld-elf/arm/rtld_machdep.h3
-rw-r--r--libexec/rtld-elf/i386/rtld_machdep.h3
-rw-r--r--libexec/rtld-elf/powerpc/rtld_machdep.h3
-rw-r--r--libexec/rtld-elf/powerpc64/rtld_machdep.h3
-rw-r--r--libexec/rtld-elf/riscv/rtld_machdep.h3
-rw-r--r--libexec/rtld-elf/rtld.c3
9 files changed, 70 insertions, 0 deletions
diff --git a/libexec/rtld-elf/aarch64/reloc.c b/libexec/rtld-elf/aarch64/reloc.c
index 44d390c5e083..d73982e26b76 100644
--- a/libexec/rtld-elf/aarch64/reloc.c
+++ b/libexec/rtld-elf/aarch64/reloc.c
@@ -29,6 +29,8 @@
#include <sys/types.h>
+#include <machine/sysarch.h>
+
#include <stdlib.h>
#include "debug.h"
@@ -52,6 +54,51 @@ void *_rtld_tlsdesc_dynamic(void *);
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
index b1c5e21cb505..36e3ec3e1a4e 100644
--- a/libexec/rtld-elf/aarch64/rtld_machdep.h
+++ b/libexec/rtld-elf/aarch64/rtld_machdep.h
@@ -45,6 +45,8 @@ struct Struct_Obj_Entry;
(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
index 68e51c4894f4..ab23567cb6e6 100644
--- a/libexec/rtld-elf/amd64/rtld_machdep.h
+++ b/libexec/rtld-elf/amd64/rtld_machdep.h
@@ -39,6 +39,9 @@ struct Struct_Obj_Entry;
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
index 6a08aa5eb02c..26f62547ae8e 100644
--- a/libexec/rtld-elf/arm/rtld_machdep.h
+++ b/libexec/rtld-elf/arm/rtld_machdep.h
@@ -39,6 +39,9 @@ struct Struct_Obj_Entry;
/* 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
index 6afb5e069cb5..69078d56df4c 100644
--- a/libexec/rtld-elf/i386/rtld_machdep.h
+++ b/libexec/rtld-elf/i386/rtld_machdep.h
@@ -39,6 +39,9 @@ struct Struct_Obj_Entry;
#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
index 7b106b7e38d7..2450d58490e1 100644
--- a/libexec/rtld-elf/powerpc/rtld_machdep.h
+++ b/libexec/rtld-elf/powerpc/rtld_machdep.h
@@ -38,6 +38,9 @@ struct Struct_Obj_Entry;
/* 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
index 7e6f13940daf..63939110356b 100644
--- a/libexec/rtld-elf/powerpc64/rtld_machdep.h
+++ b/libexec/rtld-elf/powerpc64/rtld_machdep.h
@@ -38,6 +38,9 @@ struct Struct_Obj_Entry;
/* 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
index 023245fbe6a4..814840790902 100644
--- a/libexec/rtld-elf/riscv/rtld_machdep.h
+++ b/libexec/rtld-elf/riscv/rtld_machdep.h
@@ -52,6 +52,9 @@ uint64_t set_gp(struct Struct_Obj_Entry *obj);
(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
index ad0e426f2f0e..a46cbe4e59c8 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -1729,6 +1729,9 @@ digest_notes(Obj_Entry *obj, Elf_Addr note_start, Elf_Addr note_end)
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;