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:
@@ -852,8 +852,14 @@ static int add_switch_table(struct objtool_file *file, struct symbol *func,
|
||||
* This is a fairly uncommon pattern which is new for GCC 6. As of this
|
||||
* writing, there are 11 occurrences of it in the allmodconfig kernel.
|
||||
*
|
||||
* As of GCC 7 there are quite a few more of these and the 'in between' code
|
||||
* is significant. Esp. with KASAN enabled some of the code between the mov
|
||||
* and jmpq uses .rodata itself, which can confuse things.
|
||||
*
|
||||
* TODO: Once we have DWARF CFI and smarter instruction decoding logic,
|
||||
* ensure the same register is used in the mov and jump instructions.
|
||||
*
|
||||
* NOTE: RETPOLINE made it harder still to decode dynamic jumps.
|
||||
*/
|
||||
static struct rela *find_switch_table(struct objtool_file *file,
|
||||
struct symbol *func,
|
||||
@@ -875,12 +881,25 @@ static struct rela *find_switch_table(struct objtool_file *file,
|
||||
text_rela->addend + 4);
|
||||
if (!rodata_rela)
|
||||
return NULL;
|
||||
|
||||
file->ignore_unreachables = true;
|
||||
return rodata_rela;
|
||||
}
|
||||
|
||||
/* case 3 */
|
||||
func_for_each_insn_continue_reverse(file, func, insn) {
|
||||
/*
|
||||
* Backward search using the @first_jump_src links, these help avoid
|
||||
* much of the 'in between' code. Which avoids us getting confused by
|
||||
* it.
|
||||
*/
|
||||
for (insn = list_prev_entry(insn, list);
|
||||
|
||||
&insn->list != &file->insn_list &&
|
||||
insn->sec == func->sec &&
|
||||
insn->offset >= func->offset;
|
||||
|
||||
insn = insn->first_jump_src ?: list_prev_entry(insn, list)) {
|
||||
|
||||
if (insn->type == INSN_JUMP_DYNAMIC)
|
||||
break;
|
||||
|
||||
@@ -910,14 +929,32 @@ static struct rela *find_switch_table(struct objtool_file *file,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int add_func_switch_tables(struct objtool_file *file,
|
||||
struct symbol *func)
|
||||
{
|
||||
struct instruction *insn, *prev_jump = NULL;
|
||||
struct instruction *insn, *last = NULL, *prev_jump = NULL;
|
||||
struct rela *rela, *prev_rela = NULL;
|
||||
int ret;
|
||||
|
||||
func_for_each_insn(file, func, insn) {
|
||||
if (!last)
|
||||
last = insn;
|
||||
|
||||
/*
|
||||
* Store back-pointers for unconditional forward jumps such
|
||||
* that find_switch_table() can back-track using those and
|
||||
* avoid some potentially confusing code.
|
||||
*/
|
||||
if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest &&
|
||||
insn->offset > last->offset &&
|
||||
insn->jump_dest->offset > insn->offset &&
|
||||
!insn->jump_dest->first_jump_src) {
|
||||
|
||||
insn->jump_dest->first_jump_src = insn;
|
||||
last = insn->jump_dest;
|
||||
}
|
||||
|
||||
if (insn->type != INSN_JUMP_DYNAMIC)
|
||||
continue;
|
||||
|
||||
@@ -1899,13 +1936,19 @@ static bool ignore_unreachable_insn(struct instruction *insn)
|
||||
if (is_kasan_insn(insn) || is_ubsan_insn(insn))
|
||||
return true;
|
||||
|
||||
if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest) {
|
||||
insn = insn->jump_dest;
|
||||
continue;
|
||||
if (insn->type == INSN_JUMP_UNCONDITIONAL) {
|
||||
if (insn->jump_dest &&
|
||||
insn->jump_dest->func == insn->func) {
|
||||
insn = insn->jump_dest;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (insn->offset + insn->len >= insn->func->offset + insn->func->len)
|
||||
break;
|
||||
|
||||
insn = list_next_entry(insn, list);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user