Received: by 2002:a05:6a10:6d10:0:0:0:0 with SMTP id gq16csp223435pxb; Thu, 14 Apr 2022 20:48:35 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy3SyeJlKq2wI/HM33mFIZPekj2+VENwOGB9QH6ODWOxogUl+pEtp0NiXHiybWl9S4MQeuM X-Received: by 2002:a17:907:7f26:b0:6ec:b6a:468 with SMTP id qf38-20020a1709077f2600b006ec0b6a0468mr3963497ejc.661.1649994514984; Thu, 14 Apr 2022 20:48:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649994514; cv=none; d=google.com; s=arc-20160816; b=fiBk8YUJQGAYf+iUKL6OImqyLusmd1JA+C7dQnxqqV1Q5flTcdEyDM4ucFb7gUXzqv p8r+sbcUUPnzAR3RP1uzl04ik+n4v0TPGGoURRL2FCum1+EBBYdJlUsAyLQhL+mWYNVo rr7e14b/Tje4n+LCtLrKGjvrftdrsUORWfwsQlOjU1SHCqlXtz5AS4bYT+pUh4h+k1f+ cdm3ZrUQYpEiw8wBJJrO1fjJnfBSkOMXLAMr6LRxktBeI0oJBsI08LMdVYaQWxetAkdV eCR7T0zAavDUoDSfct1p5yREa86oUnX+wL7IJOqTkjsDhHbztud6k8S733wst3k7Lhri nwmQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=1498SmuR6dXVDwcCXccoABHA14ZfP4NbQRKlblxZUE8=; b=MnIwYlO4H6/8VnSd46I/xqTagf+M/SFWWEGhxOWNr7XCyvnJnWw064NdT1J0m/51Tf 1xJrQAMqBF5ocsDbQgjGTEwmchOnqXYMQqh3RDJMqjPxx28plL5O49Y7FRbUacivOBNV KtM7hyN10K27MaDcVlckgYUxOJTn7NvLlmLwzXsn4zu94Vk27cUW+8eQrr/n8DrdSMLZ y4E/qCoKKQi5xzrT+u4AkeVDLbmg29fi/iqZtUiuhJhvBIegPq+GNl5YRfx4TgHE9st+ XmZ+kiJPTCUHQz/2aft2uPSBpu4vZR3bB7ML1i86tncw30Te2OcYA98DZlzYfh4tHl8e YMew== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=NWIlRqsl; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id mc7-20020a170906eb4700b006e7ee80423esi289321ejb.114.2022.04.14.20.48.06; Thu, 14 Apr 2022 20:48:34 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=NWIlRqsl; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239184AbiDMXXT (ORCPT + 99 others); Wed, 13 Apr 2022 19:23:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37944 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239263AbiDMXWi (ORCPT ); Wed, 13 Apr 2022 19:22:38 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 16D4323BF4 for ; Wed, 13 Apr 2022 16:20:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1649892015; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1498SmuR6dXVDwcCXccoABHA14ZfP4NbQRKlblxZUE8=; b=NWIlRqslFoSjQkWeQLQqoPdUEzYWhhL0bhRMOPQlNe+k4tvXWOSgEzB1FhA45oQYfm4bZo xT6jXMTMjghksGbSQCC9acHndXW81k8BUO2HSybBPJ03TFhypQ5uPesQG4aUNjKZPmRX3D jF+xoE3uIsvTYhf9o/Qz27VNkPwzjP4= Received: from mail-qk1-f199.google.com (mail-qk1-f199.google.com [209.85.222.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-111-eMtUgswPNB2D_v3ikpw_OQ-1; Wed, 13 Apr 2022 19:20:14 -0400 X-MC-Unique: eMtUgswPNB2D_v3ikpw_OQ-1 Received: by mail-qk1-f199.google.com with SMTP id l68-20020a378947000000b0067df0c430d8so2155275qkd.13 for ; Wed, 13 Apr 2022 16:20:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1498SmuR6dXVDwcCXccoABHA14ZfP4NbQRKlblxZUE8=; b=FYWH3IBSlhl8t10d7Cn7phHCLdOM55bC0JMCeTKtenbAJxi/cWFSbjW/edQROTF0TX Oglp7lmxvD1EWgckZk1sXxEKSMOsPSs+sg1zWGb/0V+vjK2hFBEur/+iJdCot9K6f+RP xahN4CUhXJQF+p2UgpMbr6a5NmRIsgiV6njv8hgYuHGyl5bR6NFI6gftW1SFF1kCj0I9 eYY/clFM/wazVACIdjfjc4CQhTXBGLmUXLmJbqvL03pkq35SE0IYTRigdAlWi+vgrtCF IzBxCgPyM73vnAyOTD+qzu4yA/1Nglz5xDtKNdqZe2Fn8aqgBoNCMShSQDkGUl/pjCzQ CmSg== X-Gm-Message-State: AOAM532bFC5AGD9ni6AZWs1ybCxH7Ju2zhVlrw5SALSg85DFmAYXYyrm X603S+eJHPhq/7G+eCID6MY6R4P2BrcIYgzlhJDIRPhrPfJ66EKxrq+ED3xp4SWCMPdkQK7hvY0 hIfi+u1k6JNiRellWyF7dfqwj X-Received: by 2002:a05:622a:1f0c:b0:2ed:1211:364 with SMTP id ca12-20020a05622a1f0c00b002ed12110364mr8963158qtb.390.1649892013294; Wed, 13 Apr 2022 16:20:13 -0700 (PDT) X-Received: by 2002:a05:622a:1f0c:b0:2ed:1211:364 with SMTP id ca12-20020a05622a1f0c00b002ed12110364mr8963145qtb.390.1649892012967; Wed, 13 Apr 2022 16:20:12 -0700 (PDT) Received: from treble.redhat.com ([2600:1700:6e32:6c00::45]) by smtp.gmail.com with ESMTPSA id b20-20020a05622a021400b002f08f5658a2sm193925qtx.68.2022.04.13.16.20.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Apr 2022 16:20:12 -0700 (PDT) From: Josh Poimboeuf To: x86@kernel.org Cc: Peter Zijlstra , linux-kernel@vger.kernel.org, Miroslav Benes Subject: [PATCH 10/18] objtool: Extricate ibt from stack validation Date: Wed, 13 Apr 2022 16:19:45 -0700 Message-Id: <44a73f724b51c4a994edc43536b7a7ee5e972b40.1649891421.git.jpoimboe@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: MIME-Version: 1.0 Content-type: text/plain Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Extricate ibt from validate_branch() in preparation for making stack validation optional. Signed-off-by: Josh Poimboeuf --- tools/objtool/check.c | 253 ++++++++++++++++++++---------------------- 1 file changed, 120 insertions(+), 133 deletions(-) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index bb25937b2d1c..1b1e7a4ae18b 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -3183,114 +3183,6 @@ static struct instruction *next_insn_to_validate(struct objtool_file *file, return next_insn_same_sec(file, insn); } -static struct instruction * -validate_ibt_reloc(struct objtool_file *file, struct reloc *reloc) -{ - struct instruction *dest; - struct section *sec; - unsigned long off; - - sec = reloc->sym->sec; - off = reloc->sym->offset; - - if ((reloc->sec->base->sh.sh_flags & SHF_EXECINSTR) && - (reloc->type == R_X86_64_PC32 || reloc->type == R_X86_64_PLT32)) - off += arch_dest_reloc_offset(reloc->addend); - else - off += reloc->addend; - - dest = find_insn(file, sec, off); - if (!dest) - return NULL; - - if (dest->type == INSN_ENDBR) { - if (!list_empty(&dest->call_node)) - list_del_init(&dest->call_node); - - return NULL; - } - - if (reloc->sym->static_call_tramp) - return NULL; - - return dest; -} - -static void warn_noendbr(const char *msg, struct section *sec, unsigned long offset, - struct instruction *dest) -{ - WARN_FUNC("%srelocation to !ENDBR: %s", sec, offset, msg, - offstr(dest->sec, dest->offset, false)); -} - -static void validate_ibt_dest(struct objtool_file *file, struct instruction *insn, - struct instruction *dest) -{ - if (dest->func && dest->func == insn->func) { - /* - * Anything from->to self is either _THIS_IP_ or IRET-to-self. - * - * There is no sane way to annotate _THIS_IP_ since the compiler treats the - * relocation as a constant and is happy to fold in offsets, skewing any - * annotation we do, leading to vast amounts of false-positives. - * - * There's also compiler generated _THIS_IP_ through KCOV and - * such which we have no hope of annotating. - * - * As such, blanket accept self-references without issue. - */ - return; - } - - if (dest->noendbr) - return; - - warn_noendbr("", insn->sec, insn->offset, dest); -} - -static void validate_ibt_insn(struct objtool_file *file, struct instruction *insn) -{ - struct instruction *dest; - struct reloc *reloc; - - switch (insn->type) { - case INSN_CALL: - case INSN_CALL_DYNAMIC: - case INSN_JUMP_CONDITIONAL: - case INSN_JUMP_UNCONDITIONAL: - case INSN_JUMP_DYNAMIC: - case INSN_JUMP_DYNAMIC_CONDITIONAL: - case INSN_RETURN: - /* - * We're looking for code references setting up indirect code - * flow. As such, ignore direct code flow and the actual - * dynamic branches. - */ - return; - - case INSN_NOP: - /* - * handle_group_alt() will create INSN_NOP instruction that - * don't belong to any section, ignore all NOP since they won't - * carry a (useful) relocation anyway. - */ - return; - - default: - break; - } - - for (reloc = insn_reloc(file, insn); - reloc; - reloc = find_reloc_by_dest_range(file->elf, insn->sec, - reloc->offset + 1, - (insn->offset + insn->len) - (reloc->offset + 1))) { - dest = validate_ibt_reloc(file, reloc); - if (dest) - validate_ibt_dest(file, insn, dest); - } -} - /* * Follow the branch starting at the given instruction, and recursively follow * any other branches (jumps). Meanwhile, track the frame pointer state at @@ -3500,9 +3392,6 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, break; } - if (opts.ibt) - validate_ibt_insn(file, insn); - if (insn->dead_end) return 0; @@ -3788,48 +3677,146 @@ static int validate_functions(struct objtool_file *file) return warnings; } -static int validate_ibt(struct objtool_file *file) +static void mark_endbr_used(struct instruction *insn) { - struct section *sec; + if (!list_empty(&insn->call_node)) + list_del_init(&insn->call_node); +} + +static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn) +{ + struct instruction *dest; struct reloc *reloc; + unsigned long off; + int warnings = 0; - for_each_sec(file, sec) { - bool is_data; + /* + * Looking for function pointer load relocations. Ignore + * direct/indirect branches: + */ + switch (insn->type) { + case INSN_CALL: + case INSN_CALL_DYNAMIC: + case INSN_JUMP_CONDITIONAL: + case INSN_JUMP_UNCONDITIONAL: + case INSN_JUMP_DYNAMIC: + case INSN_JUMP_DYNAMIC_CONDITIONAL: + case INSN_RETURN: + case INSN_NOP: + return 0; + default: + break; + } - /* already done in validate_branch() */ - if (sec->sh.sh_flags & SHF_EXECINSTR) - continue; + for (reloc = insn_reloc(file, insn); + reloc; + reloc = find_reloc_by_dest_range(file->elf, insn->sec, + reloc->offset + 1, + (insn->offset + insn->len) - (reloc->offset + 1))) { - if (!sec->reloc) + /* + * static_call_update() references the trampoline, which + * doesn't have (or need) ENDBR. Skip warning in that case. + */ + if (reloc->sym->static_call_tramp) continue; - if (!strncmp(sec->name, ".orc", 4)) - continue; + off = reloc->sym->offset; + if (reloc->type == R_X86_64_PC32 || reloc->type == R_X86_64_PLT32) + off += arch_dest_reloc_offset(reloc->addend); + else + off += reloc->addend; - if (!strncmp(sec->name, ".discard", 8)) + dest = find_insn(file, reloc->sym->sec, off); + if (!dest) continue; - if (!strncmp(sec->name, ".debug", 6)) + if (dest->type == INSN_ENDBR) { + mark_endbr_used(dest); continue; + } - if (!strcmp(sec->name, "_error_injection_whitelist")) + if (dest->func && dest->func == insn->func) { + /* + * Anything from->to self is either _THIS_IP_ or + * IRET-to-self. + * + * There is no sane way to annotate _THIS_IP_ since the + * compiler treats the relocation as a constant and is + * happy to fold in offsets, skewing any annotation we + * do, leading to vast amounts of false-positives. + * + * There's also compiler generated _THIS_IP_ through + * KCOV and such which we have no hope of annotating. + * + * As such, blanket accept self-references without + * issue. + */ continue; + } - if (!strcmp(sec->name, "_kprobe_blacklist")) + if (dest->noendbr) continue; - is_data = strstr(sec->name, ".data") || strstr(sec->name, ".rodata"); + WARN_FUNC("relocation to !ENDBR: %s", + insn->sec, insn->offset, + offstr(dest->sec, dest->offset, false)); - list_for_each_entry(reloc, &sec->reloc->reloc_list, list) { - struct instruction *dest; + warnings++; + } - dest = validate_ibt_reloc(file, reloc); - if (is_data && dest && !dest->noendbr) - warn_noendbr("data ", sec, reloc->offset, dest); - } + return warnings; +} + +static int validate_ibt_data_reloc(struct objtool_file *file, + struct reloc *reloc) +{ + struct instruction *dest; + + dest = find_insn(file, reloc->sym->sec, + reloc->sym->offset + reloc->addend); + if (!dest) + return 0; + + if (dest->type == INSN_ENDBR) { + mark_endbr_used(dest); + return 0; } - return 0; + if (dest->noendbr) + return 0; + + WARN_FUNC("data relocation to !ENDBR: %s", + reloc->sec->base, reloc->offset, + offstr(dest->sec, dest->offset, false)); + + return 1; +} + + +static int validate_ibt(struct objtool_file *file) +{ + struct section *sec; + struct reloc *reloc; + struct instruction *insn; + int warnings = 0; + + for_each_insn(file, insn) + warnings += validate_ibt_insn(file, insn); + + for_each_sec(file, sec) { + + if (!strstr(sec->name, ".data") && !strstr(sec->name, ".rodata")) + continue; + + if (!sec->reloc) + continue; + + list_for_each_entry(reloc, &sec->reloc->reloc_list, list) + warnings += validate_ibt_data_reloc(file, reloc); + } + + return warnings; } static int validate_reachable_instructions(struct objtool_file *file) -- 2.34.1