[Lldb-commits] [lldb] [lldb] Add `process launch --memory-tagging` option (PR #162944)
Julian Lettner via lldb-commits
lldb-commits at lists.llvm.org
Fri Oct 10 16:58:56 PDT 2025
https://github.com/yln created https://github.com/llvm/llvm-project/pull/162944
For debugging and bug-finding workflows, support
launching processes with MTE for binaries that are
not MTE entitled.
>From 5bcb5baa7f5ccfb0501c689de078ffff7c5d6a8d Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 14 Nov 2024 15:43:24 -0800
Subject: [PATCH 1/2] [lldb] Add `process launch --memory-tagging` option
For debugging and bug-finding workflows, support
launching processes with MTE for binaries that are
not MTE entitled.
---
lldb/include/lldb/lldb-enumerations.h | 2 ++
lldb/source/Commands/CommandObjectProcess.cpp | 3 +++
.../Commands/CommandOptionsProcessLaunch.cpp | 4 +++
.../Commands/CommandOptionsProcessLaunch.h | 2 ++
lldb/source/Commands/Options.td | 4 +++
lldb/source/Host/macosx/objcxx/Host.mm | 27 +++++++++++++++++++
lldb/test/API/macosx/mte/Makefile | 9 ++++---
lldb/test/API/macosx/mte/TestDarwinMTE.py | 16 +++++++++--
8 files changed, 62 insertions(+), 5 deletions(-)
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index fec9fdef44df9..e21880e8dcfb2 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -130,6 +130,8 @@ FLAGS_ENUM(LaunchFlags){
eLaunchFlagInheritTCCFromParent =
(1u << 12), ///< Don't make the inferior responsible for its own TCC
///< permissions but instead inherit them from its parent.
+ eLaunchFlagMemoryTagging =
+ (1u << 13), ///< Launch with memory tagging (MTE).
};
/// Thread Run Modes.
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 7d326404a5503..cce0a380479f7 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -181,6 +181,9 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
disable_aslr = target->GetDisableASLR();
}
+ if (m_options.memory_tagging == eLazyBoolYes)
+ m_options.launch_info.GetFlags().Set(eLaunchFlagMemoryTagging);
+
if (!m_class_options.GetName().empty()) {
m_options.launch_info.SetProcessPluginName("ScriptedProcess");
ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
index 21d94d68ceb91..bb20bbbe2e8f7 100644
--- a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
+++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
@@ -127,6 +127,10 @@ Status CommandOptionsProcessLaunch::SetOptionValue(
break;
}
+ case 'M':
+ memory_tagging = true;
+ break;
+
case 'c':
if (!option_arg.empty())
launch_info.SetShell(FileSpec(option_arg));
diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.h b/lldb/source/Commands/CommandOptionsProcessLaunch.h
index 7ab7fabe10503..640495422a694 100644
--- a/lldb/source/Commands/CommandOptionsProcessLaunch.h
+++ b/lldb/source/Commands/CommandOptionsProcessLaunch.h
@@ -34,6 +34,7 @@ class CommandOptionsProcessLaunch : public lldb_private::OptionGroup {
lldb_private::ExecutionContext *execution_context) override {
launch_info.Clear();
disable_aslr = lldb_private::eLazyBoolCalculate;
+ memory_tagging = false;
}
llvm::ArrayRef<lldb_private::OptionDefinition> GetDefinitions() override;
@@ -42,6 +43,7 @@ class CommandOptionsProcessLaunch : public lldb_private::OptionGroup {
lldb_private::ProcessLaunchInfo launch_info;
lldb_private::LazyBool disable_aslr;
+ bool memory_tagging;
}; // CommandOptionsProcessLaunch
} // namespace lldb_private
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index 595b3d08abec5..a3742aacb63a6 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -1173,6 +1173,10 @@ let Command = "process launch" in {
Arg<"Boolean">,
Desc<"Set whether to shell expand arguments to the process when "
"launching.">;
+ def process_launch_memory_tagging
+ : Option<"memory-tagging", "M">,
+ Desc<"Set whether to enable memory tagging (MTE) when launching the "
+ "process.">;
}
let Command = "process attach" in {
diff --git a/lldb/source/Host/macosx/objcxx/Host.mm b/lldb/source/Host/macosx/objcxx/Host.mm
index 3c1d1179963d2..28f4717bfc87c 100644
--- a/lldb/source/Host/macosx/objcxx/Host.mm
+++ b/lldb/source/Host/macosx/objcxx/Host.mm
@@ -1210,6 +1210,33 @@ static Status LaunchProcessPosixSpawn(const char *exe_path,
}
}
+ if (launch_info.GetFlags().Test(eLaunchFlagMemoryTagging)) {
+ typedef int (*posix_spawnattr_set_use_sec_transition_shims_np_t)(
+ posix_spawnattr_t *attr, uint32_t flags);
+ posix_spawnattr_set_use_sec_transition_shims_np_t
+ posix_spawnattr_set_use_sec_transition_shims_np_fn =
+ (posix_spawnattr_set_use_sec_transition_shims_np_t)dlsym(
+ RTLD_DEFAULT,
+ "posix_spawnattr_set_use_sec_transition_shims_np");
+ if (posix_spawnattr_set_use_sec_transition_shims_np_fn) {
+ error =
+ Status(posix_spawnattr_set_use_sec_transition_shims_np_fn(&attr, 0),
+ eErrorTypePOSIX);
+ if (error.Fail()) {
+ LLDB_LOG(log,
+ "error: {0}, "
+ "posix_spawnattr_set_use_sec_transition_shims_np(&attr, 0)",
+ error);
+ return error;
+ }
+ } else {
+ LLDB_LOG(log,
+ "error: posix_spawnattr_set_use_sec_transition_shims_np not "
+ "available",
+ error);
+ }
+ }
+
// Don't set the binpref if a shell was provided. After all, that's only
// going to affect what version of the shell is launched, not what fork of
// the binary is launched. We insert "arch --arch <ARCH> as part of the
diff --git a/lldb/test/API/macosx/mte/Makefile b/lldb/test/API/macosx/mte/Makefile
index cb20942805e2a..d614e0f0a3bcd 100644
--- a/lldb/test/API/macosx/mte/Makefile
+++ b/lldb/test/API/macosx/mte/Makefile
@@ -1,12 +1,15 @@
C_SOURCES := main.c
-EXE := uaf_mte
+EXE := uaf
-all: uaf_mte sign
+binary-plain: uaf
+binary-entitled: uaf sign
+
+all: binary-entitled
include Makefile.rules
-sign: mte-entitlements.plist uaf_mte
+sign: mte-entitlements.plist uaf
ifeq ($(OS),Darwin)
codesign -s - -f --entitlements $^
endif
diff --git a/lldb/test/API/macosx/mte/TestDarwinMTE.py b/lldb/test/API/macosx/mte/TestDarwinMTE.py
index ef858b1fc2710..a70b4b4aed26b 100644
--- a/lldb/test/API/macosx/mte/TestDarwinMTE.py
+++ b/lldb/test/API/macosx/mte/TestDarwinMTE.py
@@ -7,12 +7,24 @@
from lldbsuite.test import lldbutil
import lldbsuite.test.cpu_feature as cpu_feature
-exe_name = "uaf_mte" # Must match Makefile
+exe_name = "uaf" # Must match Makefile
class TestDarwinMTE(TestBase):
NO_DEBUG_INFO_TESTCASE = True
+ @skipUnlessFeature(cpu_feature.AArch64.MTE)
+ def test_process_launch_memory_tagging(self):
+ self.build(make_targets=["binary-plain"])
+ self.createTestTarget(self.getBuildArtifact(exe_name))
+
+ self.expect("process launch", substrs=["exited with status = 0"])
+
+ self.expect(
+ "process launch --memory-tagging",
+ substrs=["stopped", "stop reason = EXC_ARM_MTE_TAG_FAULT"],
+ )
+
@skipUnlessFeature(cpu_feature.AArch64.MTE)
def test_tag_fault(self):
self.build()
@@ -47,7 +59,7 @@ def test_memory_region(self):
self.expect("memory region ptr", substrs=["memory tagging: enabled"])
@skipUnlessFeature(cpu_feature.AArch64.MTE)
- def test_memory_read_with_tags(self):
+ def test_memory_read_show_tags(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "// before free", lldb.SBFileSpec("main.c"), exe_name=exe_name
>From 5e58d833e1ad1ab677b43edbc68d83b7302f5ae2 Mon Sep 17 00:00:00 2001
From: Julian Lettner <jlettner at apple.com>
Date: Fri, 10 Oct 2025 16:41:43 -0700
Subject: [PATCH 2/2] [lldb] Directly set memory_tagging in launch info flags
Directly set `memory_tagging` in launch info flags
eliminating the need for a dedicated member in
`CommandOptionsProcessLaunch`.
---
lldb/source/Commands/CommandObjectProcess.cpp | 3 ---
lldb/source/Commands/CommandOptionsProcessLaunch.cpp | 2 +-
lldb/source/Commands/CommandOptionsProcessLaunch.h | 2 --
3 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index cce0a380479f7..7d326404a5503 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -181,9 +181,6 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
disable_aslr = target->GetDisableASLR();
}
- if (m_options.memory_tagging == eLazyBoolYes)
- m_options.launch_info.GetFlags().Set(eLaunchFlagMemoryTagging);
-
if (!m_class_options.GetName().empty()) {
m_options.launch_info.SetProcessPluginName("ScriptedProcess");
ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
index bb20bbbe2e8f7..8ae20bd76f456 100644
--- a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
+++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
@@ -128,7 +128,7 @@ Status CommandOptionsProcessLaunch::SetOptionValue(
}
case 'M':
- memory_tagging = true;
+ launch_info.GetFlags().Set(eLaunchFlagMemoryTagging);
break;
case 'c':
diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.h b/lldb/source/Commands/CommandOptionsProcessLaunch.h
index 640495422a694..7ab7fabe10503 100644
--- a/lldb/source/Commands/CommandOptionsProcessLaunch.h
+++ b/lldb/source/Commands/CommandOptionsProcessLaunch.h
@@ -34,7 +34,6 @@ class CommandOptionsProcessLaunch : public lldb_private::OptionGroup {
lldb_private::ExecutionContext *execution_context) override {
launch_info.Clear();
disable_aslr = lldb_private::eLazyBoolCalculate;
- memory_tagging = false;
}
llvm::ArrayRef<lldb_private::OptionDefinition> GetDefinitions() override;
@@ -43,7 +42,6 @@ class CommandOptionsProcessLaunch : public lldb_private::OptionGroup {
lldb_private::ProcessLaunchInfo launch_info;
lldb_private::LazyBool disable_aslr;
- bool memory_tagging;
}; // CommandOptionsProcessLaunch
} // namespace lldb_private
More information about the lldb-commits
mailing list