linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Jinchao Wang <wangjinchao600@gmail.com>
To: akpm@linux-foundation.org
Cc: mhiramat@kernel.org, naveen@kernel.org, davem@davemloft.net,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	linux-trace-kernel@vger.kernel.org,
	Jinchao Wang <wangjinchao600@gmail.com>
Subject: [RFC PATCH 06/13] mm/kstackwatch: Add stack address resolution functions
Date: Mon, 18 Aug 2025 20:26:11 +0800	[thread overview]
Message-ID: <20250818122720.434981-7-wangjinchao600@gmail.com> (raw)
In-Reply-To: <20250818122720.434981-6-wangjinchao600@gmail.com>

Implement core stack analysis functionality for locating and validating
watch targets within kernel stack frames.

This patch provides the essential stack manipulation functions needed
to translate watch configurations into actual memory addresses:

Key functions:
1. ksw_stack_find_canary() - Locates compiler-generated stack canaries
   by scanning stack frames for the current task's canary value
2. ksw_stack_resolve_offset() - Converts relative stack offsets into
   absolute memory addresses using register state
3. ksw_stack_validate_addr() - Ensures target addresses fall within
   valid stack boundaries to prevent invalid memory access
4. ksw_stack_prepare_watch() - Unified interface that resolves watch
   configurations into concrete addresses and lengths for HWBP setup

Local variable resolution:
- Uses register state (pt_regs) to determine current stack pointer
- Calculates target addresses using SP + configured offset
- Validates addresses against THREAD_SIZE stack boundaries

All functions are marked __maybe_unused to avoid compiler warnings
during incremental development, as they will be integrated with
kprobe handlers in subsequent patches.

Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
---
 mm/kstackwatch/kstackwatch.h |   5 ++
 mm/kstackwatch/stack.c       | 112 +++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+)

diff --git a/mm/kstackwatch/kstackwatch.h b/mm/kstackwatch/kstackwatch.h
index 910f49014715..c24a651977c0 100644
--- a/mm/kstackwatch/kstackwatch.h
+++ b/mm/kstackwatch/kstackwatch.h
@@ -6,6 +6,7 @@
 
 #define MAX_FUNC_NAME_LEN 64
 #define MAX_CONFIG_STR_LEN 128
+#define MAX_FRAME_SEARCH 128
 
 /* Watch target types */
 enum watch_type {
@@ -38,6 +39,10 @@ struct ksw_config {
 
 extern bool panic_on_catch;
 
+/* stack management */
+int ksw_stack_init(struct ksw_config *config);
+void ksw_stack_exit(void);
+
 /* watch management */
 int ksw_watch_init(struct ksw_config *config);
 void ksw_watch_exit(void);
diff --git a/mm/kstackwatch/stack.c b/mm/kstackwatch/stack.c
index e69de29bb2d1..8b558cdbda97 100644
--- a/mm/kstackwatch/stack.c
+++ b/mm/kstackwatch/stack.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/stackprotector.h>
+#include <linux/kprobes.h>
+#include <asm/stacktrace.h>
+
+#include "kstackwatch.h"
+
+/* Find canary address in current stack frame */
+static unsigned long __maybe_unused ksw_stack_find_canary(struct pt_regs *regs)
+{
+	unsigned long *stack_ptr, *stack_end;
+	unsigned long expected_canary;
+	unsigned int i;
+
+	if (!regs || !regs->sp)
+		return 0;
+
+	stack_ptr = (unsigned long *)regs->sp;
+	stack_end =
+		(unsigned long *)current->stack + THREAD_SIZE / sizeof(long);
+	expected_canary = current->stack_canary;
+
+	for (i = 0; i < MAX_FRAME_SEARCH && &stack_ptr[i] < stack_end; i++) {
+		if (stack_ptr[i] == expected_canary) {
+			pr_info("KSW: Canary found i:%d 0x%px\n", i,
+				&stack_ptr[i]);
+			return (unsigned long)&stack_ptr[i];
+		}
+	}
+
+	return 0;
+}
+
+/* Resolve stack offset to actual address */
+static unsigned long __maybe_unused ksw_stack_resolve_offset(struct pt_regs *regs,
+					      s64 local_var_offset)
+{
+	unsigned long stack_base;
+	unsigned long target_addr;
+
+	if (!regs)
+		return 0;
+
+	/* Use stack pointer as base for offset calculation */
+	stack_base = regs->sp;
+	target_addr = stack_base + local_var_offset;
+
+	pr_info("KSW: %s sp:0x%lx offset: %llx, target: 0x%lx\n", __func__,
+		stack_base, local_var_offset, target_addr);
+
+	return target_addr;
+}
+
+/* Validate that address is within current stack bounds */
+static int __maybe_unused ksw_stack_validate_addr(unsigned long addr, size_t size)
+{
+	unsigned long stack_start, stack_end;
+
+	if (!addr || !size)
+		return -EINVAL;
+
+	stack_start = (unsigned long)current->stack;
+	stack_end = stack_start + THREAD_SIZE;
+
+	if (addr < stack_start || (addr + size) > stack_end) {
+		pr_warn("KSW: Address 0x%lx (size %zu) outside stack bounds [0x%lx-0x%lx]\n",
+			addr, size, stack_start, stack_end);
+		return -ERANGE;
+	}
+
+	return 0;
+}
+
+/* Setup hardware breakpoints for active watches */
+static int __maybe_unused ksw_stack_prepare_watch(struct pt_regs *regs,
+				   struct ksw_config *config, u64 *watch_addr,
+				   u64 *watch_len)
+{
+	u64 addr;
+	u64 len;
+
+	/* Resolve addresses for all active watches */
+	switch (config->type) {
+	case WATCH_CANARY:
+		addr = ksw_stack_find_canary(regs);
+		len = 8;
+		break;
+
+	case WATCH_LOCAL_VAR:
+		addr = ksw_stack_resolve_offset(regs, config->local_var_offset);
+		if (!addr) {
+			pr_err("KSW: Invalid stack var offset %u\n",
+			       config->local_var_offset);
+			return -EINVAL;
+		}
+		if (ksw_stack_validate_addr(addr, config->local_var_len)) {
+			pr_err("KSW: Invalid stack var len %u\n",
+			       config->local_var_len);
+		}
+		len = config->local_var_len;
+		break;
+
+	default:
+		pr_warn("KSW: Unknown watch type %d\n", config->type);
+		return -EINVAL;
+	}
+
+	*watch_addr = addr;
+	*watch_len = len;
+	return 0;
+}
-- 
2.43.0



  reply	other threads:[~2025-08-18 12:28 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-18 12:26 [RFC PATCH 00/13] mm: Introduce Kernel Stack Watch debugging tool Jinchao Wang
2025-08-18 12:26 ` [RFC PATCH 01/13] mm: Add kstackwatch build infrastructure Jinchao Wang
2025-08-18 12:26   ` [RFC PATCH 02/13] x86/HWBP: Add arch_reinstall_hw_breakpoint() for atomic updates Jinchao Wang
2025-08-18 12:26     ` [RFC PATCH 03/13] mm/kstackwatch: Add module core and configuration interface Jinchao Wang
2025-08-18 12:26       ` [RFC PATCH 04/13] mm/kstackwatch: Add HWBP pre-allocation infrastructure Jinchao Wang
2025-08-18 12:26         ` [RFC PATCH 05/13] mm/kstackwatch: Add atomic HWBP arm/disarm operations Jinchao Wang
2025-08-18 12:26           ` Jinchao Wang [this message]
2025-08-18 12:26             ` [RFC PATCH 07/13] mm/kstackwatch: Add kprobe and stack watch control Jinchao Wang
2025-08-18 12:26               ` [RFC PATCH 08/13] mm/kstackwatch: Wire up watch and stack subsystems in module core Jinchao Wang
2025-08-18 12:26                 ` [RFC PATCH 09/13] mm/kstackwatch: Add architecture support validation Jinchao Wang
2025-08-18 12:26                   ` [RFC PATCH 10/13] mm/kstackwatch: Handle nested function calls Jinchao Wang
2025-08-18 12:26                     ` [RFC PATCH 11/13] mm/kstackwatch: Ignore corruption in kretprobe trampolines Jinchao Wang
2025-08-18 12:26                       ` [RFC PATCH 12/13] mm/kstackwatch: Add debug and test functions Jinchao Wang
2025-08-18 12:26                         ` [RFC PATCH 13/13] mm/kstackwatch: Add a test module and script Jinchao Wang
2025-08-25 10:31               ` [RFC PATCH 07/13] mm/kstackwatch: Add kprobe and stack watch control Masami Hiramatsu
2025-08-25 13:11                 ` Jinchao Wang
2025-09-01  7:06     ` [RFC PATCH 02/13] x86/HWBP: Add arch_reinstall_hw_breakpoint() for atomic updates Masami Hiramatsu
2025-09-01 10:23       ` Jinchao Wang
2025-09-02 14:11         ` Masami Hiramatsu
2025-09-03  7:58           ` Jinchao Wang
2025-09-04  0:53             ` Jinchao Wang
2025-09-04  1:02             ` Masami Hiramatsu
2025-09-04  1:15               ` Jinchao Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250818122720.434981-7-wangjinchao600@gmail.com \
    --to=wangjinchao600@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=davem@davemloft.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=naveen@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox