Received: by 2002:ac0:da4c:0:0:0:0:0 with SMTP id a12csp693643imi; Thu, 21 Jul 2022 09:07:41 -0700 (PDT) X-Google-Smtp-Source: AGRyM1sOEBaujnXnOiIGc/DSIF6Em3PRslaAaz91V/XHKyC98eoisO/ZhOYnhJjPY/4q2Y66ZrH8 X-Received: by 2002:a05:6870:65a0:b0:10c:ec:e9ec with SMTP id fp32-20020a05687065a000b0010c00ece9ecmr5416581oab.63.1658419660979; Thu, 21 Jul 2022 09:07:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1658419660; cv=none; d=google.com; s=arc-20160816; b=SQQbTjD8ZgL5bBqskIjW6M7gqY+udiZkfxt0r//9UJD4cBk9FHej5NHsyivd/eSE4r tZbk+WbwPdrfN17NUcfkUN+GKx9jozviXZWnJ5QDatZxTW6fGsUOQ/cnNhu+7WqQG1wG R8bxqurMU9zfUtU4dacuQK+LJK9Y2ygLLZBS83uN8Ys9BfiFsYhQDmX6Dh8mcJgPh7Cg dIvpb4vBcbLTZ7nVX288j9hLVabLChAsaqSxjXyAeGo35D5Afek9jZw5ACB5k8e3NKxJ FFqs6MLJIPuBr+eWTKt0qMHjZutqFwQUaKVCM9KMBIjrNVV4YsRI1SGxRiUtjdM72wS2 S4Fg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=OXzDgWNAnXOwdpceHc0k3d33+7QUehGvNXK1iZIzZMA=; b=b3qnsBXdq2xgh1jQ7TsABzebdpFJG9czdOo8nxqFoKpP39GUfvMdj2a1u536CVyfwS kuBvLkAbUj/cwwPTRrBkJBgdKtqmANp99n0z6wqNTtqSazRmlgpCY4bqoYafSM5dHNwc RmPYmkIys2nwsP7R0MialR/Spt9HPU+3PKzNPlG9eNCeQ4hj/rcQdG06mWjxH46pSPsA fvh2pRgmPu1ApRXr7SRGJxmO4x6+YJ3SpR+ofkHxlPbF8KuKaJcSUjZB3UERDJSuS55b 5fhRnNMZR1/WhFfU+8BS52l4j+ez6P1e1jY1OSFwoINT9a49+OZIlbo8yGn2rKAFe4Uj sjZg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@infradead.org header.s=casper.20170209 header.b=nJgtNcQN; 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 Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ay17-20020a056808301100b0033a8d517bb8si1993397oib.151.2022.07.21.09.07.26; Thu, 21 Jul 2022 09:07:40 -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=@infradead.org header.s=casper.20170209 header.b=nJgtNcQN; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231196AbiGUPzP (ORCPT + 99 others); Thu, 21 Jul 2022 11:55:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52256 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230518AbiGUPzN (ORCPT ); Thu, 21 Jul 2022 11:55:13 -0400 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4CAC064E2 for ; Thu, 21 Jul 2022 08:55:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=In-Reply-To:Content-Type:MIME-Version: References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=OXzDgWNAnXOwdpceHc0k3d33+7QUehGvNXK1iZIzZMA=; b=nJgtNcQNwjhdrI8llY65aVRZuN SMWD3dUGjXu9YIEwujccQkqPg2Dp8oA8C/i5TkzWLE2Q/qOfPfHTM7lbxu7k16+mOc0usWMaARcll eFOGjdorwt6YgT2qKPVqjNNpSN5lfshA0R31XY17SXiIPkCoSf9cmg6xd12WcSOyuupgnWEASTvEN qK1NyaLLJdY39//fi3v9gw60/7zQ+cpBs6/CWTsIetXNSkVJlkjiVbJdE5+gjcSsXBcu4ub9lSj9Y TNZgnqFtBDsIyhojsprKbvDfvQQnc9+pCqaa43Hz49ZVJDGsVtEcr5ffI4czIaYp+2ouugGJwT8Za g5IZlzlA==; Received: from j130084.upc-j.chello.nl ([24.132.130.84] helo=worktop.programming.kicks-ass.net) by casper.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1oEYVc-00FTBw-Eb; Thu, 21 Jul 2022 15:54:40 +0000 Received: by worktop.programming.kicks-ass.net (Postfix, from userid 1000) id E3C7F980BD2; Thu, 21 Jul 2022 17:54:38 +0200 (CEST) Date: Thu, 21 Jul 2022 17:54:38 +0200 From: Peter Zijlstra To: Sami Tolvanen Cc: Linus Torvalds , Thomas Gleixner , Joao Moreira , LKML , the arch/x86 maintainers , Tim Chen , Josh Poimboeuf , "Cooper, Andrew" , Pawan Gupta , Johannes Wikner , Alyssa Milburn , Jann Horn , "H.J. Lu" , "Moreira, Joao" , "Nuzman, Joseph" , Steven Rostedt , "Gross, Jurgen" , Masami Hiramatsu , Alexei Starovoitov , Daniel Borkmann , Peter Collingbourne , Kees Cook Subject: Re: [patch 00/38] x86/retbleed: Call depth tracking mitigation Message-ID: References: <2f7f899cb75b79b08b0662ff4d2cb877@overdrivepizza.com> <87fsiyuhyz.ffs@tglx> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_NONE 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 On Wed, Jul 20, 2022 at 11:13:16PM +0200, Peter Zijlstra wrote: > On Tue, Jul 19, 2022 at 10:19:18AM -0700, Sami Tolvanen wrote: > > > Clang's current CFI implementation is somewhat similar to this. It > > creates separate thunks for address-taken functions and changes > > function addresses in C code to point to the thunks instead. > > > > While this works, it creates painful situations when interacting with > > assembly (e.g. a function address taken in assembly cannot be used > > for indirect calls in C as it doesn't point to the thunk) and needs > > unpleasant hacks when we want take the actual function address in C > > (i.e. scattering the code with function_nocfi() calls). > > > > I have to agree with Peter on this, I would rather avoid messing with > > function pointers in KCFI to avoid these issues. > > It is either this; and I think I can avoid the worst of it (see below); > or grow the indirect_callsites to obscure the immediate (as Linus > suggested), there's around ~16k indirect callsites in a defconfig-ish > kernel, so growing it isn't too horrible, but it isn't nice either. > > The prettiest option to obscure the immediate at the callsite I could > conjure up is something like: > > kcfi_caller_linus: > movl $0x12345600, %r10d > movb $0x78, %r10b > cmpl %r10d, -OFFSET(%r11) > je 1f > ud2 > 1: call __x86_thunk_indirect_r11 > > Which comes to around 22 bytes (+5 over the original). My very firstest LLVM patch; except it explodes at runtime and I'm not sure where to start looking... On top of sami-llvm/kcfi If I comment out the orl and cmpl it compiles stuff, put either one back and it explodes in some very unhelpful message. The idea is the above callthunk that makes any offset work by not having the full hash as an immediate and allow kCFI along with -fpatchable-function-entry=N,M and include M in the offset. Specifically, I meant to use -fpatchable-function-entry=16,16, but alas, I never got that far. Help ? --- diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp index 5e011d409ee8..ffdb95324da7 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -124,23 +124,12 @@ void X86AsmPrinter::emitKCFITypeId(const MachineFunction &MF, OutStreamer->emitSymbolAttribute(FnSym, MCSA_ELF_TypeFunction); OutStreamer->emitLabel(FnSym); - // Emit int3 padding to allow runtime patching of the preamble. - EmitAndCountInstruction(MCInstBuilder(X86::INT3)); - EmitAndCountInstruction(MCInstBuilder(X86::INT3)); - // Embed the type hash in the X86::MOV32ri instruction to avoid special // casing object file parsers. EmitAndCountInstruction(MCInstBuilder(X86::MOV32ri) .addReg(X86::EAX) .addImm(Type->getZExtValue())); - // The type hash is encoded in the last four bytes of the X86::MOV32ri - // instruction. Emit additional X86::INT3 padding to ensure the hash is - // at offset -6 from the function start to avoid potential call target - // gadgets in checks emitted by X86AsmPrinter::LowerKCFI_CHECK. - EmitAndCountInstruction(MCInstBuilder(X86::INT3)); - EmitAndCountInstruction(MCInstBuilder(X86::INT3)); - if (MAI->hasDotTypeDotSizeDirective()) { MCSymbol *EndSym = OutContext.createTempSymbol("cfi_func_end"); OutStreamer->emitLabel(EndSym); diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp index 16c4d2e45970..d72e82f4f63a 100644 --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -1340,22 +1340,34 @@ void X86AsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) { assert(std::next(MI.getIterator())->isCall() && "KCFI_CHECK not followed by a call instruction"); - // The type hash is encoded in the last four bytes of the X86::CMP32mi - // instruction. If we decided to place the hash immediately before - // indirect call targets (offset -4), the X86::JCC_1 instruction we'll - // emit next would be a potential indirect call target as it's preceded - // by a valid type hash. - // - // To avoid generating useful gadgets, X86AsmPrinter::emitKCFITypeId - // emits the type hash prefix at offset -6, which makes X86::TRAP the - // only possible target in this instruction sequence. - EmitAndCountInstruction(MCInstBuilder(X86::CMP32mi) + const Function &F = MF->getFunction(); + unsigned Imm = MI.getOperand(1).getImm(); + unsigned Num; + + if (F.hasFnAttribute("patchable-function-prefix")) { + if (F.getFnAttribute("patchable-function-prefix") + .getValueAsString() + .getAsInteger(10, Num)) + Num = 0; + } + + // movl $0x12345600, %r10d + EmitAndCountInstruction(MCInstBuilder(X86::MOV32ri) + .addReg(X86::R10) + .addImm(Imm & ~0xff)); + + // orl $0x78, %r10d + EmitAndCountInstruction(MCInstBuilder(X86::OR32ri8) + .addReg(X86::R10) + .addImm(Imm & 0xff)); + + // cmpl %r10, -off(%r11) + EmitAndCountInstruction(MCInstBuilder(X86::CMP32rm) + .addReg(X86::R10) .addReg(MI.getOperand(0).getReg()) .addImm(1) .addReg(X86::NoRegister) - .addImm(-6) - .addReg(X86::NoRegister) - .addImm(MI.getOperand(1).getImm())); + .addImm(-(Num + 4))); MCSymbol *Pass = OutContext.createTempSymbol(); EmitAndCountInstruction(