[llvm] 191e062 - [JITLink][MachO][arm64] Don't lower ptrauth edges in noalloc-lifetime sections.
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 1 04:18:28 PDT 2025
Author: Lang Hames
Date: 2025-04-01T22:18:00+11:00
New Revision: 191e0622e84a215c1d632412561c2fe6ccd86170
URL: https://github.com/llvm/llvm-project/commit/191e0622e84a215c1d632412561c2fe6ccd86170
DIFF: https://github.com/llvm/llvm-project/commit/191e0622e84a215c1d632412561c2fe6ccd86170.diff
LOG: [JITLink][MachO][arm64] Don't lower ptrauth edges in noalloc-lifetime sections.
Ptrauth relocations can only be fixed up in the executing process, but noalloc
sections do not have any memory in the executing process. Failure to skip
ptrauth edges results in signing instructions that operate on invalid addresses,
leading to segfaults or data corruption.
Ignoring noalloc sections for ptrauth lowering purposes allows the ptrauth
edges to persist until they reach the applyFixup method, at which point they
raise a useful error and cleanly terminate linking.
Added:
llvm/test/ExecutionEngine/JITLink/AArch64/MachO_ptrauth_noolloc_sections.yaml
Modified:
llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
Removed:
################################################################################
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
index 8ce7e74d67cde..fbeb920f4e189 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
@@ -240,10 +240,20 @@ Error createEmptyPointerSigningFunction(LinkGraph &G) {
// info encoded in the addend -- the only actually unknown quantity is the
// fixup location, and we can probably put constraints even on that.
size_t NumPtrAuthFixupLocations = 0;
- for (auto *B : G.blocks())
- for (auto &E : B->edges())
- NumPtrAuthFixupLocations +=
- E.getKind() == aarch64::Pointer64Authenticated;
+ for (auto &Sec : G.sections()) {
+
+ // No-alloc sections can't have ptrauth edges. We don't need to error out
+ // here: applyFixup will catch these edges if any make it to the fixup
+ // stage.
+ if (Sec.getMemLifetime() == orc::MemLifetime::NoAlloc)
+ continue;
+
+ for (auto *B : Sec.blocks()) {
+ for (auto &E : B->edges())
+ NumPtrAuthFixupLocations +=
+ E.getKind() == aarch64::Pointer64Authenticated;
+ }
+ }
constexpr size_t MaxPtrSignSeqLength =
4 + // To materialize the value to sign.
@@ -316,58 +326,65 @@ Error lowerPointer64AuthEdgesToSigningFunction(LinkGraph &G) {
return InstrWriter.writeInteger(Instr);
};
- for (auto *B : G.blocks()) {
- for (auto &E : B->edges()) {
- // We're only concerned with Pointer64Authenticated edges here.
- if (E.getKind() != aarch64::Pointer64Authenticated)
- continue;
-
- uint64_t EncodedInfo = E.getAddend();
- int32_t RealAddend = (uint32_t)(EncodedInfo & 0xffffffff);
- auto ValueToSign = E.getTarget().getAddress() + RealAddend;
- if (!ValueToSign) {
- LLVM_DEBUG(dbgs() << " " << B->getFixupAddress(E) << " <- null\n");
- E.setAddend(RealAddend);
- E.setKind(aarch64::Pointer64);
- continue;
- }
+ for (auto &Sec : G.sections()) {
+
+ if (Sec.getMemLifetime() == orc::MemLifetime::NoAlloc)
+ continue;
- uint32_t InitialDiscriminator = (EncodedInfo >> 32) & 0xffff;
- bool AddressDiversify = (EncodedInfo >> 48) & 0x1;
- uint32_t Key = (EncodedInfo >> 49) & 0x3;
- uint32_t HighBits = EncodedInfo >> 51;
-
- if (HighBits != 0x1000)
- return make_error<JITLinkError>(
- "Pointer64Auth edge at " +
- formatv("{0:x}", B->getFixupAddress(E).getValue()) +
- " has invalid encoded addend " + formatv("{0:x}", EncodedInfo));
-
- LLVM_DEBUG({
- const char *const KeyNames[] = {"IA", "IB", "DA", "DB"};
- dbgs() << " " << B->getFixupAddress(E) << " <- " << ValueToSign
- << " : key = " << KeyNames[Key] << ", discriminator = "
- << formatv("{0:x4}", InitialDiscriminator)
- << ", address diversified = "
- << (AddressDiversify ? "yes" : "no") << "\n";
- });
-
- // Materialize pointer value.
- cantFail(writeMovRegImm64Seq(AppendInstr, Reg1, ValueToSign.getValue()));
-
- // Materialize fixup pointer.
- cantFail(writeMovRegImm64Seq(AppendInstr, Reg2,
- B->getFixupAddress(E).getValue()));
-
- // Write signing instruction(s).
- cantFail(writePACSignSeq(AppendInstr, Reg1, ValueToSign, Reg2, Reg3, Key,
- InitialDiscriminator, AddressDiversify));
-
- // Store signed pointer.
- cantFail(writeStoreRegSeq(AppendInstr, Reg2, Reg1));
-
- // Replace edge with a keep-alive to preserve dependence info.
- E.setKind(Edge::KeepAlive);
+ for (auto *B : Sec.blocks()) {
+ for (auto &E : B->edges()) {
+ // We're only concerned with Pointer64Authenticated edges here.
+ if (E.getKind() != aarch64::Pointer64Authenticated)
+ continue;
+
+ uint64_t EncodedInfo = E.getAddend();
+ int32_t RealAddend = (uint32_t)(EncodedInfo & 0xffffffff);
+ auto ValueToSign = E.getTarget().getAddress() + RealAddend;
+ if (!ValueToSign) {
+ LLVM_DEBUG(dbgs() << " " << B->getFixupAddress(E) << " <- null\n");
+ E.setAddend(RealAddend);
+ E.setKind(aarch64::Pointer64);
+ continue;
+ }
+
+ uint32_t InitialDiscriminator = (EncodedInfo >> 32) & 0xffff;
+ bool AddressDiversify = (EncodedInfo >> 48) & 0x1;
+ uint32_t Key = (EncodedInfo >> 49) & 0x3;
+ uint32_t HighBits = EncodedInfo >> 51;
+
+ if (HighBits != 0x1000)
+ return make_error<JITLinkError>(
+ "Pointer64Auth edge at " +
+ formatv("{0:x}", B->getFixupAddress(E).getValue()) +
+ " has invalid encoded addend " + formatv("{0:x}", EncodedInfo));
+
+ LLVM_DEBUG({
+ const char *const KeyNames[] = {"IA", "IB", "DA", "DB"};
+ dbgs() << " " << B->getFixupAddress(E) << " <- " << ValueToSign
+ << " : key = " << KeyNames[Key] << ", discriminator = "
+ << formatv("{0:x4}", InitialDiscriminator)
+ << ", address diversified = "
+ << (AddressDiversify ? "yes" : "no") << "\n";
+ });
+
+ // Materialize pointer value.
+ cantFail(
+ writeMovRegImm64Seq(AppendInstr, Reg1, ValueToSign.getValue()));
+
+ // Materialize fixup pointer.
+ cantFail(writeMovRegImm64Seq(AppendInstr, Reg2,
+ B->getFixupAddress(E).getValue()));
+
+ // Write signing instruction(s).
+ cantFail(writePACSignSeq(AppendInstr, Reg1, ValueToSign, Reg2, Reg3,
+ Key, InitialDiscriminator, AddressDiversify));
+
+ // Store signed pointer.
+ cantFail(writeStoreRegSeq(AppendInstr, Reg2, Reg1));
+
+ // Replace edge with a keep-alive to preserve dependence info.
+ E.setKind(Edge::KeepAlive);
+ }
}
}
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/MachO_ptrauth_noolloc_sections.yaml b/llvm/test/ExecutionEngine/JITLink/AArch64/MachO_ptrauth_noolloc_sections.yaml
new file mode 100644
index 0000000000000..a2396aa776e10
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/MachO_ptrauth_noolloc_sections.yaml
@@ -0,0 +1,136 @@
+# RUN: yaml2obj %s -o %t
+# RUN: not llvm-jitlink -noexec %t 2>&1 | FileCheck %s
+#
+# Check that ptrauth edges are _not_ lowered for noalloc sections.
+#
+# Ptrauth edges are lowered to signing function instructions, so any ptrauth
+# edge in a noalloc section will introduce signing instructions that operate
+# illegally on linker working memory, rather than executor memory (this will
+# usually lead to a crash, but may silently corrupt memory in in-process JITs).
+#
+# By ignoring these edges during ptrauth lowering we prevent illegal signing
+# instructions from being generated, and the ptrauth edges error out in
+# applyFixup instead.
+#
+
+# CHECK: llvm-jitlink error: {{.*}} unsupported edge kind Pointer64Authenticated
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x100000C
+ cpusubtype: 0x80000002
+ filetype: 0x1
+ ncmds: 4
+ sizeofcmds: 440
+ flags: 0x2000
+ reserved: 0x0
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 312
+ segname: ''
+ vmaddr: 0
+ vmsize: 16
+ fileoff: 472
+ filesize: 16
+ maxprot: 7
+ initprot: 7
+ nsects: 2
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0
+ size: 8
+ offset: 0x1D8
+ align: 2
+ reloff: 0x0
+ nreloc: 0
+ flags: 0x80000400
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: 00008052C0035FD6
+ - sectname: __debug_stuff
+ segname: __DWARF
+ addr: 0x8
+ size: 8
+ offset: 0x1E0
+ align: 3
+ reloff: 0x1E8
+ nreloc: 1
+ flags: 0x2000000
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: '0000000000000080'
+ relocations:
+ - address: 0x0
+ symbolnum: 3
+ pcrel: false
+ length: 3
+ extern: true
+ type: 11
+ scattered: false
+ value: 0
+ - cmd: LC_BUILD_VERSION
+ cmdsize: 24
+ platform: 1
+ minos: 983040
+ sdk: 0
+ ntools: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 496
+ nsyms: 4
+ stroff: 560
+ strsize: 24
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 2
+ iextdefsym: 2
+ nextdefsym: 2
+ iundefsym: 4
+ nundefsym: 0
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+LinkEditData:
+ NameList:
+ - n_strx: 18
+ n_type: 0xE
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+ - n_strx: 12
+ n_type: 0xE
+ n_sect: 2
+ n_desc: 0
+ n_value: 8
+ - n_strx: 1
+ n_type: 0xF
+ n_sect: 2
+ n_desc: 0
+ n_value: 8
+ - n_strx: 6
+ n_type: 0xF
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+ StringTable:
+ - ''
+ - _foo
+ - _main
+ - ltmp1
+ - ltmp0
+...
More information about the llvm-commits
mailing list