2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 06:15:24 +00:00

compel: shstk: prepare shadow stack signal frame

When calling sigreturn with CET enabled, the kernel verifies that the
shadow stack has proper address of sa_restorer and a "restore token".
Normally, they pushed to the shadow stack when signal processing is
started.

Since compel calls sigreturn directly, the shadow stack should be
updated to match the kernel expectations for sigreturn invocation.

Add parasite_setup_shstk() that sets up the shadow stack with the
address of __export_parasite_head_start as sa_restorer and with the
required restore token.

Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
This commit is contained in:
Mike Rapoport (IBM)
2022-05-15 21:06:50 +03:00
committed by Andrei Vagin
parent eee2236507
commit a09a0eb081
4 changed files with 61 additions and 0 deletions

View File

@@ -146,4 +146,8 @@ typedef struct xsave_struct user_fpregs_struct_t;
extern bool __compel_shstk_enabled(user_fpregs_struct_t *ext_regs);
#define compel_shstk_enabled __compel_shstk_enabled
extern int __parasite_setup_shstk(struct parasite_ctl *ctl,
user_fpregs_struct_t *ext_regs);
#define parasite_setup_shstk __parasite_setup_shstk
#endif /* UAPI_COMPEL_ASM_TYPES_H__ */

View File

@@ -760,3 +760,48 @@ bool __compel_shstk_enabled(user_fpregs_struct_t *ext_regs)
return false;
}
int parasite_setup_shstk(struct parasite_ctl *ctl, user_fpregs_struct_t *ext_regs)
{
pid_t pid = ctl->rpid;
unsigned long sa_restorer = ctl->parasite_ip;
unsigned long long ssp;
unsigned long token;
struct iovec iov;
if (!compel_shstk_enabled(ext_regs))
return 0;
iov.iov_base = &ssp;
iov.iov_len = sizeof(ssp);
if (ptrace(PTRACE_GETREGSET, pid, (unsigned int)NT_X86_SHSTK, &iov) < 0) {
/* ENODEV means CET is not supported by the CPU */
if (errno != ENODEV) {
pr_perror("shstk: %d: cannot get SSP", pid);
return -1;
}
}
/* The token is for 64-bit */
token = ALIGN_DOWN(ssp, 8);
token |= (1UL << 63);
ssp = ALIGN_DOWN(ssp, 8) - 8;
if (ptrace(PTRACE_POKEDATA, pid, (void *)ssp, token)) {
pr_perror("shstk: %d: failed to inject shadow stack token", pid);
return -1;
}
ssp = ssp - sizeof(uint64_t);
if (ptrace(PTRACE_POKEDATA, pid, (void *)ssp, sa_restorer)) {
pr_perror("shstk: %d: failed to inject restorer address", pid);
return -1;
}
ssp = ssp + sizeof(uint64_t);
if (ptrace(PTRACE_SETREGSET, pid, (unsigned int)NT_X86_SHSTK, &iov) < 0) {
pr_perror("shstk: %d: cannot write SSP", pid);
return -1;
}
return 0;
}

View File

@@ -190,4 +190,13 @@ static inline bool compel_shstk_enabled(user_fpregs_struct_t *ext_regs)
#define compel_shstk_enabled
#endif
#ifndef parasite_setup_shstk
static inline int parasite_setup_shstk(struct parasite_ctl *ctl,
user_fpregs_struct_t *ext_regs)
{
return 0;
}
#define parasite_setup_shstk parasite_setup_shstk
#endif
#endif

View File

@@ -760,6 +760,9 @@ static int parasite_start_daemon(struct parasite_ctl *ctl)
if (ictx->make_sigframe(ictx->regs_arg, ctl->sigframe, ctl->rsigframe, &ctl->orig.sigmask))
return -1;
if (parasite_setup_shstk(ctl, &ext_regs))
return -1;
if (parasite_init_daemon(ctl))
return -1;