mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-22 09:58:09 +00:00
criu: kerndat: add kdat_has_shstk()
Detect if CRIU runs with shadow stack enabled and store the result in kerndat. Unlike most kerndat knobs, kdat_has_shstk() does not check for availability of the shadow stack in the kernel, but rather checks if criu runs with shadow stack enabled. This depends on hardware availabilty, kernel and glibc support, compiler options and glibc tunables, so kdat_has_shstk() must be called every time CRIU starts and its result cannot be cached. The result will be used by the code that controls shadow stack enablement in the next commit. Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
This commit is contained in:
parent
2ebd1a4f0b
commit
f47899c9ef
@ -4,5 +4,6 @@
|
||||
extern int kdat_compatible_cr(void);
|
||||
extern int kdat_can_map_vdso(void);
|
||||
extern int kdat_x86_has_ptrace_fpu_xsave_bug(void);
|
||||
extern int kdat_has_shstk(void);
|
||||
|
||||
#endif /* __CR_ASM_KERNDAT_H__ */
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "asm/compat.h"
|
||||
#include "asm/dump.h"
|
||||
#include "asm/shstk.h"
|
||||
|
||||
int kdat_can_map_vdso(void)
|
||||
{
|
||||
@ -251,3 +252,29 @@ out_kill:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlike most kerndat knobs, this does not check for availability of the
|
||||
* shadow stack in the kernel, but rather checks if criu runs with shadow
|
||||
* stack enabled.
|
||||
*
|
||||
* This depends on hardware availability, kernel and glibc support, compiler
|
||||
* options and glibc tunables.
|
||||
*/
|
||||
int kdat_has_shstk(void)
|
||||
{
|
||||
unsigned long features;
|
||||
|
||||
if (!compel_cpu_has_feature(X86_FEATURE_SHSTK))
|
||||
return 0;
|
||||
|
||||
if (syscall(__NR_arch_prctl, ARCH_SHSTK_STATUS, &features)) {
|
||||
/* kernels that don't support shadow stack return -EINVAL */
|
||||
if (errno == EINVAL)
|
||||
return 0;
|
||||
pr_perror("Cannot get shadow stack status");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return !!(features & ARCH_SHSTK_SHSTK);
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ struct kerndat_s {
|
||||
bool has_ipv6_freebind;
|
||||
bool has_membarrier_get_registrations;
|
||||
bool has_pagemap_scan;
|
||||
bool has_shstk;
|
||||
};
|
||||
|
||||
extern struct kerndat_s kdat;
|
||||
|
@ -1151,6 +1151,24 @@ static int kerndat_has_openat2(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __attribute__((weak)) kdat_has_shstk(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kerndat_has_shstk(void)
|
||||
{
|
||||
int ret = kdat_has_shstk();
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("kdat_has_shstk failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
kdat.has_shstk = !!ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define KERNDAT_CACHE_NAME "criu.kdat"
|
||||
#define KERNDAT_CACHE_FILE KDAT_RUNDIR "/" KERNDAT_CACHE_NAME
|
||||
|
||||
@ -1705,6 +1723,12 @@ int kerndat_try_load_new(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = kerndat_has_shstk();
|
||||
if (ret < 0) {
|
||||
pr_err("kerndat_has_shstk failed when initializing kerndat.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* New information is found, we need to save to the cache */
|
||||
if (ret)
|
||||
kerndat_save_cache();
|
||||
@ -1926,6 +1950,10 @@ int kerndat_init(void)
|
||||
pr_err("kerndat_has_membarrier_get_registrations failed when initializing kerndat.\n");
|
||||
ret = -1;
|
||||
}
|
||||
if (!ret && kerndat_has_shstk()) {
|
||||
pr_err("kerndat_has_shstk failed when initializing kerndat.\n");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
kerndat_lsm();
|
||||
kerndat_mmap_min_addr();
|
||||
|
Loading…
x
Reference in New Issue
Block a user