]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
ld/aarch64elf: add support for DT_AARCH64_MEMTAG_STACK dynamic tag users/ibhagat/try-mte-rfc-v2
authorIndu Bhagat <indu.bhagat@oracle.com>
Wed, 4 Dec 2024 21:45:25 +0000 (13:45 -0800)
committerIndu Bhagat <indu.bhagat@oracle.com>
Fri, 11 Apr 2025 03:54:24 +0000 (20:54 -0700)
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 <exectutable>
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
...                 ...                 ...

TBD:
1. Error/Warn if user says -z memtag-stack but does not select a
   mode ?
2. Should ld check that all input ELF components were compiled with
   -fsanitize=memtag-stack ? If yes, we likely need something like
   GNU_PROPERTY_AARCH64_FEATURE_1_MEMTAG_STACK specified in the ABI.
   Should we then allow the user to select the desirable action like we
   do in other cases, via say memtag-report[=none|warning|error] ?

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
bfd/elfxx-aarch64.h
binutils/readelf.c
include/elf/aarch64.h
ld/emultempl/aarch64elf.em
ld/ld.texi
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/dt-memtag-stack.d [new file with mode: 0644]

index 9a4d15b4ce32947a6c4eeac59ecbdc080518899d..69035a8ff000677695a682e251786cb3777646ad 100644 (file)
@@ -9784,6 +9784,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
index 64ab39edb718d0da21337a059e2446f577ff6bc5..bed976e91c8a3c6a58f5389f73181b0c6c1623b4 100644 (file)
@@ -145,6 +145,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;
index 1a74588087c29d2141e5690960570f7d6d231338..3a1fbffd1359d7c26419ea94fb6ab00925313205 100644 (file)
@@ -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;
index 129aef9a524dd3d101de088cb263d5e5d564c385..a4ef11184021c4e30e662d8d53f282b331474b6c 100644 (file)
@@ -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
index dcf314c1a211693fa663404661e9a3fdd28745f4..a2c20682e6fd5918736c18ef1bf07b181f8e0f41 100644 (file)
@@ -43,6 +43,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) \
@@ -556,6 +557,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='
@@ -573,6 +576,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"
 
index 763dce22af8b3ee803aee3a2646228bede0c07cb..0283acaedc7afff46e855effccd5e9dd7786a17b 100644 (file)
@@ -8380,6 +8380,11 @@ dynamic tag.  The @samp{sync} mode 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
index 56e68c584fb28fbcfc8c8461870be1f263d031df..8d56beb64c7b26095b43fe39f69754eb9b6a2f11 100644 (file)
@@ -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 (file)
index 0000000..242f61f
--- /dev/null
@@ -0,0 +1,7 @@
+#source: dt-memtag.s
+#ld: -shared -z memtag-stack
+#readelf: -d
+
+#...
+ 0x000000007000000c \(AARCH64_MEMTAG_STACK\) 0x1
+#...