mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-01-23 02:14:37 +00:00
compel: gcs: initial GCS support for signal frames
Add basic prerequisites for Guarded Control Stack (GCS) state on AArch64. This adds a gcs_context to the signal frame and extends user_fpregs_struct_t to carry GCS metadata, preparing the groundwork for GCS in the parasite. For now, the GCS fields are zeroed during compel_get_task_regs(), technically ignoring GCS since it does not reach the control logic yet; that will be introduced in the next commit. The code path is gated and does not affect normal tests. Can be explicitly enabled and tested via: make -C infect GCS_ENABLE=1 && make -C infect run Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com> [ alex: clean up fixes ] Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com> Acked-by: Mike Rapoport <rppt@kernel.org>
This commit is contained in:
parent
73ca071483
commit
6bb856b0af
4 changed files with 70 additions and 1 deletions
|
|
@ -2,6 +2,7 @@
|
|||
#define UAPI_COMPEL_ASM_TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
|
@ -17,8 +18,18 @@
|
|||
|
||||
typedef struct user_pt_regs user_regs_struct_t;
|
||||
|
||||
/*
|
||||
* GCS (Guarded Control Stack)
|
||||
*/
|
||||
struct user_gcs {
|
||||
__u64 features_enabled;
|
||||
__u64 features_locked;
|
||||
__u64 gcspr_el0;
|
||||
};
|
||||
|
||||
struct user_fpregs_struct {
|
||||
struct user_fpsimd_state fpstate;
|
||||
struct user_gcs gcs;
|
||||
};
|
||||
typedef struct user_fpregs_struct user_fpregs_struct_t;
|
||||
|
||||
|
|
@ -43,4 +54,7 @@ typedef struct user_fpregs_struct user_fpregs_struct_t;
|
|||
__NR_##syscall; \
|
||||
})
|
||||
|
||||
extern bool __compel_host_supports_gcs(void);
|
||||
#define compel_host_supports_gcs __compel_host_supports_gcs
|
||||
|
||||
#endif /* UAPI_COMPEL_ASM_TYPES_H__ */
|
||||
|
|
|
|||
|
|
@ -10,11 +10,20 @@
|
|||
/* Copied from the kernel header arch/arm64/include/uapi/asm/sigcontext.h */
|
||||
|
||||
#define FPSIMD_MAGIC 0x46508001
|
||||
#define GCS_MAGIC 0x47435300
|
||||
|
||||
typedef struct fpsimd_context fpu_state_t;
|
||||
|
||||
struct gcs_context {
|
||||
struct _aarch64_ctx head;
|
||||
__u64 gcspr;
|
||||
__u64 features_enabled;
|
||||
__u64 reserved;
|
||||
};
|
||||
|
||||
struct aux_context {
|
||||
struct fpsimd_context fpsimd;
|
||||
struct gcs_context gcs;
|
||||
/* additional context to be added before "end" */
|
||||
struct _aarch64_ctx end;
|
||||
};
|
||||
|
|
@ -63,6 +72,7 @@ struct cr_sigcontext {
|
|||
#define RT_SIGFRAME_AUX_CONTEXT(rt_sigframe) ((struct aux_context *)&(RT_SIGFRAME_SIGCONTEXT(rt_sigframe)->__reserved))
|
||||
#define RT_SIGFRAME_FPU(rt_sigframe) (&RT_SIGFRAME_AUX_CONTEXT(rt_sigframe)->fpsimd)
|
||||
#define RT_SIGFRAME_OFFSET(rt_sigframe) 0
|
||||
#define RT_SIGFRAME_GCS(rt_sigframe) (&RT_SIGFRAME_AUX_CONTEXT(rt_sigframe)->gcs)
|
||||
|
||||
#define rt_sigframe_erase_sigset(sigframe) memset(&sigframe->uc.uc_sigmask, 0, sizeof(k_rtsigset_t))
|
||||
#define rt_sigframe_copy_sigset(sigframe, from) memcpy(&sigframe->uc.uc_sigmask, from, sizeof(k_rtsigset_t))
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <linux/elf.h>
|
||||
|
||||
#include <compel/plugins/std/syscall-codes.h>
|
||||
#include "common/page.h"
|
||||
|
|
@ -13,6 +13,8 @@
|
|||
#include "infect.h"
|
||||
#include "infect-priv.h"
|
||||
#include "asm/breakpoints.h"
|
||||
#include "asm/gcs-types.h"
|
||||
#include <linux/prctl.h>
|
||||
|
||||
unsigned __page_size = 0;
|
||||
unsigned __page_shift = 0;
|
||||
|
|
@ -33,12 +35,32 @@ static inline void __always_unused __check_code_syscall(void)
|
|||
BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
|
||||
}
|
||||
|
||||
bool __compel_host_supports_gcs(void)
|
||||
{
|
||||
unsigned long hwcap = getauxval(AT_HWCAP);
|
||||
return (hwcap & HWCAP_GCS) != 0;
|
||||
}
|
||||
|
||||
static bool __compel_gcs_enabled(struct user_gcs *gcs)
|
||||
{
|
||||
if (!compel_host_supports_gcs())
|
||||
return false;
|
||||
|
||||
if (gcs->features_enabled & PR_SHADOW_STACK_ENABLE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs)
|
||||
{
|
||||
struct fpsimd_context *fpsimd = RT_SIGFRAME_FPU(sigframe);
|
||||
struct gcs_context *gcs = RT_SIGFRAME_GCS(sigframe);
|
||||
|
||||
memcpy(sigframe->uc.uc_mcontext.regs, regs->regs, sizeof(regs->regs));
|
||||
|
||||
pr_debug("sigreturn_prep_regs_plain: sp %lx pc %lx\n", (long)regs->sp, (long)regs->pc);
|
||||
|
||||
sigframe->uc.uc_mcontext.sp = regs->sp;
|
||||
sigframe->uc.uc_mcontext.pc = regs->pc;
|
||||
sigframe->uc.uc_mcontext.pstate = regs->pstate;
|
||||
|
|
@ -51,6 +73,19 @@ int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, user_regs_struct_t *
|
|||
fpsimd->head.magic = FPSIMD_MAGIC;
|
||||
fpsimd->head.size = sizeof(*fpsimd);
|
||||
|
||||
if (__compel_gcs_enabled(&fpregs->gcs)) {
|
||||
gcs->head.magic = GCS_MAGIC;
|
||||
gcs->head.size = sizeof(*gcs);
|
||||
gcs->reserved = 0;
|
||||
gcs->gcspr = fpregs->gcs.gcspr_el0 - 8;
|
||||
gcs->features_enabled = fpregs->gcs.features_enabled;
|
||||
|
||||
pr_debug("sigframe gcspr=%llx features_enabled=%llx\n", fpregs->gcs.gcspr_el0 - 8, fpregs->gcs.features_enabled);
|
||||
} else {
|
||||
pr_debug("sigframe gcspr=[disabled]\n");
|
||||
memset(gcs, 0, sizeof(*gcs));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +116,8 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct
|
|||
goto err;
|
||||
}
|
||||
|
||||
memset(&ext_regs->gcs, 0, sizeof(ext_regs->gcs));
|
||||
|
||||
ret = save(pid, arg, regs, ext_regs);
|
||||
err:
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -192,6 +192,14 @@ void compel_set_thread_ip(struct parasite_thread_ctl *tctl, uint64_t v);
|
|||
|
||||
extern void compel_get_stack(struct parasite_ctl *ctl, void **rstack, void **r_thread_stack);
|
||||
|
||||
#ifndef compel_host_supports_gcs
|
||||
static inline bool compel_host_supports_gcs(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#define compel_host_supports_gcs
|
||||
#endif
|
||||
|
||||
#ifndef compel_shstk_enabled
|
||||
static inline bool compel_shstk_enabled(user_fpregs_struct_t *ext_regs)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue