{"id":246,"date":"2011-11-27T17:07:16","date_gmt":"2011-11-27T21:07:16","guid":{"rendered":"http:\/\/adamrosenfield.com\/blog\/?p=246"},"modified":"2011-11-28T00:11:02","modified_gmt":"2011-11-28T04:11:02","slug":"debugging-a-strange-itunes-permissions-problem-with-dtrace","status":"publish","type":"post","link":"http:\/\/adamrosenfield.com\/blog\/2011\/11\/27\/debugging-a-strange-itunes-permissions-problem-with-dtrace\/","title":{"rendered":"Debugging a strange iTunes permissions problem with DTrace"},"content":{"rendered":"<p>The other day, I noticed that one of my media files wouldn&#8217;t play in iTunes because it decided that my computer wasn&#8217;t authorized to play it.  I could not authorize my computer to play that song, however, because the iTunes account name associated with that song no longer existed\u2014I had changed the email address of my account in between the time that that was purchased and when I transferred it to my current computer (it was purchased prior to iTunes&#8217; releasing all of their music DRM-free; I strongly oppose <a href=\"http:\/\/adamrosenfield.com\/blog\/2008\/09\/12\/digital-restrictions-management\/\">DRM<\/a>).<\/p>\n<p>When I attempted to re-download the track from the iTunes Store, it gave me this error message which would ordinarily be pretty helpful:<\/p>\n<hr>\n<p><strong>iTunes couldn&#8217;t download your purchase.<\/strong><\/p>\n<p>You don&#8217;t have write access for your iTunes Media folder or a folder within it. Change permissions (in the Finder) and then choose Store &gt; Check for Available Downloads<\/p>\n<hr>\n<p>Alas, that was not the problem.  Nothing I can think of would have messed up the permissions, and <a href=\"http:\/\/linux.die.net\/man\/1\/find\">find(1)<\/a> confirms that all of the subdirectories there are owned by me and are readable, writable, and executable:<\/p>\n<pre>\r\n$ cd ~\/Music\/iTunes\r\n$ find . \\! -user $USER\r\n$ find . -type d \\! -perm -0700\r\n$ # No output from the above commands\r\n<\/pre>\n<p>What&#8217;s going on here?<\/p>\n<p>Time to dig deeper with <a href=\"http:\/\/www.mactech.com\/articles\/mactech\/Vol.23\/23.11\/ExploringLeopardwithDTrace\/index.html\">DTrace<\/a>.  DTrace is a powerful debugging tool, useful for answering such questions as &#8220;What system calls is this process calling?&#8221;, &#8220;Why is the performance of my server so horrendous?&#8221; and many more.  It&#8217;s like <a href=\"http:\/\/blogs.oracle.com\/ksplice\/entry\/strace_the_sysadmin_s_microscope\">strace<\/a> on crack.<\/p>\n<p>But with great power comes great complexity.  In order to use DTrace, you need write a short program in the tool&#8217;s D programming language (not to be confused with <a href=\"http:\/\/www.d-programming-language.org\/\">that other D programming language<\/a>).  The program can be written on the command line or in a separate text file, but it&#8217;s still non-trivial.  Some really useful examples can be found <a href=\"http:\/\/prefetch.net\/articles\/solaris.dtracetopten.html\">here<\/a>, in addition to the various examples in the documentation.<\/p>\n<p>The error message from iTunes strongly smells like a call to <a href=\"http:\/\/linux.die.net\/man\/2\/open\"><code>open(2)<\/code><\/a> is failing with <code>EACCES<\/code> when iTunes tries to create the re-downloaded media file.  Let&#8217;s see if that&#8217;s the case:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">syscall::open*:entry\r\n\/pid == $target\/\r\n{\r\n  printf(&quot;%s %s 0x%x 0x%x&quot;, execname, copyinstr(arg0), arg1, arg2);\r\n}\r\n\r\nsyscall::open*:return\r\n\/pid == $target\/\r\n{\r\n  printf(&quot;errno=%d&quot;, errno);\r\n}\r\n<\/pre>\n<p>Get the PID of iTunes, start tracing it with <code>sudo dtrace -s open.d -p $PID<\/code>, and try to download the file again.  Unfortunately the output is not expected\u2014errors like this get printed many times:<\/p>\n<pre>dtrace: error on enabled probe ID 6 (ID 120: syscall::open:return):\r\n invalid user access in action #2 at DIF offset 24<\/pre>\n<p>After a little more digging, I discovered that <a href=\"http:\/\/www.steike.com\/code\/debugging-itunes-with-gdb\/\">iTunes does not like getting debugged<\/a>, which probably means it also doesn&#8217;t like getting itself traced\u2014it just makes the debugger segfault instead.  Fortunately, it&#8217;s not too hard to get around this: just turn <code>ptrace<\/code> into a no-op in iTunes when it tries to make itself undebuggable with <code>ptrace(PT_DENY_ATTACH)<\/code>.  <a href=\"http:\/\/www.blackhat.com\/presentations\/bh-jp-08\/bh-jp-08-Miller\/BlackHat-Japan-08-Miller-Hacking-OSX.pdf\">Charlie Miller<\/a> provides a nice gdb script for doing so:<\/p>\n<pre>break ptrace\r\ncondition 1 *((unsigned int *) ($esp + 4)) == 0x1f\r\ncommands 1\r\nreturn\r\nc\r\nend<\/pre>\n<p>Ok, so we&#8217;re past that hurdle.  Quit iTunes, restart it under gdb with this anti-anti-debugging technique, fire up DTrace again, and try to re-download the file:<\/p>\n<pre style=\"overflow: scroll;\">CPU     ID                    FUNCTION:NAME\r\n  0    119                       open:entry iTunes \/.vol\/234881026\/1516872\/SC Info.sidb 0xa00 0x1b6\r\n  0    120                      open:return errno=13<\/pre>\n<p>Hmm.  Error 13 is indeed <code>EACCES<\/code>, but what is this strange file under <code>\/.vol<\/code>?  Why, it&#8217;s the <a href=\"http:\/\/compute.cnr.berkeley.edu\/cgi-bin\/man-cgi?volfs+7\">Volume Management file system<\/a>, used by the <a href=\"http:\/\/developer.apple.com\/library\/mac\/#documentation\/Carbon\/Reference\/File_Manager\/Reference\/reference.html\">Carbon File Manager<\/a>.  Using <code>ls -al \/.vol<\/code>, it appears that that directory is completely empty, yet somehow other file accesses within there succeeded, as indicated in the DTrace output.<\/p>\n<p>I&#8217;m not sure if there&#8217;s an easy to figure out which directory in the real file system that <code>\/.vol\/234881026\/1516872<\/code> refers to, but a quick search for a file named &#8220;SC Info&#8221; yields two likely candidates:<\/p>\n<pre>$ locate -i \"SC Info\"\r\n\/Users\/Shared\/SC Info\r\n\/Users\/Shared\/SC Info~orig<\/pre>\n<p>Let&#8217;s see what those directories look like:<\/p>\n<pre>$ ls -la \/Users\/Shared\/SC\\ Info*\r\n\/Users\/Shared\/SC Info:\r\ntotal 0\r\ndrwxr-xr-x   2 root  wheel   68 Jul  2  2010 .\r\ndrwxrwxrwt  10 root  wheel  340 Oct 30 22:54 ..\r\n\r\n\/Users\/Shared\/SC Info~orig:\r\ntotal 0\r\ndrwxrwxrwx   2 adam  wheel   68 Jul  2  2010 .\r\ndrwxrwxrwt  10 root  wheel  340 Oct 30 22:54 ..<\/pre>\n<p>Aha!  So iTunes is trying to create a file named <code>SC Info.sidb<\/code> in <code>\/Users\/Shared\/SC Info<\/code>, but it&#8217;s failing because I don&#8217;t have write access to that directory.<\/p>\n<p>The solution:<\/p>\n<pre>sudo chmod a+w \/Users\/Shared\/SC\\ Info<\/pre>\n<p>Bingo!  The song now downloads successfully.<\/p>\n<p>Of course, you probably could have skipped all this, googled the error message, and found <a href=\"http:\/\/support.apple.com\/kb\/ts1277\">this knowledge base article<\/a> explaining how to fix it without too much trouble, but that&#8217;s boring.  Using DTrace to debug the problem is much more fun and exciting!<\/p>\n<p>Do you have any great success (or failure) stories involving DTrace?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The other day, I noticed that one of my media files wouldn&#8217;t play in iTunes because it decided that my computer wasn&#8217;t authorized to play it. I could not authorize my computer to play that song, however, because the iTunes account name associated with that song no longer existed\u2014I had changed the email address of [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-246","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/posts\/246","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/comments?post=246"}],"version-history":[{"count":13,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/posts\/246\/revisions"}],"predecessor-version":[{"id":260,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/posts\/246\/revisions\/260"}],"wp:attachment":[{"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/media?parent=246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/categories?post=246"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/tags?post=246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}