mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-01-23 02:14:37 +00:00
criu/restore: gcs: adds restore implementation for Guarded Control Stack
This commit finalizes AArch64 Guarded Control Stack (GCS)
support by wiring the full dump and restore flow.
The restore path adds the following steps:
- Define shared AArch64 GCS types and constants in a dedicated header
for both compel and CRIU inclusion
- compel: add get/set NT_ARM_GCS via ptrace, enabling user-space
GCS state save and restore.
- During restore switch to the new GCS (via GCSSTR) to place capability
token sa_restorer address
- arch_shstk_trampoline() — We enable GCS in a trampoline that using
prctl(PR_SET_SHADOW_STACK_STATUS, ...) via inline SVC. The trampoline
ineeded because we can’t RET without a valid GCS.
- restorer: map the recorded GCS VMA, populate contents top-down with
GCSSTR, write the signal capability at GCSPR_EL0 and the valid token at
GCSPR_EL0-8, then switch to the rebuilt GCS (GCSSS1)
- Save and restore registers via ptrace
- Extend restorer argument structures to carry GCS state
into post-restore execution
- Add shstk_set_restorer_stack(): sets tmp_gcs to temporary restorer
shadow stack start
- Add gcs_vma_restore implementation (required for mremap of the GCS VMA)
Tested with:
GCS_ENABLE=1 ./zdtm.py run -t zdtm/static/env00
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
This commit is contained in:
parent
2429d49e67
commit
d591e320e0
7 changed files with 387 additions and 0 deletions
|
|
@ -136,6 +136,9 @@ int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs)
|
|||
{
|
||||
struct iovec iov;
|
||||
|
||||
struct user_gcs gcs;
|
||||
struct iovec gcs_iov = { .iov_base = &gcs, .iov_len = sizeof(gcs) };
|
||||
|
||||
pr_info("Restoring GP/FPU registers for %d\n", pid);
|
||||
|
||||
iov.iov_base = &ext_regs->fpstate;
|
||||
|
|
@ -144,6 +147,33 @@ int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs)
|
|||
pr_perror("Failed to set FPU registers for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ptrace(PTRACE_GETREGSET, pid, NT_ARM_GCS, &gcs_iov) < 0) {
|
||||
pr_warn("gcs: Failed to get GCS for %d\n", pid);
|
||||
} else {
|
||||
ext_regs->gcs = gcs;
|
||||
compel_set_task_gcs_regs(pid, ext_regs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int compel_set_task_gcs_regs(pid_t pid, user_fpregs_struct_t *ext_regs)
|
||||
{
|
||||
struct iovec iov;
|
||||
|
||||
pr_info("gcs: restoring GCS registers for %d\n", pid);
|
||||
pr_info("gcs: restoring GCS: gcspr=%llx features=%llx\n",
|
||||
ext_regs->gcs.gcspr_el0, ext_regs->gcs.features_enabled);
|
||||
|
||||
iov.iov_base = &ext_regs->gcs;
|
||||
iov.iov_len = sizeof(ext_regs->gcs);
|
||||
|
||||
if (ptrace(PTRACE_SETREGSET, pid, NT_ARM_GCS, &iov)) {
|
||||
pr_perror("gcs: Failed to set GCS registers for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,3 +124,4 @@ openat2 437 437 (int dirfd, char *pathname, struct open_how *how, size_t size
|
|||
pidfd_getfd 438 438 (int pidfd, int targetfd, unsigned int flags)
|
||||
rseq 293 398 (void *rseq, uint32_t rseq_len, int flags, uint32_t sig)
|
||||
membarrier 283 389 (int cmd, unsigned int flags, int cpu_id)
|
||||
map_shadow_stack 453 ! (unsigned long addr, unsigned long size, unsigned int flags)
|
||||
|
|
@ -72,6 +72,7 @@ extern bool arch_can_dump_task(struct parasite_ctl *ctl);
|
|||
extern int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *ext_regs, save_regs_t save,
|
||||
void *arg, unsigned long flags);
|
||||
extern int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs);
|
||||
extern int compel_set_task_gcs_regs(pid_t pid, user_fpregs_struct_t *ext_regs);
|
||||
extern int arch_fetch_sas(struct parasite_ctl *ctl, struct rt_sigframe *s);
|
||||
extern int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, user_regs_struct_t *regs,
|
||||
user_fpregs_struct_t *fpregs);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue