Skip to content

Commit 7ec3b57

Browse files
brooniectmarinas
authored andcommitted
arm64/ptrace: Expose GCS via ptrace and core files
Provide a new register type NT_ARM_GCS reporting the current GCS mode and pointer for EL0. Due to the interactions with allocation and deallocation of Guarded Control Stacks we do not permit any changes to the GCS mode via ptrace, only GCSPR_EL0 may be changed. Reviewed-by: Thiago Jung Bauermann <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Signed-off-by: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 16f47bb commit 7ec3b57

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

arch/arm64/include/uapi/asm/ptrace.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,14 @@ struct user_za_header {
324324
#define ZA_PT_SIZE(vq) \
325325
(ZA_PT_ZA_OFFSET + ZA_PT_ZA_SIZE(vq))
326326

327+
/* GCS state (NT_ARM_GCS) */
328+
329+
struct user_gcs {
330+
__u64 features_enabled;
331+
__u64 features_locked;
332+
__u64 gcspr_el0;
333+
};
334+
327335
#endif /* __ASSEMBLY__ */
328336

329337
#endif /* _UAPI__ASM_PTRACE_H */

arch/arm64/kernel/ptrace.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <asm/cpufeature.h>
3535
#include <asm/debug-monitors.h>
3636
#include <asm/fpsimd.h>
37+
#include <asm/gcs.h>
3738
#include <asm/mte.h>
3839
#include <asm/pointer_auth.h>
3940
#include <asm/stacktrace.h>
@@ -1473,6 +1474,52 @@ static int poe_set(struct task_struct *target, const struct
14731474
}
14741475
#endif
14751476

1477+
#ifdef CONFIG_ARM64_GCS
1478+
static int gcs_get(struct task_struct *target,
1479+
const struct user_regset *regset,
1480+
struct membuf to)
1481+
{
1482+
struct user_gcs user_gcs;
1483+
1484+
if (!system_supports_gcs())
1485+
return -EINVAL;
1486+
1487+
if (target == current)
1488+
gcs_preserve_current_state();
1489+
1490+
user_gcs.features_enabled = target->thread.gcs_el0_mode;
1491+
user_gcs.features_locked = target->thread.gcs_el0_locked;
1492+
user_gcs.gcspr_el0 = target->thread.gcspr_el0;
1493+
1494+
return membuf_write(&to, &user_gcs, sizeof(user_gcs));
1495+
}
1496+
1497+
static int gcs_set(struct task_struct *target, const struct
1498+
user_regset *regset, unsigned int pos,
1499+
unsigned int count, const void *kbuf, const
1500+
void __user *ubuf)
1501+
{
1502+
int ret;
1503+
struct user_gcs user_gcs;
1504+
1505+
if (!system_supports_gcs())
1506+
return -EINVAL;
1507+
1508+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &user_gcs, 0, -1);
1509+
if (ret)
1510+
return ret;
1511+
1512+
if (user_gcs.features_enabled & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK)
1513+
return -EINVAL;
1514+
1515+
target->thread.gcs_el0_mode = user_gcs.features_enabled;
1516+
target->thread.gcs_el0_locked = user_gcs.features_locked;
1517+
target->thread.gcspr_el0 = user_gcs.gcspr_el0;
1518+
1519+
return 0;
1520+
}
1521+
#endif
1522+
14761523
enum aarch64_regset {
14771524
REGSET_GPR,
14781525
REGSET_FPR,
@@ -1503,7 +1550,10 @@ enum aarch64_regset {
15031550
REGSET_TAGGED_ADDR_CTRL,
15041551
#endif
15051552
#ifdef CONFIG_ARM64_POE
1506-
REGSET_POE
1553+
REGSET_POE,
1554+
#endif
1555+
#ifdef CONFIG_ARM64_GCS
1556+
REGSET_GCS,
15071557
#endif
15081558
};
15091559

@@ -1674,6 +1724,16 @@ static const struct user_regset aarch64_regsets[] = {
16741724
.set = poe_set,
16751725
},
16761726
#endif
1727+
#ifdef CONFIG_ARM64_GCS
1728+
[REGSET_GCS] = {
1729+
.core_note_type = NT_ARM_GCS,
1730+
.n = sizeof(struct user_gcs) / sizeof(u64),
1731+
.size = sizeof(u64),
1732+
.align = sizeof(u64),
1733+
.regset_get = gcs_get,
1734+
.set = gcs_set,
1735+
},
1736+
#endif
16771737
};
16781738

16791739
static const struct user_regset_view user_aarch64_view = {

include/uapi/linux/elf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ typedef struct elf64_shdr {
443443
#define NT_ARM_ZT 0x40d /* ARM SME ZT registers */
444444
#define NT_ARM_FPMR 0x40e /* ARM floating point mode register */
445445
#define NT_ARM_POE 0x40f /* ARM POE registers */
446+
#define NT_ARM_GCS 0x410 /* ARM GCS state */
446447
#define NT_ARC_V2 0x600 /* ARCv2 accumulator/extra registers */
447448
#define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note */
448449
#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */

0 commit comments

Comments
 (0)