|
Message-ID: <a562f9f5-79c1-8a10-8c1e-91fec7ee6614@yahoo.com> Date: Tue, 15 Jan 2019 13:56:40 -0500 From: Ruslan Nikolaev <nruslan_devel@...oo.com> To: kernel-hardening@...ts.openwall.com Cc: thgarnie@...gle.com, x86@...nel.org, kstewart@...uxfoundation.org, gregkh@...uxfoundation.org, keescook@...omium.org Subject: [PATCH v1 01/06]: Extending objtool for PIC modules Extending objtool for PIC modules The patch is by Hassan Nadeem and Ruslan Nikolaev. This extends the prior PIE kernel patch (by Thomas Garnier) to also support position-independent modules that can be placed anywhere in the 48/64-bit address space (for better KASLR). Signed-off-by: Ruslan Nikolaev <nruslan_devel@...oo.com> --- check.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff -uprN a/tools/objtool/check.c b/tools/objtool/check.c --- a/tools/objtool/check.c 2019-01-15 11:20:46.047176216 -0500 +++ b/tools/objtool/check.c 2019-01-15 11:20:57.727294197 -0500 @@ -179,7 +179,7 @@ static int __dead_end_function(struct ob return 0; insn = find_insn(file, func->sec, func->offset); - if (!insn->func) + if (!insn || !insn->func) return 0; func_for_each_insn_all(file, func, insn) { @@ -233,6 +233,8 @@ static int __dead_end_function(struct ob static int dead_end_function(struct objtool_file *file, struct symbol *func) { + if (!func) + return 0; return __dead_end_function(file, func, 0); } @@ -581,7 +583,7 @@ static int add_call_destinations(struct struct rela *rela; for_each_insn(file, insn) { - if (insn->type != INSN_CALL) + if (insn->type != INSN_CALL && insn->type != INSN_CALL_DYNAMIC) continue; rela = find_rela_by_dest_range(insn->sec, insn->offset, @@ -590,8 +592,8 @@ static int add_call_destinations(struct dest_off = insn->offset + insn->len + insn->immediate; insn->call_dest = find_symbol_by_offset(insn->sec, dest_off); - - if (!insn->call_dest && !insn->ignore) { + if (!insn->call_dest && !insn->ignore && + insn->type != INSN_CALL_DYNAMIC) { WARN_FUNC("unsupported intra-function call", insn->sec, insn->offset); if (retpoline) @@ -602,8 +604,9 @@ static int add_call_destinations(struct } else if (rela->sym->type == STT_SECTION) { insn->call_dest = find_symbol_by_offset(rela->sym->sec, rela->addend+4); - if (!insn->call_dest || - insn->call_dest->type != STT_FUNC) { + if ((!insn->call_dest || + insn->call_dest->type != STT_FUNC) && + insn->type != INSN_CALL_DYNAMIC) { WARN_FUNC("can't find call dest symbol at %s+0x%x", insn->sec, insn->offset, rela->sym->sec->name, @@ -836,6 +839,11 @@ static int add_switch_table(struct objto struct symbol *pfunc = insn->func->pfunc; unsigned int prev_offset = 0; + /* If PC32 relocations are used (as in PIC), the following logic + * can be broken in many ways. + */ + if (file->ignore_unreachables) + return 0; list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) { if (rela == next_table) break; @@ -1244,7 +1252,7 @@ static int decode_sections(struct objtoo static bool is_fentry_call(struct instruction *insn) { - if (insn->type == INSN_CALL && + if (insn->call_dest && insn->call_dest->type == STT_NOTYPE && !strcmp(insn->call_dest->name, "__fentry__")) return true; @@ -1889,6 +1897,7 @@ static int validate_branch(struct objtoo return 0; case INSN_CALL: + case INSN_CALL_DYNAMIC: if (is_fentry_call(insn)) break; @@ -1898,8 +1907,6 @@ static int validate_branch(struct objtoo if (ret == -1) return 1; - /* fallthrough */ - case INSN_CALL_DYNAMIC: if (!no_fp && func && !has_valid_stack_frame(&state)) { WARN_FUNC("call without frame pointer save/setup", sec, insn->offset); @@ -1929,12 +1936,15 @@ static int validate_branch(struct objtoo break; case INSN_JUMP_DYNAMIC: + /* XXX: Does not work properly with PIC code. */ +#if 0 if (func && list_empty(&insn->alts) && has_modified_stack_frame(&state)) { WARN_FUNC("sibling call from callable instruction with modified stack frame", sec, insn->offset); return 1; } +#endif return 0; @@ -2015,6 +2025,11 @@ static int validate_retpoline(struct obj if (!strcmp(insn->sec->name, ".init.text") && !module) continue; + /* ignore ftrace calls in PIC code */ + if (!insn->call_dest || + !strcmp(insn->call_dest->name, "__fentry__")) + continue; + WARN_FUNC("indirect %s found in RETPOLINE build", insn->sec, insn->offset, insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call"); @@ -2027,13 +2042,15 @@ static int validate_retpoline(struct obj static bool is_kasan_insn(struct instruction *insn) { - return (insn->type == INSN_CALL && + return ((insn->type == INSN_CALL || insn->type == INSN_CALL_DYNAMIC) && + insn->call_dest && !strcmp(insn->call_dest->name, "__asan_handle_no_return")); } static bool is_ubsan_insn(struct instruction *insn) { - return (insn->type == INSN_CALL && + return ((insn->type == INSN_CALL || insn->type == INSN_CALL_DYNAMIC) && + insn->call_dest && !strcmp(insn->call_dest->name, "__ubsan_handle_builtin_unreachable")); }
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.