Linux Trace Kernel
 help / color / mirror / Atom feed
From: Jens Remus <jremus@linux.ibm.com>
To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
	linux-s390@vger.kernel.org, x86@kernel.org,
	Steven Rostedt <rostedt@kernel.org>,
	Josh Poimboeuf <jpoimboe@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Jens Remus <jremus@linux.ibm.com>,
	Heiko Carstens <hca@linux.ibm.com>,
	Vasily Gorbik <gor@linux.ibm.com>,
	Alexander Gordeev <agordeev@linux.ibm.com>,
	Ilya Leoshkevich <iii@linux.ibm.com>,
	Indu Bhagat <ibhagatgnu@gmail.com>,
	Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
	Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Namhyung Kim <namhyung@kernel.org>,
	Andrii Nakryiko <andrii@kernel.org>, Kees Cook <kees@kernel.org>,
	Sam James <sam@gentoo.org>
Subject: [RFC PATCH v1 25/25] unwind_user/eh_frame: Add prctl() interface for (un)registering .eh_frame_hdr sections
Date: Tue, 18 Aug 2026 16:49:54 +0200	[thread overview]
Message-ID: <20260818144954.2320378-26-jremus@linux.ibm.com> (raw)
In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com>

The kernel does not have direct visibility to the ELF contents of
shared libraries.  Add prctl() interfaces to register and unregister
.eh_frame_hdr sections that allow dynamic linkers to tell the kernel
where to find these.

Both prctl's take a pointer to a new structure:

  struct eh_frame_setup {
	__u64	eh_frame_hdr_start;
	__u64	eh_frame_hdr_size;
	__u64	text_start;
	__u64	text_size;
  };

and a size of the passed in structure.  If the prctl's need to be
extended, then the structure could be changes and the sizre of that
structure will tell the kernel what it is the new version.  If the
kernel does not recognize the structure, it returns -EINVAL.

  eh_frame_hdr_start - Virtual address of the .eh_frame_hdr section
  eh_frame_hdr_size  - Length of the .eh_frame_hdr section
  text_start         - Virtual address of the related text section
  text_size          - Length of the related text section

The unregister only needs the eh_frame_hdr_start and requires all of
the remaining fields to be zero.

Based on Steven's patch "[PATCH v2] unwind: Add sframe_(un)register()
system calls". [1]

[1]: https://lore.kernel.org/all/20260528151023.00f5ec4e@gandalf.local.home/

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
 include/linux/eh_frame.h      | 20 +++++++++++++++
 include/uapi/linux/eh_frame.h | 14 +++++++++++
 include/uapi/linux/prctl.h    |  4 +++
 kernel/sys.c                  | 11 +++++++++
 kernel/unwind/eh_frame.c      | 46 +++++++++++++++++++++++++++++++++++
 5 files changed, 95 insertions(+)
 create mode 100644 include/uapi/linux/eh_frame.h

diff --git a/include/linux/eh_frame.h b/include/linux/eh_frame.h
index de68f21e1050..540beab5bf61 100644
--- a/include/linux/eh_frame.h
+++ b/include/linux/eh_frame.h
@@ -6,6 +6,8 @@
 #include <linux/srcu.h>
 #include <linux/unwind_user_types.h>
 
+struct eh_frame_setup;
+
 #ifdef CONFIG_HAVE_UNWIND_USER_EH_FRAME
 
 struct eh_frame_section {
@@ -39,6 +41,12 @@ extern int eh_frame_add_section(unsigned long eh_frame_hdr_start,
 				unsigned long text_start,
 				unsigned long text_end);
 extern int eh_frame_remove_section(unsigned long eh_frame_hdr_start);
+
+extern int eh_frame_register(struct eh_frame_setup __user *user_data,
+			     __kernel_size_t size);
+extern int eh_frame_unregister(struct eh_frame_setup __user *user_data,
+			       __kernel_size_t size);
+
 extern int eh_frame_find(unsigned long ip, struct unwind_user_frame *frame);
 
 static inline bool current_has_eh_frame(void)
@@ -77,6 +85,18 @@ static inline int eh_frame_find(unsigned long ip, struct unwind_user_frame *fram
 	return -ENOSYS;
 }
 
+static inline int eh_frame_register(struct eh_frame_setup __user *user_data,
+				    __kernel_size_t size)
+{
+	return -EINVAL;
+}
+
+static inline int eh_frame_unregister(struct eh_frame_setup __user *user_data,
+				      __kernel_size_t size)
+{
+	return -EINVAL;
+}
+
 static inline bool current_has_eh_frame(void) { return false; }
 
 #endif /* CONFIG_HAVE_UNWIND_USER_EH_FRAME */
diff --git a/include/uapi/linux/eh_frame.h b/include/uapi/linux/eh_frame.h
new file mode 100644
index 000000000000..8cca3792f323
--- /dev/null
+++ b/include/uapi/linux/eh_frame.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_EH_FRAME_H
+#define _UAPI_LINUX_EH_FRAME_H
+
+#include <linux/types.h>
+
+struct eh_frame_setup {
+	__u64	eh_frame_hdr_start;
+	__u64	eh_frame_hdr_size;
+	__u64	text_start;
+	__u64	text_size;
+};
+
+#endif /* _UAPI_LINUX_EH_FRAME_H */
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index b6ec6f693719..801a209bab3f 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -416,4 +416,8 @@ struct prctl_mm_map {
 # define PR_CFI_DISABLE		_BITUL(1)
 # define PR_CFI_LOCK		_BITUL(2)
 
+/* EH_FRAME management */
+#define PR_REGISTER_EH_FRAME		82
+#define PR_UNREGISTER_EH_FRAME		83
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/kernel/sys.c b/kernel/sys.c
index df69bd71de03..ee67badf267c 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -65,6 +65,7 @@
 #include <linux/rcupdate.h>
 #include <linux/uidgid.h>
 #include <linux/cred.h>
+#include <linux/eh_frame.h>
 
 #include <linux/nospec.h>
 
@@ -2907,6 +2908,16 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
 		if (arg3 & PR_CFI_LOCK && !(arg3 & PR_CFI_DISABLE))
 			error = arch_prctl_lock_branch_landing_pad_state(me);
 		break;
+	case PR_REGISTER_EH_FRAME:
+		if (arg4 || arg5)
+			return -EINVAL;
+		error = eh_frame_register((void __user *)arg2, arg3);
+		break;
+	case PR_UNREGISTER_EH_FRAME:
+		if (arg4 || arg5)
+			return -EINVAL;
+		error = eh_frame_unregister((void __user *)arg2, arg3);
+		break;
 	default:
 		trace_task_prctl_unknown(option, arg2, arg3, arg4, arg5);
 		error = -EINVAL;
diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c
index 49e8a3e8d794..12279f02381d 100644
--- a/kernel/unwind/eh_frame.c
+++ b/kernel/unwind/eh_frame.c
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/unwind_user_types.h>
 #include <linux/unwind_user_eh_frame_types.h>
+#include <uapi/linux/eh_frame.h>
 
 #include "eh_frame.h"
 #include "eh_frame_debug.h"
@@ -1723,3 +1724,48 @@ void eh_frame_free_mm(struct mm_struct *mm)
 
 	mtree_destroy(&mm->eh_frame_mt);
 }
+
+int eh_frame_register(struct eh_frame_setup __user *user_data, __kernel_size_t size)
+{
+	struct eh_frame_setup data;
+	unsigned long eh_frame_hdr_end, text_end;
+
+	if (!user_data && !size)
+		return -EINVAL;
+
+	if (size != sizeof(data))
+		return -EINVAL;
+
+	if (copy_from_user(&data, user_data, sizeof(data)))
+		return -EFAULT;
+
+	if (check_add_overflow(data.eh_frame_hdr_start, data.eh_frame_hdr_size,
+			       &eh_frame_hdr_end))
+		return -EINVAL;
+
+	if (check_add_overflow(data.text_start, data.text_size, &text_end))
+		return -EINVAL;
+
+	return eh_frame_add_section(data.eh_frame_hdr_start, eh_frame_hdr_end,
+				    data.text_start, text_end);
+}
+
+int eh_frame_unregister(struct eh_frame_setup __user *user_data, __kernel_size_t size)
+{
+	struct eh_frame_setup data;
+
+	if (!user_data && !size)
+		return -EINVAL;
+
+	if (size != sizeof(data))
+		return -EINVAL;
+
+	if (copy_from_user(&data, user_data, sizeof(data)))
+		return -EFAULT;
+
+	/* Unregister only uses eh_frame_hdr_start */
+	if (data.eh_frame_hdr_size || data.text_start || data.text_size)
+		return -EINVAL;
+
+	return eh_frame_remove_section(data.eh_frame_hdr_start);
+}
-- 
2.53.0


  parent reply	other threads:[~2026-08-18 14:50 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-18 14:49 [RFC PATCH v1 00/25] unwind_user: Implement .eh_frame handling Jens Remus
2026-08-18 14:49 ` [RFC PATCH v1 01/25] unwind_user: Add generic and arch-specific headers to MAINTAINERS Jens Remus
2026-08-18 14:49 ` [RFC PATCH v1 02/25] unwind_user: Stop when reaching an outermost frame Jens Remus
2026-08-18 14:56   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 03/25] unwind_user: Enable archs that pass RA in a register Jens Remus
2026-08-18 14:58   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 04/25] unwind_user: Flexible FP/RA recovery rules Jens Remus
2026-08-18 14:58   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 05/25] unwind_user: Flexible CFA " Jens Remus
2026-08-18 14:57   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 06/25] unwind_user: Enable archs that define CFA = SP_callsite + offset Jens Remus
2026-08-18 14:57   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 07/25] unwind_user/eh_frame: Add support for reading .eh_frame_hdr section Jens Remus
2026-08-18 15:02   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 08/25] unwind_user/eh_frame: Store .eh_frame_hdr section data in per-mm maple tree Jens Remus
2026-08-18 15:08   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 09/25] unwind_user/eh_frame: Add support for reading .eh_frame section Jens Remus
2026-08-18 15:05   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 10/25] unwind_user/eh_frame: Detect .eh_frame_hdr sections in executables Jens Remus
2026-08-18 15:18   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 11/25] unwind_user/eh_frame: Wire up unwind_user to eh_frame Jens Remus
2026-08-18 15:09   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 12/25] unwind_user/eh_frame: Remove .eh_frame[_hdr] section on detected corruption Jens Remus
2026-08-18 15:10   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 13/25] unwind_user/eh_frame: Show file name in debug output Jens Remus
2026-08-18 15:00   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 14/25] unwind_user/eh_frame: Add .eh_frame[_hdr] validation option Jens Remus
2026-08-18 15:08   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 15/25] unwind_user/eh_frame: Duplicate registered .eh_frame[_hdr] section data on clone/fork Jens Remus
2026-08-18 15:11   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 16/25] unwind_user/eh_frame: Add linear .eh_frame search fallback Jens Remus
2026-08-18 15:06   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 17/25] unwind_user/eh_frame: Ignore DW_CFA_GNU_args_size Jens Remus
2026-08-18 15:04   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 18/25] unwind_user/eh_frame: Add support for DWARF expressions Jens Remus
2026-08-18 15:13   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 19/25] x86/uaccess: Add unsafe_copy_from_user() implementation Jens Remus
2026-08-18 15:08   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 20/25] unwind_user/eh_frame/x86: Enable eh_frame unwinding on x86 Jens Remus
2026-08-18 15:04   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 21/25] unwind_user/eh_frame/x86: Handle PLT expressions Jens Remus
2026-08-18 15:10   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 22/25] unwind_user/eh_frame/x86: Handle DRAP expressions Jens Remus
2026-08-18 15:10   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 23/25] s390/ptrace: Provide frame_pointer() Jens Remus
2026-08-18 15:06   ` sashiko-bot
2026-08-18 14:49 ` [RFC PATCH v1 24/25] unwind_user/eh_frame/s390: Enable eh_frame unwinding on s390 Jens Remus
2026-08-18 15:15   ` sashiko-bot
2026-08-18 14:49 ` Jens Remus [this message]
2026-08-18 15:17   ` [RFC PATCH v1 25/25] unwind_user/eh_frame: Add prctl() interface for (un)registering .eh_frame_hdr sections sashiko-bot
2026-08-18 17:21 ` [RFC PATCH v1 00/25] unwind_user: Implement .eh_frame handling Steven Rostedt

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=20260818144954.2320378-26-jremus@linux.ibm.com \
    --to=jremus@linux.ibm.com \
    --cc=agordeev@linux.ibm.com \
    --cc=andrii@kernel.org \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=gor@linux.ibm.com \
    --cc=hca@linux.ibm.com \
    --cc=hpa@zytor.com \
    --cc=ibhagatgnu@gmail.com \
    --cc=iii@linux.ibm.com \
    --cc=jpoimboe@kernel.org \
    --cc=kees@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@kernel.org \
    --cc=sam@gentoo.org \
    --cc=tglx@kernel.org \
    --cc=x86@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