From patchwork Tue Jan 15 18:56:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ruslan Nikolaev X-Patchwork-Id: 10764997 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C2FC86C5 for ; Tue, 15 Jan 2019 19:08:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B20492CE93 for ; Tue, 15 Jan 2019 19:08:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A64092D74A; Tue, 15 Jan 2019 19:08:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 805FA2CE93 for ; Tue, 15 Jan 2019 19:08:36 +0000 (UTC) Received: (qmail 21878 invoked by uid 550); 15 Jan 2019 19:08:35 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Delivered-To: moderator for kernel-hardening@lists.openwall.com Received: (qmail 8070 invoked from network); 15 Jan 2019 18:56:55 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1547578603; bh=g+RHT64K4ZMqKcL4K/TRpWO5qyU4voXfUD6JhAkwDkc=; h=To:Cc:From:Subject:Date:From:Subject; b=PjtpSL5iThOfM5nBBrykwoqmhMjRjgJ3vvsYqlOoYyocdfFQs3acLJpUi1QynpXJKnyYs8byV2lMcpfKdAqViyNha5Wph5+y8KrT6pvdsGf8FEFJjl9fsdLeFVO+ZUr1QTZ8sLlY8oKWq83g7RHwA65+RkzIrS9LD0xepiNC/KWkLQe/UettcpIUWzm2su6M0Q8MZp1b/jNXxe4UdioG/rqCntrMJHtIvpiPQtolHGJ3duCKTOGa3z8Hwz44KibxbCOUuVCYSKzrvskgAwPA+YVpzQuDJTr2yDXlXOCCcuA3W2icgVySsmCFEVpkDytVtx6wWZ2j2bTf+8p9N4pJfQ== X-YMail-OSG: Czr5xfkVM1k6WEwbtgYgT3pfANgCJZrqt7R1gFdocRuGAz16YlNwoHMX7c91yO. MVofJelOnb8sLF8YYvMsf45Icq31SJdx8E7n.Ej3fOrEitOTqwaOXkCnquw1XEU.mva4Qq0gjV1B COIKMs4truPzNZQlUqkkBYXW8W0xnEIZ1plHCfFQIWsKFpPcKF2zpj9evCPY77bHEeohdfEm7hXW G1I0_O2_28zloFHhe.w68Nr1cUAn5ULBY17GwHbMh6GvGn3br3L.2IZOCckab46Rnb.fhI8e39Eo 1TodItnzIQc.scB41OvUI7uZ6eHnZ0MpFPnJ9r0VMbK5bwPDLRAeAyPQeqYVREmZJ692lNvaYviO mMAJnr7TqWq.61FDC7D_UT164i9lI1W0O0JIVSB3UtPuY.L7V77exe1JeuY3mxPFw3SUq3xBY1SD Z1FDqJNj080TD7EttNTqHxqDFRVkzoGufO9z1Jv2ZmbHLLn7meVExz8Pmqrb6x_nI5UN2UhqZ34y ANW8Rxfw24YrUCotaLNiT.qnmAqgsPnHd.Da3fS85U64vh6jId3xXkxuWWxIKOOOCA5EC6pQ22k0 nIB5CY.nBt4GT5FlmAO2ye_GYeZ_ftjWYSlgcZenSVweoHKKqRbnSHU61Mqk1KFBMpHRk.uV9u_U aJky16IYLxbInCPzMA00DI.mGoiSn0Z7YS4.ZuBD5vKA2ll79f0JxOhzfpoBz0BppPR0ZOtVU5Cu uGCxjQcFCELP399YVPw9.yZilM1xLbFmE2vDJUE2Hp1NxkdHPOl.HKpXFojX7upwnoWbkV1aiIxC dxg0V0fkNjhnSQaxnjH5SpRN7WGl6x0MvB7zXOUCgLhoaSfCnM8hCXHTwTSMbuhpg_t5SLpaFslE dJL8JrC5YjYqVpi3enabMN3EmcdKKCqTfBl1X2EgcQJCR493RPXNn.sw__mExs06THbm.kque4NV 3VlQAfuhISehTxo23jHMKdHsqoSovC2NaHy79vMuAcrRi6Mcs7zr0XAuxH4e4tS0zLQEfxWCBPGC feLgXWv.A.FchAFSQz_LAJh1qRRnEydYAxWXCXTLzxOMmeWs9NbSlK.ctBWk- To: kernel-hardening@lists.openwall.com Cc: thgarnie@google.com, x86@kernel.org, kstewart@linuxfoundation.org, gregkh@linuxfoundation.org, keescook@chromium.org From: Ruslan Nikolaev Subject: [PATCH v1 01/06]: Extending objtool for PIC modules Message-ID: Date: Tue, 15 Jan 2019 13:56:40 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 Content-Language: en-US X-Virus-Scanned: ClamAV using ClamSMTP 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 --- check.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) @@ -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")); } 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); }