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:
committed by
Andrei Vagin
parent
eee2236507
commit
a09a0eb081
@@ -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__ */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user