mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 10:41:38 -04:00
Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 PTI and Spectre related fixes and updates from Ingo Molnar:
"Here's the latest set of Spectre and PTI related fixes and updates:
Spectre:
- Add entry code register clearing to reduce the Spectre attack
surface
- Update the Spectre microcode blacklist
- Inline the KVM Spectre helpers to get close to v4.14 performance
again.
- Fix indirect_branch_prediction_barrier()
- Fix/improve Spectre related kernel messages
- Fix array_index_nospec_mask() asm constraint
- KVM: fix two MSR handling bugs
PTI:
- Fix a paranoid entry PTI CR3 handling bug
- Fix comments
objtool:
- Fix paranoid_entry() frame pointer warning
- Annotate WARN()-related UD2 as reachable
- Various fixes
- Add Add Peter Zijlstra as objtool co-maintainer
Misc:
- Various x86 entry code self-test fixes
- Improve/simplify entry code stack frame generation and handling
after recent heavy-handed PTI and Spectre changes. (There's two
more WIP improvements expected here.)
- Type fix for cache entries
There's also some low risk non-fix changes I've included in this
branch to reduce backporting conflicts:
- rename a confusing x86_cpu field name
- de-obfuscate the naming of single-TLB flushing primitives"
* 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (41 commits)
x86/entry/64: Fix CR3 restore in paranoid_exit()
x86/cpu: Change type of x86_cache_size variable to unsigned int
x86/spectre: Fix an error message
x86/cpu: Rename cpu_data.x86_mask to cpu_data.x86_stepping
selftests/x86/mpx: Fix incorrect bounds with old _sigfault
x86/mm: Rename flush_tlb_single() and flush_tlb_one() to __flush_tlb_one_[user|kernel]()
x86/speculation: Add <asm/msr-index.h> dependency
nospec: Move array_index_nospec() parameter checking into separate macro
x86/speculation: Fix up array_index_nospec_mask() asm constraint
x86/debug: Use UD2 for WARN()
x86/debug, objtool: Annotate WARN()-related UD2 as reachable
objtool: Fix segfault in ignore_unreachable_insn()
selftests/x86: Disable tests requiring 32-bit support on pure 64-bit systems
selftests/x86: Do not rely on "int $0x80" in single_step_syscall.c
selftests/x86: Do not rely on "int $0x80" in test_mremap_vdso.c
selftests/x86: Fix build bug caused by the 5lvl test which has been moved to the VM directory
selftests/x86/pkeys: Remove unused functions
selftests/x86: Clean up and document sscanf() usage
selftests/x86: Fix vDSO selftest segfault for vsyscall=none
x86/entry/64: Remove the unused 'icebp' macro
...
This commit is contained in:
commit
d4667ca142
69 changed files with 444 additions and 362 deletions
|
|
@ -5,16 +5,26 @@ include ../lib.mk
|
|||
|
||||
.PHONY: all all_32 all_64 warn_32bit_failure clean
|
||||
|
||||
TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall test_mremap_vdso \
|
||||
check_initial_reg_state sigreturn ldt_gdt iopl mpx-mini-test ioperm \
|
||||
UNAME_M := $(shell uname -m)
|
||||
CAN_BUILD_I386 := $(shell ./check_cc.sh $(CC) trivial_32bit_program.c -m32)
|
||||
CAN_BUILD_X86_64 := $(shell ./check_cc.sh $(CC) trivial_64bit_program.c)
|
||||
|
||||
TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \
|
||||
check_initial_reg_state sigreturn iopl mpx-mini-test ioperm \
|
||||
protection_keys test_vdso test_vsyscall
|
||||
TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
|
||||
test_FCMOV test_FCOMI test_FISTTP \
|
||||
vdso_restorer
|
||||
TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip 5lvl
|
||||
TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip
|
||||
# Some selftests require 32bit support enabled also on 64bit systems
|
||||
TARGETS_C_32BIT_NEEDED := ldt_gdt ptrace_syscall
|
||||
|
||||
TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
|
||||
TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) $(TARGETS_C_32BIT_NEEDED)
|
||||
TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY)
|
||||
ifeq ($(CAN_BUILD_I386)$(CAN_BUILD_X86_64),11)
|
||||
TARGETS_C_64BIT_ALL += $(TARGETS_C_32BIT_NEEDED)
|
||||
endif
|
||||
|
||||
BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
|
||||
BINARIES_64 := $(TARGETS_C_64BIT_ALL:%=%_64)
|
||||
|
||||
|
|
@ -23,10 +33,6 @@ BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64))
|
|||
|
||||
CFLAGS := -O2 -g -std=gnu99 -pthread -Wall -no-pie
|
||||
|
||||
UNAME_M := $(shell uname -m)
|
||||
CAN_BUILD_I386 := $(shell ./check_cc.sh $(CC) trivial_32bit_program.c -m32)
|
||||
CAN_BUILD_X86_64 := $(shell ./check_cc.sh $(CC) trivial_64bit_program.c)
|
||||
|
||||
define gen-target-rule-32
|
||||
$(1) $(1)_32: $(OUTPUT)/$(1)_32
|
||||
.PHONY: $(1) $(1)_32
|
||||
|
|
@ -40,12 +46,14 @@ endef
|
|||
ifeq ($(CAN_BUILD_I386),1)
|
||||
all: all_32
|
||||
TEST_PROGS += $(BINARIES_32)
|
||||
EXTRA_CFLAGS += -DCAN_BUILD_32
|
||||
$(foreach t,$(TARGETS_C_32BIT_ALL),$(eval $(call gen-target-rule-32,$(t))))
|
||||
endif
|
||||
|
||||
ifeq ($(CAN_BUILD_X86_64),1)
|
||||
all: all_64
|
||||
TEST_PROGS += $(BINARIES_64)
|
||||
EXTRA_CFLAGS += -DCAN_BUILD_64
|
||||
$(foreach t,$(TARGETS_C_64BIT_ALL),$(eval $(call gen-target-rule-64,$(t))))
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -315,11 +315,39 @@ static inline void *__si_bounds_upper(siginfo_t *si)
|
|||
return si->si_upper;
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
* This deals with old version of _sigfault in some distros:
|
||||
*
|
||||
|
||||
old _sigfault:
|
||||
struct {
|
||||
void *si_addr;
|
||||
} _sigfault;
|
||||
|
||||
new _sigfault:
|
||||
struct {
|
||||
void __user *_addr;
|
||||
int _trapno;
|
||||
short _addr_lsb;
|
||||
union {
|
||||
struct {
|
||||
void __user *_lower;
|
||||
void __user *_upper;
|
||||
} _addr_bnd;
|
||||
__u32 _pkey;
|
||||
};
|
||||
} _sigfault;
|
||||
*
|
||||
*/
|
||||
|
||||
static inline void **__si_bounds_hack(siginfo_t *si)
|
||||
{
|
||||
void *sigfault = &si->_sifields._sigfault;
|
||||
void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault);
|
||||
void **__si_lower = end_sigfault;
|
||||
int *trapno = (int*)end_sigfault;
|
||||
/* skip _trapno and _addr_lsb */
|
||||
void **__si_lower = (void**)(trapno + 2);
|
||||
|
||||
return __si_lower;
|
||||
}
|
||||
|
|
@ -331,7 +359,7 @@ static inline void *__si_bounds_lower(siginfo_t *si)
|
|||
|
||||
static inline void *__si_bounds_upper(siginfo_t *si)
|
||||
{
|
||||
return (*__si_bounds_hack(si)) + sizeof(void *);
|
||||
return *(__si_bounds_hack(si) + 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -393,34 +393,6 @@ pid_t fork_lazy_child(void)
|
|||
return forkret;
|
||||
}
|
||||
|
||||
void davecmp(void *_a, void *_b, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned long *a = _a;
|
||||
unsigned long *b = _b;
|
||||
|
||||
for (i = 0; i < len / sizeof(*a); i++) {
|
||||
if (a[i] == b[i])
|
||||
continue;
|
||||
|
||||
dprintf3("[%3d]: a: %016lx b: %016lx\n", i, a[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void dumpit(char *f)
|
||||
{
|
||||
int fd = open(f, O_RDONLY);
|
||||
char buf[100];
|
||||
int nr_read;
|
||||
|
||||
dprintf2("maps fd: %d\n", fd);
|
||||
do {
|
||||
nr_read = read(fd, &buf[0], sizeof(buf));
|
||||
write(1, buf, nr_read);
|
||||
} while (nr_read > 0);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
#define PKEY_DISABLE_ACCESS 0x1
|
||||
#define PKEY_DISABLE_WRITE 0x2
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,9 @@ static void check_result(void)
|
|||
|
||||
int main()
|
||||
{
|
||||
#ifdef CAN_BUILD_32
|
||||
int tmp;
|
||||
#endif
|
||||
|
||||
sethandler(SIGTRAP, sigtrap, 0);
|
||||
|
||||
|
|
@ -139,12 +141,13 @@ int main()
|
|||
: : "c" (post_nop) : "r11");
|
||||
check_result();
|
||||
#endif
|
||||
|
||||
#ifdef CAN_BUILD_32
|
||||
printf("[RUN]\tSet TF and check int80\n");
|
||||
set_eflags(get_eflags() | X86_EFLAGS_TF);
|
||||
asm volatile ("int $0x80" : "=a" (tmp) : "a" (SYS_getpid)
|
||||
: INT80_CLOBBERS);
|
||||
check_result();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This test is particularly interesting if fast syscalls use
|
||||
|
|
|
|||
|
|
@ -90,8 +90,12 @@ int main(int argc, char **argv, char **envp)
|
|||
vdso_size += PAGE_SIZE;
|
||||
}
|
||||
|
||||
#ifdef __i386__
|
||||
/* Glibc is likely to explode now - exit with raw syscall */
|
||||
asm volatile ("int $0x80" : : "a" (__NR_exit), "b" (!!ret));
|
||||
#else /* __x86_64__ */
|
||||
syscall(SYS_exit, ret);
|
||||
#endif
|
||||
} else {
|
||||
int status;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,20 +26,59 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
int nerrs = 0;
|
||||
/* max length of lines in /proc/self/maps - anything longer is skipped here */
|
||||
#define MAPS_LINE_LEN 128
|
||||
|
||||
#ifdef __x86_64__
|
||||
# define VSYS(x) (x)
|
||||
#else
|
||||
# define VSYS(x) 0
|
||||
#endif
|
||||
int nerrs = 0;
|
||||
|
||||
typedef long (*getcpu_t)(unsigned *, unsigned *, void *);
|
||||
|
||||
const getcpu_t vgetcpu = (getcpu_t)VSYS(0xffffffffff600800);
|
||||
getcpu_t vgetcpu;
|
||||
getcpu_t vdso_getcpu;
|
||||
|
||||
void fill_function_pointers()
|
||||
static void *vsyscall_getcpu(void)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
FILE *maps;
|
||||
char line[MAPS_LINE_LEN];
|
||||
bool found = false;
|
||||
|
||||
maps = fopen("/proc/self/maps", "r");
|
||||
if (!maps) /* might still be present, but ignore it here, as we test vDSO not vsyscall */
|
||||
return NULL;
|
||||
|
||||
while (fgets(line, MAPS_LINE_LEN, maps)) {
|
||||
char r, x;
|
||||
void *start, *end;
|
||||
char name[MAPS_LINE_LEN];
|
||||
|
||||
/* sscanf() is safe here as strlen(name) >= strlen(line) */
|
||||
if (sscanf(line, "%p-%p %c-%cp %*x %*x:%*x %*u %s",
|
||||
&start, &end, &r, &x, name) != 5)
|
||||
continue;
|
||||
|
||||
if (strcmp(name, "[vsyscall]"))
|
||||
continue;
|
||||
|
||||
/* assume entries are OK, as we test vDSO here not vsyscall */
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
fclose(maps);
|
||||
|
||||
if (!found) {
|
||||
printf("Warning: failed to find vsyscall getcpu\n");
|
||||
return NULL;
|
||||
}
|
||||
return (void *) (0xffffffffff600800);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void fill_function_pointers()
|
||||
{
|
||||
void *vdso = dlopen("linux-vdso.so.1",
|
||||
RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
|
||||
|
|
@ -54,6 +93,8 @@ void fill_function_pointers()
|
|||
vdso_getcpu = (getcpu_t)dlsym(vdso, "__vdso_getcpu");
|
||||
if (!vdso_getcpu)
|
||||
printf("Warning: failed to find getcpu in vDSO\n");
|
||||
|
||||
vgetcpu = (getcpu_t) vsyscall_getcpu();
|
||||
}
|
||||
|
||||
static long sys_getcpu(unsigned * cpu, unsigned * node,
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* max length of lines in /proc/self/maps - anything longer is skipped here */
|
||||
#define MAPS_LINE_LEN 128
|
||||
|
||||
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
|
||||
int flags)
|
||||
{
|
||||
|
|
@ -98,7 +101,7 @@ static int init_vsys(void)
|
|||
#ifdef __x86_64__
|
||||
int nerrs = 0;
|
||||
FILE *maps;
|
||||
char line[128];
|
||||
char line[MAPS_LINE_LEN];
|
||||
bool found = false;
|
||||
|
||||
maps = fopen("/proc/self/maps", "r");
|
||||
|
|
@ -108,10 +111,12 @@ static int init_vsys(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), maps)) {
|
||||
while (fgets(line, MAPS_LINE_LEN, maps)) {
|
||||
char r, x;
|
||||
void *start, *end;
|
||||
char name[128];
|
||||
char name[MAPS_LINE_LEN];
|
||||
|
||||
/* sscanf() is safe here as strlen(name) >= strlen(line) */
|
||||
if (sscanf(line, "%p-%p %c-%cp %*x %*x:%*x %*u %s",
|
||||
&start, &end, &r, &x, name) != 5)
|
||||
continue;
|
||||
|
|
|
|||
Loading…
Reference in a new issue