Is there a workaround for: “dtrace cannot control

2019-01-21 18:44发布

It looks like in OS X 10.11 El Capitan, dtruss and dtrace can no longer do what they're meant to do. This is the error I get when I try to run sudo dtruss curl ...:

dtrace: failed to execute curl: dtrace cannot control executables signed with restricted entitlements

I've come across people noticing this problem but so far no solutions.

Is there a way to fix this or work around this?

6条回答
冷血范
2楼-- · 2019-01-21 18:52

I would post this as a comment but I'm not allowed.

Disabling SIP is not necessary. Just copy the binary to an alternate location and it works just fine:

$ sudo dtruss ping google.com
dtrace: system integrity protection is on, some features will not be available

dtrace: failed to execute ping: dtrace cannot control executables signed with restricted entitlements
$ sudo cp $(which ping) .
$ sudo dtruss ./ping google.com
dtrace: system integrity protection is on, some features will not be available

SYSCALL(args)        = return
PING google.com (172.217.10.78): 56 data bytes
^C
$ csrutil status
System Integrity Protection status: enabled.

For binaries that can still function normally after being copied, this is the best option as it captures the entire lifetime of the process and doesn't require disabling any protections.

查看更多
\"骚年 ilove
3楼-- · 2019-01-21 18:56

For those who want to dtrace system shipped binary after csrutil disable, copyit to a directory that is not "restricted", for example, /tmp

CC@~ $ csrutil status
System Integrity Protection status: disabled.
CC@~ $ cp /bin/echo /tmp
CC@~ $ sudo dtruss /tmp/echo

SYSCALL(args)        = return
thread_selfid(0x0, 0x0, 0x0)         = 46811 0
csops(0x0, 0x0, 0x7FFF51B6CA20)      = 0 0
issetugid(0x0, 0x0, 0x7FFF51B6CA20)      = 0 0
shared_region_check_np(0x7FFF51B6A918, 0x0, 0x7FFF51B6CA20)      = 0 0
stat64("/usr/lib/dtrace/libdtrace_dyld.dylib\0", 0x7FFF51B6BEA8, 0x7FFF51B6CA20      = 0 0

See @J.J's comment: https://apple.stackexchange.com/questions/208762/now-that-el-capitan-is-rootless-is-there-any-way-to-get-dtrace-working/224731#224731

查看更多
forever°为你锁心
4楼-- · 2019-01-21 19:00

Looks like completely disabling SIP still blocks dtruss for restricted processes:

$ /usr/bin/csrutil status
System Integrity Protection status: disabled.
$ sudo dtruss /bin/echo "blah"
dtrace: failed to execute /bin/echo: dtrace cannot control executables signed with restricted entitlements
$ sw_vers 
ProductName:    Mac OS X
ProductVersion: 10.11.2
BuildVersion:   15C50
查看更多
我命由我不由天
5楼-- · 2019-01-21 19:02

As Andrew notices it's because of System Integrity Protection, also known as "rootless".

You can disable it completely or partially (enable just dtrace with some limitations).

Completely disable SIP

Although not recommended by Apple, you can entirely disable System Integrity Protection on you Mac. Here's how:

  1. Boot your Mac into Recovery Mode: reboot it and hold cmd+R until a progress bar appears.
  2. Go to Utilities menu. Choose Terminal there.
  3. Enter this command to disable System Integrity Protection:

$ csrutil disable

It will ask you to reboot — do so and you're free from SIP!

Partially disable SIP

Fortunately, SIP is not monolithic: it's built from many different modules we can disable/enable separately.

Repeat steps 1 and 2 from «Completely disable SIP» section above. Now in Terminal enter these commands:

$ csrutil clear # restore the default configuration first
$ csrutil enable --without dtrace # disable dtrace restrictions *only*

Reboot and enjoy your OS again.

Dtrace starts to work but you're still unable to attach dtrace to restricted processes

Instructions source: http://internals.exposed/blog/dtrace-vs-sip.html

查看更多
做个烂人
6楼-- · 2019-01-21 19:03

Once you csrutil enable --without dtrace, there is an alternative to copying the binary: run the binary in one Terminal window and trace the Terminal process itself in another Terminal window.

In the first terminal window, find its PID:

$ echo $$
1154

In the second terminal window, begin the trace:

$ sudo dtruss -p 1154 -f

Back, in the first terminal window, run the process you want to trace:

$ ls

At this point, you should see the trace in the second window. Ignore the entries for the PID you are tracing (e.g., 1154), and the rest are for the process (and its descendants) you are interested in.

1154/0x1499:  sigprocmask(0x3, 0x7FFF53E5C608, 0x0)      = 0x0 0
1154/0x1499:  sigprocmask(0x1, 0x7FFF53E5C614, 0x7FFF53E5C610)       = 0x0 0
3100/0xa9f3:  getpid(0x7FFF82A35344, 0x7FFF82A35334, 0x2000)         = 3100 0
3100/0xa9f3:  sigprocmask(0x3, 0x10BE32EF8, 0x0)         = 0x0 0
查看更多
放我归山
7楼-- · 2019-01-21 19:16

See my answer on related question "How can get dtrace to run the traced command with non-root priviledges?" [sic].

DTrace can snoop processes that are already running. So, start a background process which waits 1sec for DTrace to start up (sorry for race condition), and snoop the PID of that process.

sudo true && \
(sleep 1; ps) & \
sudo dtrace -n 'syscall:::entry /pid == $1/ {@[probefunc] = count();}' $! \
&& kill $!

Full explanation in linked answer.

查看更多
登录 后发表回答