compel: infect: prepare parasite_service() for addition of CET support

To support sigreturn with CET enabled parasite must rewind its stack
before calling sigreturn so that shadow stack will be compatible with
actual calling sequence.

In addition, calling sigreturn from top level routine
(__export_parasite_head_start) will significantly simplify the shadow
stack manipulations required to execute sigreturn.

For x86 make fini_sigreturn() return the stack pointer for the signal
frame that will be used by sigreturn and propagate that return value up
to __export_parasite_head_start.

In non-daemon mode parasite_trap_cmd() returns non-positive value
which allows to distinguish daemon and non-daemon mode and properly stop
at int3 in non-daemon mode.

Architectures other than x86 remain unchanged and will still call
sigreturn from fini_sigreturn().

Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
This commit is contained in:
Mike Rapoport (IBM) 2022-05-15 19:58:04 +03:00 committed by Andrei Vagin
parent 6e491a19a3
commit 63a45e1c8a
5 changed files with 44 additions and 18 deletions

View file

@ -7,7 +7,7 @@ extern int parasite_get_rpc_sock(void);
extern unsigned int __export_parasite_service_cmd;
extern void *__export_parasite_service_args_ptr;
extern int __must_check parasite_service(void);
extern unsigned long __must_check parasite_service(void);
/*
* Must be supplied by user plugins.

View file

@ -16,6 +16,10 @@
#include "rpc-pie-priv.h"
#ifndef ARCH_RT_SIGRETURN_DUMP
#define ARCH_RT_SIGRETURN_DUMP ARCH_RT_SIGRETURN
#endif
static int tsock = -1;
static struct rt_sigframe *sigframe;
@ -79,12 +83,13 @@ static int __parasite_daemon_wait_msg(struct ctl_msg *m)
/* Core infect code */
static noinline void fini_sigreturn(unsigned long new_sp)
static noinline unsigned long fini_sigreturn(unsigned long new_sp)
{
ARCH_RT_SIGRETURN(new_sp, sigframe);
ARCH_RT_SIGRETURN_DUMP(new_sp, sigframe);
return new_sp;
}
static int fini(void)
static unsigned long fini(void)
{
unsigned long new_sp;
@ -96,14 +101,14 @@ static int fini(void)
sys_close(tsock);
std_log_set_fd(-1);
fini_sigreturn(new_sp);
return fini_sigreturn(new_sp);
BUG();
return -1;
}
static noinline __used int noinline parasite_daemon(void *args)
static noinline __used unsigned long parasite_daemon(void *args)
{
struct ctl_msg m;
int ret = -1;
@ -140,12 +145,10 @@ static noinline __used int noinline parasite_daemon(void *args)
}
out:
fini();
return 0;
return fini();
}
static noinline __used int parasite_init_daemon(void *data)
static noinline __used unsigned long parasite_init_daemon(void *data)
{
struct parasite_init_args *args = data;
int ret;
@ -178,14 +181,11 @@ static noinline __used int parasite_init_daemon(void *data)
} else
goto err;
parasite_daemon(data);
return parasite_daemon(data);
err:
futex_set_and_wake(&args->daemon_connected, ret);
fini();
BUG();
return -1;
return fini();
}
#ifndef __parasite_entry
@ -203,7 +203,7 @@ err:
unsigned int __export_parasite_service_cmd = 0;
void *__export_parasite_service_args_ptr = NULL;
int __used __parasite_entry parasite_service(void)
unsigned long __used __parasite_entry parasite_service(void)
{
unsigned int cmd = __export_parasite_service_cmd;
void *args = __export_parasite_service_args_ptr;