From b9b7bbb466efc2955c80204250eedeecfacbecd7 Mon Sep 17 00:00:00 2001 From: Indu Bhagat Date: Wed, 9 Jul 2025 23:13:58 +0200 Subject: [PATCH] ld/aarch64elf: add support for DT_AARCH64_MEMTAG_STACK dynamic tag Add new command line option -z memtag-stack for aarch64 elf. This option instructs the linker to generate the necessary dynamic tag DT_AARCH64_MEMTAG_STACK, which the dynamic loader can then use to protect the stack memory with PROT_MTE. Linker issues an 'unrecognized option' error when -z memtag-stack is specified for non-aarch64 based emulations. readelf displays the dynamic tag when present: $ readelf -d Dynamic section at offset 0xfdd8 contains XX entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000000c (INIT) 0x400520 0x000000000000000d (FINI) 0x400b64 0x0000000000000019 (INIT_ARRAY) 0x41fdc8 ... ... ... 0x000000007000000c (AARCH64_MEMTAG_STACK) 0x1 ... ... ... ChangeLog: * bfd/elfnn-aarch64.c (elfNN_aarch64_late_size_sections): Emit DT_AARCH64_MEMTAG_STACK dynamic tag. * bfd/elfxx-aarch64.h (struct aarch64_memtag_opts): Add new member for tracking whether stack access uses MTE insns. * binutils/readelf.c (get_aarch64_dynamic_type): Handle DT_AARCH64_MEMTAG_STACK. * ld/emultempl/aarch64elf.em: Add new command line option. * ld/ld.texi: Add documentation for -z memtag-stack. * ld/testsuite/ld-aarch64/aarch64-elf.exp: Add new test. * ld/testsuite/ld-aarch64/dt-memtag-stack.d: New test. include/ChangeLog: * elf/aarch64.h (DT_AARCH64_MEMTAG_STACK): New definition. --- bfd/elfnn-aarch64.c | 6 ++++++ bfd/elfxx-aarch64.h | 3 +++ binutils/readelf.c | 1 + include/elf/aarch64.h | 1 + ld/emultempl/aarch64elf.em | 5 +++++ ld/ld.texi | 5 +++++ ld/testsuite/ld-aarch64/aarch64-elf.exp | 1 + ld/testsuite/ld-aarch64/dt-memtag-stack.d | 7 +++++++ 8 files changed, 29 insertions(+) create mode 100644 ld/testsuite/ld-aarch64/dt-memtag-stack.d diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 0e9e22e210b..9e98215d638 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -9786,6 +9786,12 @@ elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, && !add_dynamic_entry (DT_AARCH64_MEMTAG_MODE, htab->memtag_opts.memtag_mode == AARCH64_MEMTAG_MODE_ASYNC)) return false; + + if (is_aarch64_elf (output_bfd) + && htab->memtag_opts.memtag_stack == 1 + && !add_dynamic_entry (DT_AARCH64_MEMTAG_STACK, + htab->memtag_opts.memtag_stack == 1)) + return false; } #undef add_dynamic_entry diff --git a/bfd/elfxx-aarch64.h b/bfd/elfxx-aarch64.h index 66c1f48d450..bd3642cbefe 100644 --- a/bfd/elfxx-aarch64.h +++ b/bfd/elfxx-aarch64.h @@ -147,6 +147,9 @@ struct aarch64_memtag_opts { /* Mode of MTE operation. */ aarch64_memtag_mode_type memtag_mode; + + /* Whether stack accesses use MTE insns. */ + unsigned int memtag_stack; }; typedef struct aarch64_memtag_opts aarch64_memtag_opts; diff --git a/binutils/readelf.c b/binutils/readelf.c index 0d8daf3626f..cfccdd2ba65 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -2588,6 +2588,7 @@ get_aarch64_dynamic_type (unsigned long type) case DT_AARCH64_PAC_PLT: return "AARCH64_PAC_PLT"; case DT_AARCH64_VARIANT_PCS: return "AARCH64_VARIANT_PCS"; case DT_AARCH64_MEMTAG_MODE: return "AARCH64_MEMTAG_MODE"; + case DT_AARCH64_MEMTAG_STACK: return "AARCH64_MEMTAG_STACK"; default: return NULL; diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h index 747d8dc022f..74bd7b402e0 100644 --- a/include/elf/aarch64.h +++ b/include/elf/aarch64.h @@ -53,6 +53,7 @@ #define DT_AARCH64_PAC_PLT (DT_LOPROC + 3) #define DT_AARCH64_VARIANT_PCS (DT_LOPROC + 5) #define DT_AARCH64_MEMTAG_MODE (DT_LOPROC + 9) +#define DT_AARCH64_MEMTAG_STACK (DT_LOPROC + 12) /* AArch64-specific values for st_other. */ #define STO_AARCH64_VARIANT_PCS 0x80 /* Symbol may follow different call diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em index d7e4eb78059..66eaf1cd861 100644 --- a/ld/emultempl/aarch64elf.em +++ b/ld/emultempl/aarch64elf.em @@ -44,6 +44,7 @@ static aarch64_protection_opts sw_protections = { static aarch64_memtag_opts memtag_opts = { .memtag_mode = AARCH64_MEMTAG_MODE_NONE, + .memtag_stack = 0, }; #define COMPILE_TIME_STRLEN(s) \ @@ -557,6 +558,8 @@ PARSE_AND_LIST_OPTIONS=' sync: Enable precise exceptions when mismatched address and\n\ allocation tags detected on load/store operations.\n\ async: Enable imprecise exceptions.\n")); + fprintf (file, _("\ + -z memtag-stack Mark program stack with MTE protection.\n")); ' PARSE_AND_LIST_ARGS_CASE_Z_AARCH64=' @@ -574,6 +577,8 @@ PARSE_AND_LIST_ARGS_CASE_Z_AARCH64=' {} else if (aarch64_parse_memtag_mode_option (optarg)) {} + else if (strcmp (optarg, "memtag-stack") == 0) + memtag_opts.memtag_stack = 1; ' PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_AARCH64" diff --git a/ld/ld.texi b/ld/ld.texi index f5350e799bb..413335ad765 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -8384,6 +8384,11 @@ implies precise exceptions, with the runtime providing the exact instruction where the fault occurred, and the exact faulting address. The @samp{async} mode implies imprecise exceptions. +@kindex -z memtag-stack +@cindex Mark program stack for MTE protection +The @samp{-z memtag-stack} specifies that output object uses MTE +instructions for stack memory usage. + @ifclear GENERIC @lowersections @end ifclear diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index 56e68c584fb..8d56beb64c7 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -378,6 +378,7 @@ run_dump_test_lp64 "variant_pcs-now" run_dump_test_lp64 "mte-tagged-frame" run_dump_test_lp64 "dt-memtag-mode" +run_dump_test_lp64 "dt-memtag-stack" set aarch64elflinktests { {"ld-aarch64/so with global symbol" "-shared" "" "" {copy-reloc-so.s} diff --git a/ld/testsuite/ld-aarch64/dt-memtag-stack.d b/ld/testsuite/ld-aarch64/dt-memtag-stack.d new file mode 100644 index 00000000000..242f61fa172 --- /dev/null +++ b/ld/testsuite/ld-aarch64/dt-memtag-stack.d @@ -0,0 +1,7 @@ +#source: dt-memtag.s +#ld: -shared -z memtag-stack +#readelf: -d + +#... + 0x000000007000000c \(AARCH64_MEMTAG_STACK\) 0x1 +#... -- 2.39.5