Skip to content

Commit b835bbd

Browse files
authored
Advertise pointer authentication support to GDB (#4073)
* Advertise pointer authentication support to GDB GDB uses the values of the provided pointer authentication mask registers to mask return addresses from the stack trace. Because we weren't providing these masks, the return addresses in the stack trace were incorrect in programs built with -mbranch-protection=pac-ret, such as most of Fedora. Fix it by advertising pointer authentication to GDB, and providing the correct masks. Fixes the following tests on PAC platforms: fork_exec_info_thr fork_exec_info_thr-no-syscallbuf vdso_clock_gettime_stack vdso_time_stack * Only include the pauth registers in target_registers() if they're present.
1 parent b32fc69 commit b835bbd

8 files changed

Lines changed: 46 additions & 3 deletions

src/ExtraRegisters.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,21 @@ size_t ExtraRegisters::read_register(uint8_t* buf, GdbServerRegister regno,
275275
} else if (regno == DREG_FPCR) {
276276
reg_data = RegData(offsetof(ARM64Arch::user_fpsimd_state, fpcr),
277277
sizeof(uint32_t));
278+
#ifdef __aarch64__
279+
} else if (regno == DREG_PAUTH_DMASK || regno == DREG_PAUTH_CMASK) {
280+
uint64_t ptr = 1ULL << 55;
281+
// The XPAC instruction will copy bit 55 of the argument into the PAC mask
282+
// bits, so ptr will be set to the mask plus bit 55.
283+
if (regno == DREG_PAUTH_DMASK) {
284+
__asm__ __volatile__("xpacd %0" : "+r"(ptr));
285+
} else {
286+
__asm__ __volatile__("xpaci %0" : "+r"(ptr));
287+
}
288+
uint64_t mask = ptr & ~(1ULL << 55);
289+
*defined = true;
290+
memcpy(buf, &mask, sizeof(mask));
291+
return sizeof(mask);
292+
#endif
278293
} else {
279294
*defined = false;
280295
return 0;

src/GdbServer.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2332,6 +2332,7 @@ const vector<GdbServerRegister>& GdbServer::target_registers(
23322332
bool have_PKU = dbg->cpu_features() & GdbServerConnection::CPU_PKU;
23332333
bool have_AVX = dbg->cpu_features() & GdbServerConnection::CPU_AVX;
23342334
bool have_AVX512 = dbg->cpu_features() & GdbServerConnection::CPU_AVX512;
2335+
bool have_PAUTH = dbg->cpu_features() & GdbServerConnection::CPU_PAUTH;
23352336
switch (arch) {
23362337
case x86: {
23372338
add_range(GdbServerRegister(0), GdbServerRegister(DREG_ORIG_EAX));
@@ -2368,7 +2369,11 @@ const vector<GdbServerRegister>& GdbServer::target_registers(
23682369
}
23692370
case aarch64:
23702371
add_range(GdbServerRegister::DREG_X0,
2371-
GdbServerRegister::DREG_NUM_LINUX_AARCH64);
2372+
GdbServerRegister::DREG_FPCR);
2373+
if (have_PAUTH) {
2374+
register_description.push_back(DREG_PAUTH_DMASK);
2375+
register_description.push_back(DREG_PAUTH_CMASK);
2376+
}
23722377
break;
23732378
default:
23742379
FATAL() << "Unknown architecture";

src/GdbServerConnection.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <poll.h>
1919
#include <stdio.h>
2020
#include <stdlib.h>
21+
#include <sys/auxv.h>
2122
#include <sys/mman.h>
2223
#include <sys/socket.h>
2324
#include <sys/types.h>
@@ -32,6 +33,7 @@
3233
#include "ScopedFd.h"
3334
#include "TargetDescription.h"
3435
#include "core.h"
36+
#include "kernel_supplement.h"
3537
#include "log.h"
3638

3739
using namespace std;
@@ -106,6 +108,11 @@ static uint32_t get_cpu_features(SupportedArch arch) {
106108
}
107109
case aarch64:
108110
cpu_features = GdbServerConnection::CPU_AARCH64;
111+
#ifdef __aarch64__
112+
if (getauxval(AT_HWCAP) & HWCAP_PACA) {
113+
cpu_features |= GdbServerConnection::CPU_PAUTH;
114+
}
115+
#endif
109116
break;
110117
default:
111118
FATAL() << "Unknown architecture";

src/GdbServerConnection.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,8 @@ class GdbServerConnection {
752752
CPU_AVX = 1 << 1,
753753
CPU_AARCH64 = 1 << 2,
754754
CPU_PKU = 1 << 3,
755-
CPU_AVX512 = 1 << 4
755+
CPU_AVX512 = 1 << 4,
756+
CPU_PAUTH = 1 << 5
756757
};
757758

758759
void set_cpu_features(SupportedArch arch);

src/GdbServerRegister.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,11 @@ enum GdbServerRegister {
320320
DREG_FPSR,
321321
DREG_FPCR,
322322

323-
DREG_NUM_LINUX_AARCH64 = DREG_FPCR + 1,
323+
// aarch64-pauth.xml
324+
DREG_PAUTH_DMASK,
325+
DREG_PAUTH_CMASK,
326+
327+
DREG_NUM_LINUX_AARCH64,
324328
};
325329

326330
} // namespace rr

src/TargetDescription.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ FeatureStream& operator<<(FeatureStream& stream, TargetFeature feature) {
7878
case TargetFeature::FPU:
7979
stream << "fpu.xml";
8080
break;
81+
case TargetFeature::PAuth:
82+
stream << "pauth.xml";
83+
break;
8184
}
8285
stream << R"("/>)" << '\n';
8386
return stream;
@@ -103,6 +106,9 @@ TargetDescription::TargetDescription(rr::SupportedArch arch,
103106
case rr::aarch64:
104107
target_features.push_back(TargetFeature::Core);
105108
target_features.push_back(TargetFeature::FPU);
109+
if (cpu_features & rr::GdbServerConnection::CPU_PAUTH) {
110+
target_features.push_back(TargetFeature::PAuth);
111+
}
106112
break;
107113
}
108114

src/TargetDescription.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ enum class TargetFeature : uint32_t {
2020
AVX512,
2121
PKeys,
2222
FPU,
23+
PAuth,
2324
};
2425

2526
class TargetDescription {

src/kernel_supplement.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ enum _ptrace_get_syscall_info_op {
148148
#define NT_ARM_PACG_KEYS 0x408
149149
#endif
150150

151+
#ifndef HWCAP_PACA
152+
#define HWCAP_PACA (1 << 30)
153+
#endif
154+
151155
// These are defined by the include/linux/errno.h in the kernel tree.
152156
// Since userspace doesn't see these errnos in normal operation, that
153157
// header apparently isn't distributed with libc.

0 commit comments

Comments
 (0)