criu/compel/include/infect-priv.h
Igor Svilenkov Bozic d591e320e0 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>
2025-12-07 19:20:00 +01:00

81 lines
2.5 KiB
C

#ifndef __COMPEL_INFECT_PRIV_H__
#define __COMPEL_INFECT_PRIV_H__
#include <stdbool.h>
#define BUILTIN_SYSCALL_SIZE 8
struct thread_ctx {
k_rtsigset_t sigmask;
user_regs_struct_t regs;
#ifdef ARCH_HAS_PTRACE_GET_THREAD_AREA
tls_t tls;
#endif
user_fpregs_struct_t ext_regs;
};
/* parasite control block */
struct parasite_ctl {
int rpid; /* Real pid of the victim */
void *remote_map;
void *local_map;
void *sigreturn_addr; /* A place for the breakpoint */
unsigned long map_length;
struct infect_ctx ictx;
/* thread leader data */
bool daemonized;
struct thread_ctx orig;
void *rstack; /* thread leader stack*/
struct rt_sigframe *sigframe;
struct rt_sigframe *rsigframe; /* address in a parasite */
void *r_thread_stack; /* stack for non-leader threads */
unsigned long parasite_ip; /* service routine start ip */
unsigned int *cmd; /* address for command */
void *args; /* address for arguments */
unsigned long args_size;
int tsock; /* transport socket for transferring fds */
struct parasite_blob_desc pblob;
};
struct parasite_thread_ctl {
int tid;
struct parasite_ctl *ctl;
struct thread_ctx th;
};
#define MEMFD_FNAME "CRIUMFD"
#define MEMFD_FNAME_SZ sizeof(MEMFD_FNAME)
struct ctl_msg;
int parasite_wait_ack(int sockfd, unsigned int cmd, struct ctl_msg *m);
extern void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
extern void *remote_mmap(struct parasite_ctl *ctl, void *addr, size_t length, int prot, int flags, int fd,
off_t offset);
extern bool arch_can_dump_task(struct parasite_ctl *ctl);
/*
* @regs: general purpose registers
* @ext_regs: extended register set (fpu/mmx/sse/etc)
* for task that is NULL, restored by sigframe on rt_sigreturn()
* @save: callback to dump all info
* @flags: see INFECT_* in infect_ctx::flags
* @pid: mystery
*/
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);
extern int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, struct rt_sigframe *rsigframe);
extern int compel_execute_syscall(struct parasite_ctl *ctl, user_regs_struct_t *regs, const char *code_syscall);
#endif