What's in a (task) name
Fixing a bug in lsmp(1)
Jonathan Levin, (@Morpheus______), http://newosxbook.com/ - 02/02/2020
About
Apple's lsmp(1)
is a wonderful little utility to list Mach ports, and is similar to what I do in procexp(j) $PID ports
. By using mach_port_space_info
and friends, the utility can dump Mach port names of any PID, and - more importantly - find their peers, by using the kobject
: a (poorly) permuted 32-bit of the kernel address of the ipc_port_t
in kernel. There is a great discussion of this in my MOXiI Volume I (chapter 11) and Volume II (chapter 10), so I'm leaving that discussion out. Btw, the man page for lsmp(1)
isn't installed by default IIRC, but it's part of the source (in
The utility, however, is also pretty hard to use - (terrible output formatting and a bug when used with no arguments, just printing out \n...) - and has a functional bug. It won't display TASK-NAME ports correctly, due to an "optimization" and Apple's user-space Mach folk not talking to the kernel space folk. It will display all TASK-NAME ports as pointing to the owning task, which is just wrong. TASK-NAME ports (the "unprivileged" task ports) are (unfortunately) rarely used, so the bug must have slipped Apple. In fact, it slipped me, till I started xn00ping around the kernel.
Fortunately, it's not that hard to fix.
The Bug
Looking at the code handling the TASK-NAME and TASKs we see:
Two comments here stand out:
- "Converting to kobjects is not always supported"
- "neat little optimization.."
The first one is correct. In fact, too correct. mach_port_kernel_object
works, BUT, it's intentionally broken. Observe the latest sources, from xnu-4903 (because AAPL is taking FOREVER WITH XNU-6153, #%#$%$#$%) for mach_port_kobject()
(which is called from the former anyway):
Don't worry about MACH_IPC_DEBUG
- that part is fine. But note DEVELOPMENT || DEBUG
- both of which are not set (for obvious reasons - have I mentioned that the V_KERNEL_UNSLIDE_OR_PERM
is terrible??). So kobject
(*addrp) will be set to 0, even though ikot_type
(*typep) will be (sometimes) non-zero, and the return value overall will be a KERN_SUCCESS
. So - taskinfo->task_kobject == kobject
will always be true (because both are 0), and the "optimization" will think that the NAME is a SELF pointer..
The fix
So, mach_port_kernel_object
won't work. BUT mach_port_space_info
still does, and will report the kobject
value in the ipc_entry
's iin_object
(assuming we have the entitlements, or SIP is disabled). So, here are the fixes:
In port_details.c:
In task_details.c: First add a task_name
field:
..and then collect the names to our own task:
..and expose our task information (because that's all static) through a getter:
You also need to add the task_name
field in common.h
, alongwith the prototype for getMyTaskDetails()
.
Download fixes:
- Source + binaries
- To compile you'll need to copy headers between the MacOS.sdk and iOS.sdk. I use symlinks so I don't have to type the mile long path to the SDKs, and it looks something like this:
morpheus@Chimera (~/Documents/src/Apple/binpack/system_cmds-805.220.1/lsmp.tproj) %ls -l ~/iOS.sdk 18:13 lrwxr-xr-x 1 root staff 99 Dec 7 2017 /Users/morpheus/iOS.sdk -> /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/ morpheus@Chimera (~/Documents/src/Apple/binpack/system_cmds-805.220.1/lsmp.tproj) %ls -l ~/MacOS.sdk 18:14 lrwxr-xr-x 1 root staff 95 Dec 7 2017 /Users/morpheus/MacOS.sdk -> /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/ morpheus@Chimera (~/Documents/src/Apple/binpack/system_cmds-805.220.1/lsmp.tproj) % cp ~/MacOS.sdk/usr/include/libproc.h ~/iOS.sdk/usr/include morpheus@Chimera (~/Documents/src/Apple/binpack/system_cmds-805.220.1/lsmp.tproj) % cp ~/MacOS.sdk/usr/include/sys/proc_info.h ~/iOS.sdk/usr/include/sys morpheus@Chimera (~/Documents/src/Apple/binpack/system_cmds-805.220.1/lsmp.tproj) % cp ~/MacOS.sdk/usr/include/sys/kern_control.h ~/iOS.sdk/usr/include/sys morpheus@Chimera (~/Documents/src/Apple/binpack/system_cmds-805.220.1/lsmp.tproj) % cp ~/MacOS.sdk/usr/include/net/route.h ~/iOS.sdk/usr/include/net/
Results
You can't fix this for MacOS when SIP is enabled since that despicable AMFI won't allow com.apple.system-task-ports
and task_for_pid-allow
. But it does work if SIP is disabled, or , on iOS, since you can easily fake sign with jtool2
:
And, running the original vs. the new, and double checking with xn00p
:
lsmp(1)
anytime because, in addition to the ports, it also talks to launchd(1)
over the bootstrap pipe to get the actual Mach service names. I got unofficial word from AAPL that they liked my trick there (an undocumented technique I also put into my launjctl(j)
), but to reward me, they made launchd(1)
only talk to platform binaries - i.e. it only works now in iOS..
It's cheaper (and better for me) if you buy direct - by emailing moxii at this site, but if you use AMZN please follow these links? Thank you! |