Merge branch 'upstream-x86-selftests' into WIP.x86/pti.base
Conflicts: arch/x86/kernel/cpu/Makefile Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -115,7 +115,15 @@ static void check_valid_segment(uint16_t index, int ldt,
|
||||
return;
|
||||
}
|
||||
|
||||
if (ar != expected_ar) {
|
||||
/* The SDM says "bits 19:16 are undefined". Thanks. */
|
||||
ar &= ~0xF0000;
|
||||
|
||||
/*
|
||||
* NB: Different Linux versions do different things with the
|
||||
* accessed bit in set_thread_area().
|
||||
*/
|
||||
if (ar != expected_ar &&
|
||||
(ldt || ar != (expected_ar | AR_ACCESSED))) {
|
||||
printf("[FAIL]\t%s entry %hu has AR 0x%08X but expected 0x%08X\n",
|
||||
(ldt ? "LDT" : "GDT"), index, ar, expected_ar);
|
||||
nerrs++;
|
||||
@@ -129,30 +137,51 @@ static void check_valid_segment(uint16_t index, int ldt,
|
||||
}
|
||||
}
|
||||
|
||||
static bool install_valid_mode(const struct user_desc *desc, uint32_t ar,
|
||||
bool oldmode)
|
||||
static bool install_valid_mode(const struct user_desc *d, uint32_t ar,
|
||||
bool oldmode, bool ldt)
|
||||
{
|
||||
int ret = syscall(SYS_modify_ldt, oldmode ? 1 : 0x11,
|
||||
desc, sizeof(*desc));
|
||||
if (ret < -1)
|
||||
errno = -ret;
|
||||
if (ret == 0) {
|
||||
uint32_t limit = desc->limit;
|
||||
if (desc->limit_in_pages)
|
||||
limit = (limit << 12) + 4095;
|
||||
check_valid_segment(desc->entry_number, 1, ar, limit, true);
|
||||
return true;
|
||||
} else if (errno == ENOSYS) {
|
||||
printf("[OK]\tmodify_ldt returned -ENOSYS\n");
|
||||
struct user_desc desc = *d;
|
||||
int ret;
|
||||
|
||||
if (!ldt) {
|
||||
#ifndef __i386__
|
||||
/* No point testing set_thread_area in a 64-bit build */
|
||||
return false;
|
||||
#endif
|
||||
if (!gdt_entry_num)
|
||||
return false;
|
||||
desc.entry_number = gdt_entry_num;
|
||||
|
||||
ret = syscall(SYS_set_thread_area, &desc);
|
||||
} else {
|
||||
if (desc->seg_32bit) {
|
||||
printf("[FAIL]\tUnexpected modify_ldt failure %d\n",
|
||||
ret = syscall(SYS_modify_ldt, oldmode ? 1 : 0x11,
|
||||
&desc, sizeof(desc));
|
||||
|
||||
if (ret < -1)
|
||||
errno = -ret;
|
||||
|
||||
if (ret != 0 && errno == ENOSYS) {
|
||||
printf("[OK]\tmodify_ldt returned -ENOSYS\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
uint32_t limit = desc.limit;
|
||||
if (desc.limit_in_pages)
|
||||
limit = (limit << 12) + 4095;
|
||||
check_valid_segment(desc.entry_number, ldt, ar, limit, true);
|
||||
return true;
|
||||
} else {
|
||||
if (desc.seg_32bit) {
|
||||
printf("[FAIL]\tUnexpected %s failure %d\n",
|
||||
ldt ? "modify_ldt" : "set_thread_area",
|
||||
errno);
|
||||
nerrs++;
|
||||
return false;
|
||||
} else {
|
||||
printf("[OK]\tmodify_ldt rejected 16 bit segment\n");
|
||||
printf("[OK]\t%s rejected 16 bit segment\n",
|
||||
ldt ? "modify_ldt" : "set_thread_area");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -160,7 +189,15 @@ static bool install_valid_mode(const struct user_desc *desc, uint32_t ar,
|
||||
|
||||
static bool install_valid(const struct user_desc *desc, uint32_t ar)
|
||||
{
|
||||
return install_valid_mode(desc, ar, false);
|
||||
bool ret = install_valid_mode(desc, ar, false, true);
|
||||
|
||||
if (desc->contents <= 1 && desc->seg_32bit &&
|
||||
!desc->seg_not_present) {
|
||||
/* Should work in the GDT, too. */
|
||||
install_valid_mode(desc, ar, false, false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void install_invalid(const struct user_desc *desc, bool oldmode)
|
||||
@@ -367,9 +404,24 @@ static void do_simple_tests(void)
|
||||
install_invalid(&desc, false);
|
||||
|
||||
desc.seg_not_present = 0;
|
||||
desc.read_exec_only = 0;
|
||||
desc.seg_32bit = 1;
|
||||
desc.read_exec_only = 0;
|
||||
desc.limit = 0xfffff;
|
||||
|
||||
install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA | AR_S | AR_P | AR_DB);
|
||||
|
||||
desc.limit_in_pages = 1;
|
||||
|
||||
install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA | AR_S | AR_P | AR_DB | AR_G);
|
||||
desc.read_exec_only = 1;
|
||||
install_valid(&desc, AR_DPL3 | AR_TYPE_RODATA | AR_S | AR_P | AR_DB | AR_G);
|
||||
desc.contents = 1;
|
||||
desc.read_exec_only = 0;
|
||||
install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA_EXPDOWN | AR_S | AR_P | AR_DB | AR_G);
|
||||
desc.read_exec_only = 1;
|
||||
install_valid(&desc, AR_DPL3 | AR_TYPE_RODATA_EXPDOWN | AR_S | AR_P | AR_DB | AR_G);
|
||||
|
||||
desc.limit = 0;
|
||||
install_invalid(&desc, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -189,17 +189,29 @@ void lots_o_noops_around_write(int *write_to_me)
|
||||
#define u64 uint64_t
|
||||
|
||||
#ifdef __i386__
|
||||
#define SYS_mprotect_key 380
|
||||
#define SYS_pkey_alloc 381
|
||||
#define SYS_pkey_free 382
|
||||
|
||||
#ifndef SYS_mprotect_key
|
||||
# define SYS_mprotect_key 380
|
||||
#endif
|
||||
#ifndef SYS_pkey_alloc
|
||||
# define SYS_pkey_alloc 381
|
||||
# define SYS_pkey_free 382
|
||||
#endif
|
||||
#define REG_IP_IDX REG_EIP
|
||||
#define si_pkey_offset 0x14
|
||||
|
||||
#else
|
||||
#define SYS_mprotect_key 329
|
||||
#define SYS_pkey_alloc 330
|
||||
#define SYS_pkey_free 331
|
||||
|
||||
#ifndef SYS_mprotect_key
|
||||
# define SYS_mprotect_key 329
|
||||
#endif
|
||||
#ifndef SYS_pkey_alloc
|
||||
# define SYS_pkey_alloc 330
|
||||
# define SYS_pkey_free 331
|
||||
#endif
|
||||
#define REG_IP_IDX REG_RIP
|
||||
#define si_pkey_offset 0x20
|
||||
|
||||
#endif
|
||||
|
||||
void dump_mem(void *dumpme, int len_bytes)
|
||||
|
||||
Reference in New Issue
Block a user