Skip to content

[PAC][lld] Use braa instr in PAC PLT sequence with valid PAuth core info #113945

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions lld/ELF/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,11 @@ class AArch64BtiPac final : public AArch64 {

private:
bool btiHeader; // bti instruction needed in PLT Header and Entry
bool pacEntry; // autia1716 instruction needed in PLT Entry
enum {
PEK_NoAuth,
PEK_AuthHint, // use autia1716 instr for authenticated branch in PLT entry
PEK_Auth, // use braa instr for authenticated branch in PLT entry
} pacEntryKind;
};
} // namespace

Expand All @@ -1014,9 +1018,21 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) {
// relocations.
// The PAC PLT entries require dynamic loader support and this isn't known
// from properties in the objects, so we use the command line flag.
pacEntry = ctx.arg.zPacPlt;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be worth adding to the comment here. Something like:

By default we only use hint-space instructions, but if we detect the PAuthABI, which requires v8.3-A we can use the non-hint space instructions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added, thanks, see b189f51

// By default we only use hint-space instructions, but if we detect the
// PAuthABI, which requires v8.3-A, we can use the non-hint space
// instructions.

if (ctx.arg.zPacPlt) {
if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo,
[](uint8_t c) { return c != 0; }))
pacEntryKind = PEK_Auth;
else
pacEntryKind = PEK_AuthHint;
} else {
pacEntryKind = PEK_NoAuth;
}

if (btiHeader || pacEntry) {
if (btiHeader || (pacEntryKind != PEK_NoAuth)) {
pltEntrySize = 24;
ipltEntrySize = 24;
}
Expand Down Expand Up @@ -1066,9 +1082,13 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.got.plt[n]))]
0x10, 0x02, 0x00, 0x91 // add x16, x16, Offset(&(.got.plt[n]))
};
const uint8_t pacHintBr[] = {
0x9f, 0x21, 0x03, 0xd5, // autia1716
0x20, 0x02, 0x1f, 0xd6 // br x17
};
const uint8_t pacBr[] = {
0x9f, 0x21, 0x03, 0xd5, // autia1716
0x20, 0x02, 0x1f, 0xd6 // br x17
0x30, 0x0a, 0x1f, 0xd7, // braa x17, x16
0x1f, 0x20, 0x03, 0xd5 // nop
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe UDF instruction is a safer choice instead of NOP. also may not have any significance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a nice suggestion, but I'll apply it in a separate PR not to mix different changes - nop is present both in pacBr and stdBr, while the current PR is intended to change only pacBr.

};
const uint8_t stdBr[] = {
0x20, 0x02, 0x1f, 0xd6, // br x17
Expand Down Expand Up @@ -1096,8 +1116,10 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
relocateNoSym(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr);
relocateNoSym(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr);

if (pacEntry)
memcpy(buf + sizeof(addrInst), pacBr, sizeof(pacBr));
if (pacEntryKind != PEK_NoAuth)
memcpy(buf + sizeof(addrInst),
pacEntryKind == PEK_AuthHint ? pacHintBr : pacBr,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be a possibility to make pacHintBr and pacBr into an array indexed by pacEntryKind.

memcpy(buf + sizeof(addrInst),
  pacBrInstrs[pacEntryKind],
  sizeof(pacBrInstrs[pacEntryKind]));

Not sure if it is worth the trouble though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for suggestion. I think I'll leave this "as is" w/o changes - it looks like that a pretty small decrease in code length here will require increase in complexity by introducing invariants on enum values and increase in code length somewhere else.

sizeof(pacEntryKind == PEK_AuthHint ? pacHintBr : pacBr));
else
memcpy(buf + sizeof(addrInst), stdBr, sizeof(stdBr));
if (!hasBti)
Expand Down
10 changes: 6 additions & 4 deletions lld/test/ELF/aarch64-feature-pauth.s
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@

# PACPLTTAG: 0x0000000070000003 (AARCH64_PAC_PLT)

# RUN: llvm-objdump -d pacplt-nowarn | FileCheck --check-prefix PACPLT -DA=10380 -DB=478 -DC=480 %s
# RUN: llvm-objdump -d pacplt-warn | FileCheck --check-prefix PACPLT -DA=10390 -DB=488 -DC=490 %s
# RUN: llvm-objdump -d pacplt-nowarn | FileCheck --check-prefixes=PACPLT,NOHINT -DA=10380 -DB=478 -DC=480 %s
# RUN: llvm-objdump -d pacplt-warn | FileCheck --check-prefixes=PACPLT,HINT -DA=10390 -DB=488 -DC=490 %s

# PACPLT: Disassembly of section .text:
# PACPLT: <func2>:
Expand All @@ -77,8 +77,10 @@
# PACPLT-NEXT: adrp x16, 0x30000 <func3+0x30000>
# PACPLT-NEXT: ldr x17, [x16, #0x[[C]]]
# PACPLT-NEXT: add x16, x16, #0x[[C]]
# PACPLT-NEXT: autia1716
# PACPLT-NEXT: br x17
# NOHINT-NEXT: braa x17, x16
# NOHINT-NEXT: nop
# HINT-NEXT: autia1716
# HINT-NEXT: br x17
# PACPLT-NEXT: nop

#--- abi-tag-short.s
Expand Down
Loading