-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[lldb][Darwin] Add process launch --memory-tagging
option
#162944
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-lldb Author: Julian Lettner (yln) ChangesFor debugging and bug-finding workflows, support Full diff: https://github.com/llvm/llvm-project/pull/162944.diff 6 Files Affected:
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/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
index 21d94d68ceb91..8ae20bd76f456 100644
--- a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
+++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
@@ -127,6 +127,10 @@ Status CommandOptionsProcessLaunch::SetOptionValue(
break;
}
+ case 'M':
+ launch_info.GetFlags().Set(eLaunchFlagMemoryTagging);
+ break;
+
case 'c':
if (!option_arg.empty())
launch_info.SetShell(FileSpec(option_arg));
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
|
Please make it clear in the PR description what operating systems this applies to and exactly what the entitlement actually enables. Meaning, what can a process allocate and from where and is it tagged, with and without the entitlement. On Linux:
So our equivalent for Linux would be some
|
process launch --memory-tagging
optionprocess launch --memory-tagging
option
For debugging and bug-finding workflows on Darwin, support launching processes with memory tagging for binaries that are not entitled. This will cause the process to behave as if the binary was entitled with: ``` <key>com.apple.security.hardened-process.checked-allocations</key> <true/> ``` This has no effect on hardware without MTE support. Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
Directly set `memory_tagging` in launch info flags eliminating the need for a dedicated member in `CommandOptionsProcessLaunch`.
145b6cb
to
18dca98
Compare
@DavidSpickett, thanks for your review! :)
Update PR title & description, commit messages, comments, and docs.
There is 2 separate ways to enable memory tagging in a process:
On Darwin, only processes that are started with memory tagging enabled will be able to request tagged memory.
If a process has memory tagging enabled, OS components like the system allocator will automatically start tagging memory. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Darwin experts can give the approval.
Just wondering what part of all the API calls is the key here.
if (launch_info.GetFlags().Test(eLaunchFlagMemoryTagging)) { | ||
// The following function configures the spawn attributes to launch the | ||
// process with memory tagging explicitly enabled. We look it up | ||
// dynamically since it is only available on newer OS. Does nothing on | ||
// hardware which does not support MTE. | ||
// | ||
// int posix_spawnattr_set_use_sec_transition_shims_np( | ||
// posix_spawnattr_t *attr, uint32_t flags); | ||
// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine, but I still don't see the key line below.
Generally even in code I'm not familiar with, I could at least point to a boolean or API call that does the key work. Here these names don't suggest "memory tagging" to me.
Is the 0 value what turns on memory tagging? Is "sec_transition_shims_np" something like "when spawning do so with secure mode shims enabled, which causes the process to be memory tagged even though it wouldn't enable it itself"?
I'm just amazed there are so many words here and some of them mean memory tagging but I've no idea what :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The call of this API (through the function pointer) is the line that does the work.
posix_spawnattr_set_use_sec_transition_shims_np_fn(&attr, 0)
It means "launch with memory tagging enabled".
- The naming of this function is unfortunate
- We call through function pointer that is looked up via
dlsym()
because the function is not available on older OS - The
flags=0
value allows for future, more specific semantics. - Everything else is just error handling
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment in the code along the lines of:
// This is the call that actually changes the setting.
Push this directly, no need for a PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed in: c4d7c42
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
) For debugging and bug-finding workflows on Darwin, support launching processes with memory tagging for binaries that are not entitled. This will cause the process to behave as if the binary was entitled with: ``` <key>com.apple.security.hardened-process.checked-allocations</key> <true/> ``` This has no effect on hardware without MTE support. --------- Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
For debugging and bug-finding workflows on Darwin, support
launching processes with memory tagging for binaries that are
not entitled.
This will cause the process to behave as if the binary was entitled with:
This has no effect on hardware without MTE support.