task_for_pid fails with os/kern failure even with system.privilege.taskport

1,101 views
Skip to first unread message

Ben Staveley-Taylor

unread,
Oct 12, 2011, 12:33:58 PM10/12/11
to darwi...@lists.apple.com
I'm trying to use the task_for_pid() mach call. I've found several list posts and other items about the security requirements for this from 10.5 onwards and I believe I'm complying, but I just can't get it to work. Can anyone spot what I'm doing wrong?

Setup:
------

- Running on OS X 10.7.1
- I created a new Cocoa application with the code snippets shown below.
- Info.plist contains:
<key>SecTaskAccess</key>
<array>
<string>allowed</string>
<string>safe</string>
</array>
- The app is codesigned using a self-signed certificate.

Behaviour:
----------

- If I sudo-run the app's executable in Terminal (i.e. Test.app/Contents/MacOS/test) directly, it works
- If I do the same without sudo, I get the output:
system.privilege.taskport acquired
com.apple.TextEdit pid is 2475
Failed; machErr=(os/kern) failure (5)

- If I run the .app bundle by double-clicking in Finder, or in Terminal using "open Test.app" or "sudo open Test.app" it also fails in the same way.

So in the failure cases I'm told that I do have system.privilege.taskport rights, but task_for_pid() then fails. What vital step am I missing?

Many thanks if you can help,

Ben Staveley-Taylor
ben.stave...@oracle.com


Code:
-----

ProcessSerialNumber psn;

// Get pid of TextEdit, assuming it is running
NSString *targetProcessBundle = @"com.apple.TextEdit";
if (FindPSNForBundleID(targetProcessBundle, &psn) == noErr) {

// I don't think this should be necessary, but done for verification
OSStatus osErr = AcquireTaskportRight();

if (osErr == noErr)
{
// Convert PSN to PID.
pid_t pid;
GetProcessPID( &psn, &pid );
NSLog(@"%@ pid is %d", targetProcessBundle, pid);

mach_port_t remoteTask = 0;
mach_error_t machErr = task_for_pid( mach_task_self(), pid, &remoteTask );

if (machErr == 0) {
NSLog(@"Success");
}
else {
const char *msg = mach_error_string(machErr);
NSLog(@"Failed; machErr=%s (%d)", msg, (int)machErr);
}
}
}


OSStatus AcquireTaskportRight() {

OSStatus stat = noErr;
AuthorizationItem taskport_item[] = {
{"system.privilege.taskport"},0,0,0
};
AuthorizationRights rights = {1, taskport_item}, *out_rights = NULL;
AuthorizationRef authRef;
AuthorizationFlags auth_flags = kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize;

stat = AuthorizationCreate (NULL, kAuthorizationEmptyEnvironment, auth_flags, &authRef);

if (stat == errAuthorizationSuccess) {
stat = AuthorizationCopyRights ( authRef, &rights, kAuthorizationEmptyEnvironment, auth_flags, &out_rights);
}

if (stat == errAuthorizationSuccess) {
NSLog(@"system.privilege.taskport acquired");
}
else {
NSLog(@"Failed to acquire system.privilege.taskport right. Error: %d", (int)stat);
}

return stat;
}

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (Darwi...@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/darwin-dev/darwin-dev-garchive-73044%40googlegroups.com

This email sent to darwin-dev-g...@googlegroups.com

Brian Bergstrand

unread,
Oct 12, 2011, 3:00:07 PM10/12/11
to Ben Staveley-Taylor, darwi...@lists.apple.com
IIRC, a self-signed cert is not acceptable. The same is true for persistent Keychain Access. You must sign with a cert that was created by a system-recognized CA.

> http://lists.apple.com/mailman/options/darwin-dev/brian%40classicalguitar.net
>
> This email sent to br...@classicalguitar.net

Jean-Daniel Dupas

unread,
Oct 13, 2011, 4:23:44 AM10/13/11
to Brian Bergstrand, darwi...@lists.apple.com, Ben Staveley-Taylor
Not true. It's perfectly possible to use a self signed cert, as long as it is properly installed.

I'm using custom lldb build that required to be signed to works, and didn't have issue with a self signed cert.

The instruction to sign lldb are available here. The interesting section is the one that start with:

«The next steps are necessary on SnowLeopard, but are probably because of a bug
how Keychain Access makes certificates.
[Note: These also apply for Lion.]»


https://llvm.org/svn/llvm-project/lldb/trunk/docs/code-signing.txt

You may have a look at what it does, and

> http://lists.apple.com/mailman/options/darwin-dev/devlists%40shadowlab.org
>
> This email sent to devl...@shadowlab.org

-- Jean-Daniel

Jean-Daniel Dupas

unread,
Oct 13, 2011, 4:28:49 AM10/13/11
to darwi...@lists.apple.com
As a side note, IIRC, the "safe" key is reserved by Apple and required the binary to be signed by an Apple certificate.

Ben Staveley-Taylor

unread,
Oct 13, 2011, 7:21:47 AM10/13/11
to darwi...@lists.apple.com, Nico Schmidt
Thanks to all for your replies. I've tried Jean-Daniel's excellent lldb steps for fully trusting a self-signed certificate, and I have today also tried creating a different code signing certificate from an external CA (not a public one, just company test one, but still set up such that the Mac has an entry for the CA as a trusted root.) In both cases this has now removed the need to interactively authenticate once per login, but I still get the same problem as I have always had: if I run from Terminal using sudo, the task_for_pid() call succeeds. If I run any other way, either from Terminal not using sudo, or interactively from the Finder, I get told that I do have the correct privilege, but then the call fails.

(Output from the code in my original post; I won't re-post it again)

system.privilege.taskport acquired
com.apple.TextEdit pid is <id>
Failed; machErr=(os/kern) failure (5)

Is there a way to get a bit more diagnostic info on what is causing the failure that might give me a clue?

Thanks,

-- Ben.

On 13 Oct 2011, at 09:23, Jean-Daniel Dupas wrote:

> Not true. It's perfectly possible to use a self signed cert, as long as it is properly installed.
>
> I'm using custom lldb build that required to be signed to works, and didn't have issue with a self signed cert.
>
> The instruction to sign lldb are available here. The interesting section is the one that start with:
>
> «The next steps are necessary on SnowLeopard, but are probably because of a bug
> how Keychain Access makes certificates.
> [Note: These also apply for Lion.]»

_______________________________________________

Jean-Daniel Dupas

unread,
Oct 13, 2011, 10:16:32 AM10/13/11
to Ben Staveley-Taylor, darwi...@lists.apple.com
I just try to create a simple tool that required task_for_pid, and following the lldb instruction (reboot required), it works nicely.

Note that to use task_for_pid(), you don't have to do anything like creating authorization. Just call it, and it works (if your executable is properly signed, and the plist is properly embedded in your tool).

I just tried the following snippet:


#include <stdlib.h>
#include <mach/mach.h>

int main(int argc, char **argv) {
  if (argc < 2) return 1;

  

  

  int pid = strtol(argv[1], NULL, 10);

  

  mach_port_t remoteTask = 0;
  kern_return_t kr = task_for_pid( mach_task_self(), pid, &remoteTask);
  if (kr != 0)
    mach_error("task_for_pid", kr);

  

  return 0;
}

----- Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.lldb</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>lldb</string>
<key>CFBundleVersion</key>
<string>2</string>
<key>SecTaskAccess</key>
<array>
<string>allowed</string>
<string>safe</string>
</array>
</dict>
</plist>

---------


clang -o test test.c  -Wl,-sectcreate,__TEXT,__info_plist,Info.plist
./test 368
task_for_pid (os/kern) failure
codesign -s lldb_codesign test
./test 368
# no error message



Le 13 oct. 2011 à 13:21, Ben Staveley-Taylor a écrit :

Thanks to all for your replies. I've tried Jean-Daniel's excellent lldb steps for fully trusting a self-signed certificate, and I have today also tried creating a different code signing certificate from an external CA (not a public one, just company test one, but still set up such that the Mac has an entry for the CA as a trusted root.) In both cases this has now removed the need to interactively authenticate once per login, but I still get the same problem as I have always had: if I run from Terminal using sudo, the task_for_pid() call succeeds. If I run any other way, either from Terminal not using sudo, or interactively from the Finder, I get told that I do have the correct privilege, but then the call fails.

(Output from the code in my original post; I won't re-post it again)

system.privilege.taskport acquired
com.apple.TextEdit pid is <id>
Failed; machErr=(os/kern) failure (5)

Is there a way to get a bit more diagnostic info on what is causing the failure that might give me a clue?

Thanks,

-- Ben.





On 13 Oct 2011, at 09:23, Jean-Daniel Dupas wrote:

Not true. It's perfectly possible to use a self signed cert, as long as it is properly installed.

I'm using custom lldb build that required to be signed to works, and didn't have issue with a self signed cert.

The instruction to sign lldb are available here.  The interesting section is the one that start with:

«The next steps are necessary on SnowLeopard, but are probably because of a bug
how Keychain Access makes certificates.
[Note: These also apply for Lion.]»


-- Jean-Daniel




Nico Weber

unread,
Oct 13, 2011, 11:04:24 AM10/13/11
to Ben Staveley-Taylor, darwi...@lists.apple.com
Hi Ben,

as far as I know, only apps signed with a certain Apple signature can
call task_for_pid() on ports other than mach_task_self() without auth
prompt, see http://lists.apple.com/archives/apple-cdsa/2008/Feb/msg00014.html

If you only need to call task_for_pid() for processes you control, you
can add code to these processes to let them send their
mach_task_self() to your controlling program over mach IPC, and then
call task_for_pid() on that from the controller. That's what we do for
the task manager in chrome.

Nico

> http://lists.apple.com/mailman/options/darwin-dev/thakis%40chromium.org
>
> This email sent to tha...@chromium.org

Ben Staveley-Taylor

unread,
Oct 13, 2011, 12:52:18 PM10/13/11
to Jean-Daniel Dupas, darwi...@lists.apple.com
Thanks very much for creating that code snippet.

Using your code, I still get an security prompt once per login session. If I reboot and run ./test, I get:
"Developer Tools Access is trying to take control of another process. Type your password to allow this."
the first time. Thereafter, the tool runs successfully with no further prompt until the next reboot. (Yes, I have run the 'security add-trust ..' steps in the lldb document on my self-signed certificate). Does your test tool run without any user interaction, every time even after a fresh boot? If so I guess I must have messed up the security add-trust steps, though I have done it a couple of times now.

Even so, this is much better than my test app behaved, which simply failed every time (without sudo). Although I realised that I didn't need to get my own Authorization right and that taskgated would do it for me, I put that code in as a diagnostic aid and with hindsight it seems to have caused the problems. Once I completely removed any attempt to Authorize in my own code, taskgated seems to allow my app through, subject to that once-per-login-session security alert. So thanks for pointing that out.

Is the security prompt unavoidable given that I'm not signing with an Apple certificate (as Nico points out in his reply, ref. http://lists.apple.com/archives/apple-cdsa/2008/Feb/msg00014.html )?

Thanks,

-- Ben.



On 13 Oct 2011, at 15:16, Jean-Daniel Dupas wrote:

I just try to create a simple tool that required task_for_pid, and following the lldb instruction (reboot required), it works nicely.

Note that to use task_for_pid(), you don't have to do anything like creating authorization. Just call it, and it works (if your executable is properly signed, and the plist is properly embedded in your tool).

I just tried the following snippet:

...

Jean-Daniel Dupas

unread,
Oct 13, 2011, 1:07:38 PM10/13/11
to Ben Staveley-Taylor, darwi...@lists.apple.com
Le 13 oct. 2011 à 18:52, Ben Staveley-Taylor a écrit :

Thanks very much for creating that code snippet.

Using your code, I still get an security prompt once per login session. If I reboot and run ./test, I get:
"Developer Tools Access is trying to take control of another process. Type your password to allow this."
the first time. Thereafter, the tool runs successfully with no further prompt until the next reboot. (Yes, I have run the 'security add-trust ..' steps in the lldb document on my self-signed certificate). Does your test tool run without any user interaction, every time even after a fresh boot? If so I guess I must have messed up the security add-trust steps, though I have done it a couple of times now.

Yes, I forgot to mention it, but I also have the "once per session prompt".

Even so, this is much better than my test app behaved, which simply failed every time (without sudo). Although I realised that I didn't need to get my own Authorization right and that taskgated would do it for me, I put that code in as a diagnostic aid and with hindsight it seems to have caused the problems. Once I completely removed any attempt to Authorize in my own code, taskgated seems to allow my app through, subject to that once-per-login-session security alert. So thanks for pointing that out.

Is the security prompt unavoidable given that I'm not signing with an Apple certificate (as Nico points out in his reply, ref. http://lists.apple.com/archives/apple-cdsa/2008/Feb/msg00014.html )?`

I can't give a definitive answer, but AFAIK, it is indeed unavoidable.

-- Jean-Daniel




Reply all
Reply to author
Forward
0 new messages