Struggling with SMJobBless in a sandboxed app

I've got an app that is sandboxed, and it requires a privileged helper. I've worked through the EBAS sample app with various updates to conform with current systems. After a lot of work, I've got to a point where I'm stumped.

The Python script SMJobBlessUtil.py returns this error, and I don't know what to do to correct it:

<path to helper tool>: tool __TEXT / __info_plist section dump malformed (2)

I've gone over the various settings numerous times. It doesn't fail for the EBAS sample, but does for my app. Looking at the binary, the __info_plist sections look identical apart from identifiers. This is what mine looks like (identifiers deleted):

<?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>CFBundleIdentifier</key>
        <string>***</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleName</key>
        <string>***</string>
        <key>CFBundleVersion</key>
        <string>1.0</string>
        <key>SMAuthorizedClients</key>
        <array>
                <string>anchor apple generic and identifier "***" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "***")</string>
        </array>
</dict>
</plist>

I must be missing something, but I've run out of ideas on where to find it. Anybody got a pointer?

That message means that SMJobBlessUtil.py was unable to parse the output of otool -s __TEXT __info_plist. If you run that command manually against the tool, what do you see?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I get what I expect, a hex representation of the plist:

Contents of (__TEXT,__info_plist) section
0000000100003ada        6d783f3c 6576206c 6f697372 31223d6e 
0000000100003aea        2022302e 6f636e65 676e6964 5455223d 
0000000100003afa        22382d46 3c0a3e3f 434f4421 45505954 
0000000100003b0a        696c7020 50207473 494c4255 2d222043 
0000000100003b1a        70412f2f 2f656c70 4454442f 494c5020 
0000000100003b2a        31205453 2f2f302e 20224e45 74746822 
0000000100003b3a        2f2f3a70 2e777777 6c707061 6f632e65 
0000000100003b4a        54442f6d 502f7344 65706f72 4c797472 
0000000100003b5a        2d747369 2e302e31 22647464 703c0a3e 
0000000100003b6a        7473696c 72657620 6e6f6973 2e31223d 
0000000100003b7a        0a3e2230 6369643c 090a3e74 79656b3c 
0000000100003b8a        4246433e 6c646e75 65644965 6669746e 
0000000100003b9a        3c726569 79656b2f 3c090a3e 69727473 
0000000100003baa        6f3e676e 732e6772 552e6c69 656c656b 
0000000100003bba        4b2e656c 6f627965 49647261 6174736e 
0000000100003bca        72656c6c 6c6f6f54 74732f3c 676e6972 
0000000100003bda        3c090a3e 3e79656b 75424643 656c646e 
0000000100003bea        6f666e49 74636944 616e6f69 65567972 
0000000100003bfa        6f697372 6b2f3c6e 0a3e7965 74733c09 
0000000100003c0a        676e6972 302e363e 74732f3c 676e6972 
0000000100003c1a        3c090a3e 3e79656b 75424643 656c646e 
0000000100003c2a        656d614e 656b2f3c 090a3e79 7274733c 
0000000100003c3a        3e676e69 2e67726f 2e6c6973 6c656b55 
0000000100003c4a        2e656c65 6279654b 6472616f 74736e49 
0000000100003c5a        656c6c61 6f6f5472 732f3c6c 6e697274 
0000000100003c6a        090a3e67 79656b3c 4246433e 6c646e75 
0000000100003c7a        72655665 6e6f6973 656b2f3c 090a3e79 
0000000100003c8a        7274733c 3e676e69 3c302e31 7274732f 
0000000100003c9a        3e676e69 6b3c090a 533e7965 7475414d 
0000000100003caa        69726f68 4364657a 6e65696c 2f3c7374 
0000000100003cba        3e79656b 613c090a 79617272 09090a3e 
0000000100003cca        7274733c 3e676e69 68636e61 6120726f 
0000000100003cda        656c7070 6e656720 63697265 646e6120 
0000000100003cea        65646920 6669746e 20726569 67726f22 
0000000100003cfa        6c69732e 656b552e 656c656c 4350582e 
0000000100003d0a        76726553 22656369 646e6120 65632820 
0000000100003d1a        66697472 74616369 656c2065 665b6661 
0000000100003d2a        646c6569 322e312e 3034382e 3331312e 
0000000100003d3a        2e353336 2e303031 2e312e36 2f205d39 
0000000100003d4a        7865202a 73747369 202f2a20 6320726f 
0000000100003d5a        69747265 61636966 31206574 6569665b 
0000000100003d6a        312e646c 382e322e 312e3034 33363331 
0000000100003d7a        30312e35 2e362e30 5d362e32 202a2f20 
0000000100003d8a        73697865 2a207374 6e61202f 65632064 
0000000100003d9a        66697472 74616369 656c2065 665b6661 
0000000100003daa        646c6569 322e312e 3034382e 3331312e 
0000000100003dba        2e353336 2e303031 2e312e36 205d3331 
0000000100003dca        65202a2f 74736978 2f2a2073 646e6120 
0000000100003dda        72656320 69666974 65746163 61656c20 
0000000100003dea        75735b66 63656a62 554f2e74 203d205d 
0000000100003dfa        45593322 36385734 2247334c 732f3c29 
0000000100003e0a        6e697274 090a3e67 72612f3c 3e796172 
0000000100003e1a        642f3c0a 3e746369 702f3c0a 7473696c 
0000000100003e2a        3e 0a 

(BTW, I'll be away tomorrow, so will get back to things again on Friday.)

I ran into a similar problem a few months back. The solution was to upgrade SMJobBlessUtil.py to python3. The issue was covered in https://developer.apple.com/forums/thread/699310

The conversion seems to work but I have only run it with my own use cases and not done any rigorous testing.

I was running the old version with Python 2. I tried the updated version with Python 3, and get the same result. Running otool -P gives me the info.plist as XML, so the system thinks it's OK.

Looking at the comments in the utility script:

# line looks like this:
#
# '0000000100000b80\t3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 '

makes me wonder if there's an endianness problem, since the first line has the bytes swapped (0000000100003ada 6d783f3c 6576206c 6f697372 31223d6e). But I'm not familiar enough with Python to know whether that is a valid objection.

If you are using an Apple Silicon Mac, have you tried running the script under Rosetta2?

Yes, it is an Apple Silicon iMac. The Python 2 installation is x86_64, so presumably running with Rosetta 2. The Python 3 installation is a fat binary, so presumably running native arm64 code. It might be easier to copy the files over to my old MBP and run it there. I'll try that next week, if I have the chance.

I run the script under rosetta on an M1 with python3 by using:

arch -x86_64 scripts/SMJobBlessUtil-python3.py check path_to_bundle

It seems to work

Same result using the script with Rosetta 2. Copying the XPC service to my older MBP and running the utility gives the same error. I will attempt to get the project up on the MBP and build there to see if I get the same issue. It's running Big Sur, so that may take a bit of manipulating to build.

OK, I got it to work on the MBP, and it works there. Significantly, the otool output starts off like this:

Contents of (__TEXT,__info_plist) section
0000000100003af6        3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 
0000000100003b06        2e 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 55 54 

And it is byte-swapped compared to the one on Apple Silicon!

So where can I go now?

Bug filed, FB10039195.

Bug filed, FB10039195.

Thanks.

FYI, the architecture that you’re running on is only indirectly relevant; the key factor is the architecture that you’re dumping. On both Intel and Apple silicon I see this result:

% otool -s __TEXT __info_plist -arch x86_64 Test94430156 | head
Test94430156:
Contents of (__TEXT,__info_plist) section
0000000100003c2a	3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 
0000000100003c3a	2e 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 55 54 
0000000100003c4a	46 2d 38 22 3f 3e 0a 3c 21 44 4f 43 54 59 50 45 
0000000100003c5a	20 70 6c 69 73 74 20 50 55 42 4c 49 43 20 22 2d 
0000000100003c6a	2f 2f 41 70 70 6c 65 2f 2f 44 54 44 20 50 4c 49 
0000000100003c7a	53 54 20 31 2e 30 2f 2f 45 4e 22 20 22 68 74 74 
0000000100003c8a	70 3a 2f 2f 77 77 77 2e 61 70 70 6c 65 2e 63 6f 
0000000100003c9a	6d 2f 44 54 44 73 2f 50 72 6f 70 65 72 74 79 4c 
% otool -s __TEXT __info_plist -arch arm64 Test94430156 | head 
Test94430156:
Contents of (__TEXT,__info_plist) section
0000000100003c30	6d783f3c 6576206c 6f697372 31223d6e 
0000000100003c40	2022302e 6f636e65 676e6964 5455223d 
0000000100003c50	22382d46 3c0a3e3f 434f4421 45505954 
0000000100003c60	696c7020 50207473 494c4255 2d222043 
0000000100003c70	70412f2f 2f656c70 4454442f 494c5020 
0000000100003c80	31205453 2f2f302e 20224e45 74746822 
0000000100003c90	2f2f3a70 2e777777 6c707061 6f632e65 
0000000100003ca0	54442f6d 502f7344 65706f72 4c797472 

That is, when I dump arm64 I see everything byte swapped. That is… well… unexpected.

One potential workaround is to add the -v flag, which causes otool to print the property list as text.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

OK, that makes sense. I was working with the debug scheme, so only arm64 was available on my iMac, and only x86_64 on the MBP.

The workaround requires some rewriting of the Python tool, which I'm not equipped to do myself (I've never taken the time to learn Python), so this will probably go on the back burner for a while, and I'll work on some other areas that are incomplete.

However, a question that will need to be answered is whether the issue will cause the privileged helper invocation to fail on arm64. In other words, does the system's checking run into the same problem? If the bug is in otool, then I suspect not, but I don't know the internals, of course.

However, a question that will need to be answered is whether the issue will cause the privileged helper invocation to fail on arm64.

This is an otool thing not an OS thing. If you open the file with Hex Edit, you’ll see that strings like CFBundleIdentifier are not byte swapped.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@eskimo

This is an otool thing not an OS thing. If you open the file with Hex Edit, you’ll see that strings like CFBundleIdentifier are not byte swapped.

What do you see with otool -V -s __TEXT __info_plist test or otool -v -s __TEXT __info_plist test on Apple Silicon vs Intel.

On Intel the correct host architecture appears to be selected. On Apple Silicon all architectures are output:

otool --version
llvm-otool(1): Apple Inc. version cctools-1000
otool(1): Apple Inc. version cctools-1000
disassmbler: LLVM version 14.0.0, (clang-1400.0.17.3.1)

otool -V -s __TEXT __info_plist test
test (architecture x86_64):
(__TEXT,__info_plist) section
<?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>

<snip>

</dict>
</plist>

test (architecture arm64):
(__TEXT,__info_plist) section
<?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>

<snip>

</dict>
</plist>

Updated SMJobBlessUtil-python3.py with workaround for otool arm64 weirdness: https://gist.github.com/mikeyh/89a1e2ecc6849ff6056b7391c5216799

Struggling with SMJobBless in a sandboxed app
 
 
Q