Received: by 2002:a05:6358:1087:b0:cb:c9d3:cd90 with SMTP id j7csp2904331rwi; Fri, 21 Oct 2022 09:08:54 -0700 (PDT) X-Google-Smtp-Source: AMsMyM413QWgARKKTIORbe25pW5aTAlGiMzhF+x4WT6cWtGr93QvoUN64Qte8p2OqnYzBAj0FZ0c X-Received: by 2002:a17:90b:1649:b0:20d:2d96:6b05 with SMTP id il9-20020a17090b164900b0020d2d966b05mr59056001pjb.9.1666368534109; Fri, 21 Oct 2022 09:08:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666368534; cv=none; d=google.com; s=arc-20160816; b=Sn/Emaf8atbIUNITbzDIbv+QzIwTOO4rEfP6wCFGO2w6uFWfEO4yjVAkHmKCc8Du9+ mfE08YexUbbsxoxYZCKL/2lfyr453oHmz7cV6x1TR6907GllUn6X9bzkdG0m4CEaJa+A nICBFh12GMP/eVpbFBPLbdLW6cCOVUO9RGbMwBSZt8rwQGkGaEZ4X3SJ2nP6woLtDFQ4 hZ7/hU+WCj9StfcEYvkru5gVGGmLyv4E5Sn3pfoBrFEEy9qb5P9zTNoJDIObLPsEzqXb Ql2EPKhWd6g/P/jpyST3YJkULUhOw1JeU5MmBg+MK4Ib/vpaBAYlUSYwibyFQPmuXC3z XD3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-disposition:mime-version:message-id :subject:cc:to:from:date; bh=DNCBlBKpzX+vosp9kft4BH5Fq6/KIiOZu6s/OXW2Jjo=; b=L18BsUGBMQEURJTOJuWJiQZ4Kqp1VKhhaoQHplnGYBoSqpxLEWk0kKDNLtd+Sh5z3m jFb8W30R9+dcXYHOvbMPqEAVG45XEv2a274ltO5Zqmzr/C4OHRclE6ECwYyK6xjHhB+R SQ6qgJ4QO4mq9uTbWnIo+XfOmP6mfaHuwqGmvcN9yvDKBRJMB3F1aAzxc9rr+6FcC1YH LoLat8BUURQWYnqj+9WJXC8EUpwEhJ9QEN4Zi12e9YWJIIhRoqTleUPhUMJdJtLUQsao ybA2Wy19sGCvD9jek9BhpI2/0Drx1nnnu9DFWm3Ron4Hm0yZCLf8NJzs7aN6ge4/VVFr Uj7w== ARC-Authentication-Results: i=1; mx.google.com; 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=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g6-20020a656cc6000000b0041b7be8ef1csi25596511pgw.219.2022.10.21.09.08.40; Fri, 21 Oct 2022 09:08:54 -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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230268AbiJUP5C (ORCPT + 99 others); Fri, 21 Oct 2022 11:57:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43578 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230243AbiJUP4y (ORCPT ); Fri, 21 Oct 2022 11:56:54 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D0E2018E73E for ; Fri, 21 Oct 2022 08:56:31 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 96D9B1063; Fri, 21 Oct 2022 08:56:37 -0700 (PDT) Received: from FVFF77S0Q05N (unknown [10.57.6.231]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9017B3F792; Fri, 21 Oct 2022 08:56:29 -0700 (PDT) Date: Fri, 21 Oct 2022 16:56:20 +0100 From: Mark Rutland To: llvm@lists.linux.dev Cc: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Fangrui Song , Joao Moreira , Josh Poimboeuf , Kees Cook , Nathan Chancellor , Nick Desaulniers , Peter Zijlstra , Sami Tolvanen Subject: kCFI && patchable-function-entry=M,N Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW, 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 Hi, For arm64, I'd like to use -fatchable-function-entry=M,N (where N > 0), for our ftrace implementation, which instruments *some* but not all functions. Unfortuntately, this doesn't play nicely with -fsanitize=kcfi, as instrumented and non-instrumented functions don't agree on where the type hash should live relative to the function entry point, making them incompatible with one another. AFAICT, there's no mechanism today to get them to agree. Today we use -fatchable-function-entry=2, which happens to avoid this. For example, in the below, functions with N=0 expect the type hash to be placed 4 bytes before the entry point, and functions with N=2 expect the type hash to be placed 12 bytes before the entry point. | % cat test.c | #define __notrace __attribute__((patchable_function_entry(0, 0))) | | void callee_patchable(void) | { | } | | void __notrace callee_non_patchable(void) | { | } | | typedef void (*callee_fn_t)(void); | | void caller_patchable(callee_fn_t callee) | { | callee(); | } | | void __notrace caller_non_patchable(callee_fn_t callee) | { | callee(); | } | % clang --target=aarch64-linux -c test.c -fpatchable-function-entry=2,2 -fsanitize=kcfi -O2 | % aarch64-linux-objdump -d test.o | | test.o: file format elf64-littleaarch64 | | | Disassembly of section .text: | | 0000000000000000 : | 0: a540670c .word 0xa540670c | 4: d503201f nop | 8: d503201f nop | | 000000000000000c : | c: d65f03c0 ret | 10: a540670c .word 0xa540670c | | 0000000000000014 : | 14: d65f03c0 ret | 18: 07d85f31 .word 0x07d85f31 | 1c: d503201f nop | 20: d503201f nop | | 0000000000000024 : | 24: b85f4010 ldur w16, [x0, #-12] | 28: 728ce191 movk w17, #0x670c | 2c: 72b4a811 movk w17, #0xa540, lsl #16 | 30: 6b11021f cmp w16, w17 | 34: 54000040 b.eq 3c // b.none | 38: d4304400 brk #0x8220 | 3c: d61f0000 br x0 | 40: 07d85f31 .word 0x07d85f31 | | 0000000000000044 : | 44: b85fc010 ldur w16, [x0, #-4] | 48: 728ce191 movk w17, #0x670c | 4c: 72b4a811 movk w17, #0xa540, lsl #16 | 50: 6b11021f cmp w16, w17 | 54: 54000040 b.eq 5c // b.none | 58: d4304400 brk #0x8220 | 5c: d61f0000 br x0 On arm64, I'd like to use -fpatchable-function-entry=4,2 on arm64, along with -falign-functions=8, so that we can place a naturally-aligned 8-byte literal before the function (e.g. a pointer value). That allows us to implement an efficient per-callsite hook without hitting branch range limitations and/or requiring trampolines. I have a PoC that works without kCFI at: https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arm64/ftrace/per-callsite-ops I mentioned this in the #clangbuiltlinux IRQ channel, and Sami wrote up a github issue at: https://github.com/ClangBuiltLinux/linux/issues/1744 Currently clang generates: | < HASH > | NOP | NOP | func: BTI // optional | NOP | NOP ... and to make this consistent with non-instrumented functions, the non-instrumented functions would need pre-function padding before their hashes. For my use-case, it doesn't matter where the pre-function NOPs are placed relative to the type hash, so long as the location is consistent, and it might be nicer to have the option to place the pre-function NOPs before the hash, which would avoid needing to change non-instrumented functions (and save some space) e.g. | NOP | NOP | < HASH > | func: BTI // optional | NOP | NOP ... but I understand that for x86, folk want the pre-function NOPs to fall-through into the body of the function. Is there any mechanism today that we could use to solve this, or could we extend clang to have some options to control this behaviour? It would also be helpful to have a symbol before both the hash and pre-function NOPs so that we can filter those out of probes patching (I see that x86 does this with the __cfi_function symbol). Thanks, Mark.