From patchwork Tue Mar 26 01:21:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 13603227 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 655BEC54E64 for ; Tue, 26 Mar 2024 01:21:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Date:Subject:Cc :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=QuQ+N/3F63DNLuhUiejzSALJR3TaBrD8RzQ8V2HOwJY=; b=TQtYjObXjgBXsj aaJJszP+5+t66mjptMEnBurn4ouFnzl2dI4E9XTmyTsjMoWtXFwHputqkG9OwzrW/eRFlIKIpLMCZ EgKsK6ruLYMz+u70Ck13wk/QPFU0NEFy+ij6xh5Vuj8ESuzOxULCrGBGGpmI9CmFOqadOHoHDOzcw SVI8gHYn2mwctSmQXS4BSXuZQ6oqJVmR+K9nDBdxEYL1D4VhHUKGYzA8PCv9YKvV+ie5Lz6T1krAA b3GMl7ig2MHnIcbMUDdv0x4dsVxojENPNb/Pms0MDG3azi2TCrSXUF043Y3PWFEdOI7nDDkvPJtqJ 3g/0mEhOXDUxyxMUhVdg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rovV2-00000002cVy-3ABf; Tue, 26 Mar 2024 01:21:12 +0000 Received: from dfw.source.kernel.org ([139.178.84.217]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rovUz-00000002cV7-0lK6 for linux-riscv@lists.infradead.org; Tue, 26 Mar 2024 01:21:10 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 3786B61224; Tue, 26 Mar 2024 01:21:08 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 52DA3C433F1; Tue, 26 Mar 2024 01:21:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1711416067; bh=7b1vl46sDmGnCQuMlZMcbfRMULcOrVeHrbz4hUVNxeE=; h=From:To:Cc:Subject:Date:From; b=jOl0HhZU55WYhJxOL1ddNpj/1ZU7V0lLRLX9nWFC16Dcw4WiOA0rkqWBEzkJUJDMG MureUOks+NcIrGURJmL5xH4A6L8je9Bvxe3bqY7GVAipvaEzutChIkGk3hlxtd/Vnj hxtlaNYkX2uqcyLMKorz7uBSE+kyL9jZlBvlqO5fyx5MptmNtqyiSAhmgXp5V5RKUC kL8Kl6shrb6x7NpbmGkLmiYwhcUc6JT7Z24flC5mes8jk+eepavoBU/MX9r0So394E CuaIMK4ih6k5MXPiIZZIcC9Squ4LwR+gliew90/py7rxGhGPvGzDhHpD6PrjoDwGma e5mXC1TB0U6tw== From: Jarkko Sakkinen To: linux-riscv@lists.infradead.org Cc: Jarkko Sakkinen , Masami Hiramatsu , Paul Walmsley , Palmer Dabbelt , Albert Ou , linux-kernel@vger.kernel.org, Luis Chamberlain , linux-modules@vger.kernel.org, "Naveen N . Rao" , Anil S Keshavamurthy , "David S . Miller" Subject: [PATCH v6 1/2] kprobes: implemente trampoline memory allocator Date: Tue, 26 Mar 2024 03:21:01 +0200 Message-ID: <20240326012102.27438-1-jarkko@kernel.org> X-Mailer: git-send-email 2.44.0 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240325_182109_541516_CBE8F92D X-CRM114-Status: GOOD ( 26.90 ) X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org Tracing with kprobes while running a monolithic kernel is currently impossible because CONFIG_KPROBES depends on CONFIG_MODULES. Introduce alloc_execmem() and free_execmem() for allocating executable memory. If an arch implements these functions, it can mark this up with the HAVE_ALLOC_EXECMEM kconfig flag. The second new kconfig flag is ALLOC_EXECMEM, which can be selected if either MODULES is selected or HAVE_ALLOC_EXECMEM is support by the arch. If HAVE_ALLOC_EXECMEM is not supported by an arch, module_alloc() and module_memfree() are used as a fallback, thus retaining backwards compatibility to earlier kernel versions. This will allow architecture to enable kprobes traces without requiring to enable module. The support can be implemented with four easy steps: 1. Implement alloc_execmem(). 2. Implement free_execmem(). 3. Edit arch//Makefile. 4. Set HAVE_ALLOC_EXECMEM in arch//Kconfig. Link: https://lore.kernel.org/all/20240325115632.04e37297491cadfbbf382767@kernel.org/ Suggested-by: Masami Hiramatsu Signed-off-by: Jarkko Sakkinen --- v6: - Use null pointer for notifiers and register the module notifier only if IS_ENABLED(CONFIG_MODULES) is set. - Fixed typo in the commit message and wrote more verbose description of the feature. v5: - alloc_execmem() was missing GFP_KERNEL parameter. The patch set did compile because 2/2 had the fixup (leaked there when rebasing the patch set). v4: - Squashed a couple of unrequired CONFIG_MODULES checks. - See https://lore.kernel.org/all/D034M18D63EC.2Y11D954YSZYK@kernel.org/ v3: - A new patch added. - For IS_DEFINED() I need advice as I could not really find that many locations where it would be applicable. --- arch/Kconfig | 16 +++++++++++++++- include/linux/execmem.h | 13 +++++++++++++ kernel/kprobes.c | 19 +++++++++++++++---- kernel/trace/trace_kprobe.c | 15 +++++++++++++-- 4 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 include/linux/execmem.h diff --git a/arch/Kconfig b/arch/Kconfig index a5af0edd3eb8..33ba68b7168f 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -52,8 +52,8 @@ config GENERIC_ENTRY config KPROBES bool "Kprobes" - depends on MODULES depends on HAVE_KPROBES + select ALLOC_EXECMEM select KALLSYMS select TASKS_RCU if PREEMPTION help @@ -215,6 +215,20 @@ config HAVE_OPTPROBES config HAVE_KPROBES_ON_FTRACE bool +config HAVE_ALLOC_EXECMEM + bool + help + Architectures that select this option are capable of allocating executable + memory, which can be used by subsystems but is not dependent of any of its + clients. + +config ALLOC_EXECMEM + bool "Executable (trampoline) memory allocation" + depends on MODULES || HAVE_ALLOC_EXECMEM + help + Select this for executable (trampoline) memory. Can be enabled when either + module allocator or arch-specific allocator is available. + config ARCH_CORRECT_STACKTRACE_ON_KRETPROBE bool help diff --git a/include/linux/execmem.h b/include/linux/execmem.h new file mode 100644 index 000000000000..ae2ff151523a --- /dev/null +++ b/include/linux/execmem.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_EXECMEM_H +#define _LINUX_EXECMEM_H + +#ifdef CONFIG_HAVE_ALLOC_EXECMEM +void *alloc_execmem(unsigned long size, gfp_t gfp); +void free_execmem(void *region); +#else +#define alloc_execmem(size, gfp) module_alloc(size) +#define free_execmem(region) module_memfree(region) +#endif + +#endif /* _LINUX_EXECMEM_H */ diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 9d9095e81792..9ed07a4bf9e3 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -44,6 +44,7 @@ #include #include #include +#include #define KPROBE_HASH_BITS 6 #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS) @@ -113,17 +114,17 @@ enum kprobe_slot_state { void __weak *alloc_insn_page(void) { /* - * Use module_alloc() so this page is within +/- 2GB of where the + * Use alloc_execmem() so this page is within +/- 2GB of where the * kernel image and loaded module images reside. This is required * for most of the architectures. * (e.g. x86-64 needs this to handle the %rip-relative fixups.) */ - return module_alloc(PAGE_SIZE); + return alloc_execmem(PAGE_SIZE, GFP_KERNEL); } static void free_insn_page(void *page) { - module_memfree(page); + free_execmem(page); } struct kprobe_insn_cache kprobe_insn_slots = { @@ -1580,6 +1581,7 @@ static int check_kprobe_address_safe(struct kprobe *p, goto out; } +#ifdef CONFIG_MODULES /* Check if 'p' is probing a module. */ *probed_mod = __module_text_address((unsigned long) p->addr); if (*probed_mod) { @@ -1603,6 +1605,8 @@ static int check_kprobe_address_safe(struct kprobe *p, ret = -ENOENT; } } +#endif + out: preempt_enable(); jump_label_unlock(); @@ -2482,6 +2486,7 @@ int kprobe_add_area_blacklist(unsigned long start, unsigned long end) return 0; } +#ifdef CONFIG_MODULES /* Remove all symbols in given area from kprobe blacklist */ static void kprobe_remove_area_blacklist(unsigned long start, unsigned long end) { @@ -2499,6 +2504,7 @@ static void kprobe_remove_ksym_blacklist(unsigned long entry) { kprobe_remove_area_blacklist(entry, entry + 1); } +#endif /* CONFIG_MODULES */ int __weak arch_kprobe_get_kallsym(unsigned int *symnum, unsigned long *value, char *type, char *sym) @@ -2564,6 +2570,7 @@ static int __init populate_kprobe_blacklist(unsigned long *start, return ret ? : arch_populate_kprobe_blacklist(); } +#ifdef CONFIG_MODULES static void add_module_kprobe_blacklist(struct module *mod) { unsigned long start, end; @@ -2660,6 +2667,9 @@ static int kprobes_module_callback(struct notifier_block *nb, mutex_unlock(&kprobe_mutex); return NOTIFY_DONE; } +#else +#define kprobes_module_callback (NULL) +#endif /* CONFIG_MODULES */ static struct notifier_block kprobe_module_nb = { .notifier_call = kprobes_module_callback, @@ -2724,7 +2734,8 @@ static int __init init_kprobes(void) err = arch_init_kprobes(); if (!err) err = register_die_notifier(&kprobe_exceptions_nb); - if (!err) + + if (!err && IS_ENABLED(CONFIG_MODULES)) err = register_module_notifier(&kprobe_module_nb); kprobes_initialized = (err == 0); diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index c4c6e0e0068b..13ea0d0994d5 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -111,6 +111,7 @@ static nokprobe_inline bool trace_kprobe_within_module(struct trace_kprobe *tk, return strncmp(module_name(mod), name, len) == 0 && name[len] == ':'; } +#ifdef CONFIG_MODULES static nokprobe_inline bool trace_kprobe_module_exist(struct trace_kprobe *tk) { char *p; @@ -129,6 +130,9 @@ static nokprobe_inline bool trace_kprobe_module_exist(struct trace_kprobe *tk) return ret; } +#else +#define trace_kprobe_module_exist(tk) false /* aka a module never exists */ +#endif /* CONFIG_MODULES */ static bool trace_kprobe_is_busy(struct dyn_event *ev) { @@ -670,6 +674,7 @@ static int register_trace_kprobe(struct trace_kprobe *tk) return ret; } +#ifdef CONFIG_MODULES /* Module notifier call back, checking event on the module */ static int trace_kprobe_module_callback(struct notifier_block *nb, unsigned long val, void *data) @@ -699,6 +704,9 @@ static int trace_kprobe_module_callback(struct notifier_block *nb, return NOTIFY_DONE; } +#else +#define trace_kprobe_module_callback (NULL) +#endif /* CONFIG_MODULES */ static struct notifier_block trace_kprobe_module_nb = { .notifier_call = trace_kprobe_module_callback, @@ -1897,8 +1905,11 @@ static __init int init_kprobe_trace_early(void) if (ret) return ret; - if (register_module_notifier(&trace_kprobe_module_nb)) - return -EINVAL; + if (IS_ENABLED(CONFIG_MODULES)) { + ret = register_module_notifier(&trace_kprobe_module_nb); + if (ret) + return -EINVAL; + } return 0; } From patchwork Tue Mar 26 01:21:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 13603226 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EE0C5C54E58 for ; Tue, 26 Mar 2024 01:21:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=4/wvdu34oavw5Djx04G3SNAt5fjGpA7W+3ejM2wE3nE=; b=AtLs0uOlJ6xl2b w0Y2ezYflIqBxDaQ7z9vLAJW0alVtRuVcB7dXV4gv07wE3x8HkR4RWxqsMnVWdioA0lafiMlvSElz Ub/unygFrUjRaQTDpG8SuswUMsE7yIThgQo5iKWMAxdDtLQwRxRVmZE88m5IqB64kvW9XEVCA/ehR aSjwv2amylWeR9IHmiNiwIAUun/rmgrgnMD/z9l0SwxQHY0OvGq0PjmEHNnfkFmal9Rdazx6jqddI +0sMfFiIV/IEr/DAkY0qnhP0+xLU6BXd0Y9lsv3LbIpx7c2H/6B+AwRttfRBrvPyOtk1+iUy/uxJR 1XXFvyAygGLR02CkQnjA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rovV7-00000002cYJ-1njT; Tue, 26 Mar 2024 01:21:17 +0000 Received: from sin.source.kernel.org ([2604:1380:40e1:4800::1]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rovV4-00000002cWF-0UoO for linux-riscv@lists.infradead.org; Tue, 26 Mar 2024 01:21:16 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sin.source.kernel.org (Postfix) with ESMTP id 4D448CE1E01; Tue, 26 Mar 2024 01:21:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 576DAC433F1; Tue, 26 Mar 2024 01:21:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1711416071; bh=oxc669xa4HArX18pe0zMZ3KIpnQmQJWwkeqzhcN8JkQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VByYMOgnCP2iCf/wIvMGIWEZ4efp6NKR1i70mSvBsSMDbQX/BMpoSESqMLQLC+dCu Lttm79WU10PxVme+2sNIuUct8OAHnNjEAq/eg6C6/CBSLhAUQ7VqshB/vdVJdVFyZF OEY1sqJOQRV0KQ8XA462AGjzqXZa+p2s3roU9VwZOZ2H34LHiH8vtbBQcJlrYkGmH8 M4PKUXsTcaYDQCwCZxPhMT3g9b1AqE8+XTLQ7t/omtIYeje7yu6EpzGpLzLd6CsvPY 9LHe4AWYk0vXwKlhIaKm6P2VK14F47fMOXH03DiGDrI5nS/8J/7Qk9FvsWH2K25zWo GPL8moZhjgeJg== From: Jarkko Sakkinen To: linux-riscv@lists.infradead.org Cc: Jarkko Sakkinen , Paul Walmsley , Palmer Dabbelt , Albert Ou , linux-kernel@vger.kernel.org, Luis Chamberlain , linux-modules@vger.kernel.org, "Naveen N . Rao" , Anil S Keshavamurthy , "David S . Miller" , Masami Hiramatsu Subject: [PATCH v6 2/2] arch/riscv: Enable kprobes when CONFIG_MODULES=n Date: Tue, 26 Mar 2024 03:21:02 +0200 Message-ID: <20240326012102.27438-2-jarkko@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240326012102.27438-1-jarkko@kernel.org> References: <20240326012102.27438-1-jarkko@kernel.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240325_182114_635927_56C2E7C9 X-CRM114-Status: GOOD ( 15.60 ) X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org Tacing with kprobes while running a monolithic kernel is currently impossible due the kernel module allocator dependency. Address the issue by implementing textmem API for RISC-V. Link: https://www.sochub.fi # for power on testing new SoC's with a minimal stack Link: https://lore.kernel.org/all/20220608000014.3054333-1-jarkko@profian.com/ # continuation Signed-off-by: Jarkko Sakkinen --- v4: - Include linux/execmem.h. v3: - Architecture independent parts have been split to separate patches. - Do not change arch/riscv/kernel/module.c as it is out of scope for this patch set now. v2: - Better late than never right? :-) - Focus only to RISC-V for now to make the patch more digestable. This is the arch where I use the patch on a daily basis to help with QA. - Introduce HAVE_KPROBES_ALLOC flag to help with more gradual migration. --- arch/riscv/Kconfig | 1 + arch/riscv/kernel/Makefile | 3 +++ arch/riscv/kernel/execmem.c | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 arch/riscv/kernel/execmem.c diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index e3142ce531a0..499512fb17ff 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -132,6 +132,7 @@ config RISCV select HAVE_KPROBES if !XIP_KERNEL select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL select HAVE_KRETPROBES if !XIP_KERNEL + select HAVE_ALLOC_EXECMEM if !XIP_KERNEL # https://github.com/ClangBuiltLinux/linux/issues/1881 select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if !LD_IS_LLD select HAVE_MOVE_PMD diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index 604d6bf7e476..337797f10d3e 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -73,6 +73,9 @@ obj-$(CONFIG_SMP) += cpu_ops.o obj-$(CONFIG_RISCV_BOOT_SPINWAIT) += cpu_ops_spinwait.o obj-$(CONFIG_MODULES) += module.o +ifeq ($(CONFIG_ALLOC_EXECMEM),y) +obj-y += execmem.o +endif obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o obj-$(CONFIG_CPU_PM) += suspend_entry.o suspend.o diff --git a/arch/riscv/kernel/execmem.c b/arch/riscv/kernel/execmem.c new file mode 100644 index 000000000000..3e52522ead32 --- /dev/null +++ b/arch/riscv/kernel/execmem.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include + +void *alloc_execmem(unsigned long size, gfp_t /* gfp */) +{ + return __vmalloc_node_range(size, 1, MODULES_VADDR, + MODULES_END, GFP_KERNEL, + PAGE_KERNEL, 0, NUMA_NO_NODE, + __builtin_return_address(0)); +} + +void free_execmem(void *region) +{ + if (in_interrupt()) + pr_warn("In interrupt context: vmalloc may not work.\n"); + + vfree(region); +}