<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Chris Ball: Systemtap for fun and profit</title>
    <link>http://blog.printf.net/articles/2006/05/11/systemtap-for-fun-and-profit</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Systemtap for fun and profit</title>
      <description>&lt;p&gt;Kjartan Maraas pointed me at &lt;a href="http://https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=190128"&gt;this Fedora bug&lt;/a&gt; yesterday &amp;mdash; it points out that &lt;code&gt;/proc/$pid/maps&lt;/code&gt; has been broken in Rawhide for a month.  The patch that made &lt;code&gt;linux/fs/proc/task_mmu.c&lt;/code&gt; (which is where map requests are handled) diverge from mainline is &lt;a href="http://www.redhat.com/archives/fedora-cvs-commits/2006-April/msg00487.html"&gt;this one&lt;/a&gt;.  I can't read more about its motivation since the Bugzilla ID is security blocked.&lt;/p&gt;

&lt;p&gt;So, where to start?  &lt;code&gt;mm_for_maps()&lt;/code&gt; is a new function that does a bunch of checks on the relationship between &lt;code&gt;task&lt;/code&gt; and &lt;code&gt;current&lt;/code&gt; before deciding whether to allow the request; I threw some &lt;code&gt;printk()&lt;/code&gt;s in to find out which were failing, and found that we take the &lt;code&gt;!__ptrace_may_attach(task))&lt;/code&gt; path to the &lt;code&gt;out&lt;/code&gt; label in the code below:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if (task-&amp;gt;mm != mm)
    goto out;
if (task-&amp;gt;mm != current-&amp;gt;mm &amp;amp;&amp;amp; !__ptrace_may_attach(task))
    goto out;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From there, it got hazy.  &lt;code&gt;__ptrace_may_attach()&lt;/code&gt; returns whatever &lt;code&gt;security_ptrace()&lt;/code&gt; does.  This takes us into pluggable LSMs land &amp;mdash; any LSM that gave a &lt;code&gt;struct security_operations&lt;/code&gt; with a pointer to a ptrace function will have a shot at returning an error that would be sent back to &lt;code&gt;security_ptrace()&lt;/code&gt; to stop our request from completing. &lt;/p&gt;

&lt;p&gt;But how do I tell which LSM is complaining, or even which LSMs are &lt;em&gt;loaded&lt;/em&gt;?  After all, they're registered at runtime.  Enter &lt;a href="http://sourceware.org/systemtap/"&gt;systemtap&lt;/a&gt;, as wisely suggested to me by Bill Nottingham (whom I now surely owe beer to).  Systemtap is similar to the Solaris dtrace; it'll let you instrument and track kernel functions and system calls for a running kernel.  It was installed on my Rawhide machine by default, which is always a nice touch.&lt;/p&gt;

&lt;p&gt;So, how to see which ptrace functions were registered?  Enter my first systemtap probe:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;unity:cjb~ % cat list-ptrace.stp
probe kernel.function("*ptrace*") {
    printf("%s\n", probefunc())
}
unity:cjb~ % sudo stap list-ptrace.stp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point, our stp script is converted into C code and compiled into a kernel module, before being loaded into the running kernel.  After running a &lt;code&gt;cat /proc/&amp;lt;pid&amp;gt;/maps&lt;/code&gt; in another terminal, we see:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;__ptrace_may_attach
cap_ptrace
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;.. which suggests that &lt;code&gt;cap_ptrace&lt;/code&gt; was called by &lt;code&gt;__ptrace_may_attach&lt;/code&gt;, and &lt;em&gt;that's&lt;/em&gt; where our &lt;code&gt;__ptrace_may_attach&lt;/code&gt; might be being turned down.  To be sure that we got to &lt;code&gt;cap_ptrace&lt;/code&gt; via &lt;code&gt;__ptrace_may_attach&lt;/code&gt;, we can ask for a backtrace:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;unity:cjb~ % cat cap-backtrace.stp
probe kernel.function("cap_ptrace") {
    printf("%s -&amp;gt; %s\n", probefunc(), print_backtrace())
}
unity:cjb~ % sudo stap cap-backtrace.stp
cap_ptrace -&amp;gt;
trace for 6345 (cat)
 0xc04c2286 : cap_ptrace+0x7/0x49 []
 0xc042a600 : __ptrace_may_attach+0xac/0xae []
 0xc049350c : mm_for_maps+0x83/0xd8 []
 0xc0492892 : m_start+0x28/0x11d []
 0xc04800d9 : seq_read+0xdb/0x268 []
 0xc0446288 : audit_syscall_entry+0x104/0x12b []
 0xc047fffe : seq_read+0x0/0x268 []
 0xc04648e2 : vfs_read+0x9f/0x13e []
 0xc0464d2e : sys_read+0x3c/0x63 []
 0xc0403d07 : syscall_call+0x7/0xb []
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We're pretty sure that &lt;code&gt;cap_ptrace&lt;/code&gt; was responsible.  Hunting through its source, we see that it has a path to return &lt;code&gt;-EPERM&lt;/code&gt;, which would do it.  So, we recompile the kernel in order to have &lt;code&gt;cap_ptrace&lt;/code&gt; tell us  what return value it's going to use, right?  Well, no.  Straight back to systemtap:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;unity:cjb~ % cat return-codes.stp
probe kernel.function("*ptrace*").return {
    printf("%s -&amp;gt; ", probefunc())
    log(returnstr(1));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;.return&lt;/code&gt; after the function pattern tells systemtap to trigger when the function is returning, and &lt;code&gt;returnstr(1)&lt;/code&gt; asks for the return value as a decimal.  There's also &lt;code&gt;print_regs()&lt;/code&gt;, if you prefer to see what's in EAX directly.  Over to the other terminal to cat a &lt;code&gt;maps&lt;/code&gt; file again, and:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;unity:cjb~ % sudo stap return-codes.stp
cap_ptrace -&amp;gt; 0
__ptrace_may_attach -&amp;gt; 0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's odd.  &lt;code&gt;cap_ptrace&lt;/code&gt; is returning 0, which we can see in its code is meant to mean success, and &lt;code&gt;__ptrace_may_attach&lt;/code&gt; is receiving it back unharmed.  Cue an "ah-hah!" moment as we realise that the conditional:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if (task-&amp;gt;mm != current-&amp;gt;mm &amp;amp;&amp;amp; !__ptrace_may_attach(task))
    goto out;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;.. has the wrong polarity; each of the functions that &lt;code&gt;__ptrace_may_attach&lt;/code&gt; backs onto return zero for "success" (permission to attach), but the logic above is "if we're not trying to get the map of the current process, and &lt;code&gt;__ptrace_may_attach&lt;/code&gt; isn't non-zero, we should fail".  The exclamation mark needs to disappear.&lt;/p&gt;

&lt;p&gt;And so we're done.  My uses of systemtap weren't nearly as complex as those in the &lt;a href="http://sourceware.org/systemtap/tutorial/node9.html"&gt;tutorial&lt;/a&gt;,  but I'm happy that I saved myself the kernel compiles.  I'd somehow managed to miss any hype around systemtap; if you're another systemtap user, please consider blogging your code!&lt;/p&gt;</description>
      <pubDate>Thu, 11 May 2006 01:40:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:88c71590-68a1-42a8-9a08-37f155be34c9</guid>
      <author>Chris Ball</author>
      <link>http://blog.printf.net/articles/2006/05/11/systemtap-for-fun-and-profit</link>
      <category>kernel</category>
      <category>linux</category>
      <category>fedora</category>
      <trackback:ping>http://blog.printf.net/articles/trackback/162</trackback:ping>
    </item>
    <item>
      <title>"Systemtap for fun and profit" by teen models</title>
      <description>&lt;p&gt;is there any mass edit plugs section? want to change my blog script  - it's wp now.&lt;/p&gt;</description>
      <pubDate>Thu, 17 May 2007 09:54:48 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:66759808-4ada-4b4e-b1be-5f3c48b11498</guid>
      <link>http://blog.printf.net/articles/2006/05/11/systemtap-for-fun-and-profit#comment-222</link>
    </item>
    <item>
      <title>"Systemtap for fun and profit" by craig</title>
      <description>&lt;p&gt;bugs are everywere ;(&lt;/p&gt;</description>
      <pubDate>Thu, 03 May 2007 14:24:57 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:e9343d1f-8a83-4af9-bed8-41cc84b795dc</guid>
      <link>http://blog.printf.net/articles/2006/05/11/systemtap-for-fun-and-profit#comment-205</link>
    </item>
    <item>
      <title>"Systemtap for fun and profit" by Pozycjonowanie</title>
      <description>&lt;p&gt;I didn't understand a word, but I guess I should congrat you.&lt;/p&gt;</description>
      <pubDate>Fri, 27 Oct 2006 13:40:39 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:0f4b9196-cf9a-4233-b787-1ace3003ef14</guid>
      <link>http://blog.printf.net/articles/2006/05/11/systemtap-for-fun-and-profit#comment-142</link>
    </item>
    <item>
      <title>"Systemtap for fun and profit" by Frank Ch. Eigler</title>
      <description>&lt;p&gt;Scott: agreed, we need to clean up such inconsistencies in the subroutine library.   It has been written somewhat haphazardly, and we'll clean up these style bugs.  In fact, since just about all these routines are included in systemtap in source form (in a "tapset" directory), a more aesthetically conscious user can suggest/test/use and even submit improved names for them.&lt;/p&gt;

&lt;p&gt;It may provide additional consolatio to know that many of Chris' scripts could have been written more compactly.  For  example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;unity:cjb~ % cat cap-backtrace.stp
probe kernel.function("cap_ptrace")  {
    printf("%s", probefunc())
    print_backtrace() # more correct
}

unity:cjb~ % cat return-codes.stp
probe kernel.function("*ptrace*").return {
    printf("%s -&amp;gt; %d", probefunc(), retval())
}
&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Fri, 12 May 2006 15:42:21 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:8892fa09-6ecc-47dc-afa8-48836751ae29</guid>
      <link>http://blog.printf.net/articles/2006/05/11/systemtap-for-fun-and-profit#comment-56</link>
    </item>
    <item>
      <title>"Systemtap for fun and profit" by diegoe</title>
      <description>&lt;p&gt;I didn't understand a word, but I guess I should congrat you.&lt;/p&gt;</description>
      <pubDate>Fri, 12 May 2006 12:22:17 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:5ab3efdb-6e84-41ee-89be-7bbde53c0214</guid>
      <link>http://blog.printf.net/articles/2006/05/11/systemtap-for-fun-and-profit#comment-55</link>
    </item>
    <item>
      <title>"Systemtap for fun and profit" by Chris</title>
      <description>&lt;p&gt;Hi, Bram.  It's a good point, and the answer is that &lt;code&gt;__ptrace_may_attach&lt;/code&gt; is used on more occasions than this one, with the semantics of zero=success.  I think there should be a change, but I'm not sure where it should be; perhaps the LSM modules should be changed instead.&lt;/p&gt;</description>
      <pubDate>Thu, 11 May 2006 15:36:51 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:01b8d5c0-e1c9-4a09-bdd8-be393f472e15</guid>
      <link>http://blog.printf.net/articles/2006/05/11/systemtap-for-fun-and-profit#comment-54</link>
    </item>
    <item>
      <title>"Systemtap for fun and profit" by Bram!</title>
      <description>&lt;p&gt;I'm not a proffesional hacker and unfamiliar with the linux code but by the looks of "something&lt;em&gt;may&lt;/em&gt;verb" you expect it to say true if you may do so, right? &lt;/p&gt;

&lt;p&gt;Names like cap&lt;em&gt;ptrace or security&lt;/em&gt;ptrace don't really tell me what they return so it's okay to lookup their contract before interpreting their return value, but why didn't you fix &lt;em&gt;_ptrace&lt;/em&gt;may_attach by changing it's name or by actually returning true in this case?&lt;/p&gt;</description>
      <pubDate>Thu, 11 May 2006 09:52:51 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:d9d247c0-f30c-4e10-b11f-b23ba9a67d11</guid>
      <link>http://blog.printf.net/articles/2006/05/11/systemtap-for-fun-and-profit#comment-53</link>
    </item>
    <item>
      <title>"Systemtap for fun and profit" by Scott Tsai</title>
      <description>&lt;p&gt;I'm actually disappointed that so early in the SystemTap programming language's life we already have inconsistencies in naming like "print_backtrace" and "returnstr" (the use of underscores).&lt;/p&gt;

&lt;p&gt;Reminds me of PHP instead of Python.&lt;/p&gt;</description>
      <pubDate>Thu, 11 May 2006 03:30:53 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:651f0641-b5d5-4f17-9dee-c7cb139eef80</guid>
      <link>http://blog.printf.net/articles/2006/05/11/systemtap-for-fun-and-profit#comment-52</link>
    </item>
  </channel>
</rss>
