Sequoia, multicast and lldb - no route to host

On Sequoia it became impossible to properly debug programs using third party mDNS, multicast or broadcast, thanks to a bug? in I guess the new local network privacy feature, every send call returns no route to host. If I run the CI job, which properly packages, signs, notarizes said program, the resulting .app works fine and also requests permission to access the local network - which is impossible through lldb as it doesn't have an Info.plist, just the ***** binary itself. However this may not be the issue, see the repro method below.

A fast and easy method to reproduce is using an example from this repo: https://github.com/keepsimple1/mdns-sd/

Running the query example in a good old shell without lldb (cargo run --example query _smb._tcp) starts outputting results.

Then running the same binary through lldb (lldb -o run target/debug/examples/query _smb._tcp) would result in no route to host errors. I can't provide an output anymore as I was forced to downgrade. It works fine again on 14.6.1. I'm a bit reluctant to even try 14.7.

Also reported in feedback assistant: FB15185667

Answered by DTS Engineer in 805942022
however it'd be very unreasonable to expect debug binaries to be signed

All code should be signed. On Apple silicon, all code must be signed. Without it, the code won’t run [1].

When working with open source projects it’s common for the code to be ad-hoc signed by the linker. This is less than ideal, because you’re taking the hit for code signing without getting any of the benefits.

For day-to-day development my recommendation is that you sign your code with an Apple Development signing identity.

then why does it work without lldb or any entitlements?

On macOS, local network privacy is not enforced for command-line tools run from Terminal. That’s why, for example, you can do this:

% curl http://fluffy.local

without triggering an LNP alert.

This privilege seems to extend to child processes. For example, if I run Terminal, start vi in a window, and then run curl from within vi, it can access the local network.

In the case of the lldb tool, it runs the debugged program as a child process but something about its debugging infrastructure severs the responsibility chain, which means that the debugged program doesn’t benefit from Terminal’s largesse. That’s why it’s getting block by LNP.

Honestly, I’m not sure what the correct behaviour here. Sometimes you want the debugged program to be an independent thing, and sometimes you don’t.

Regardless, it should be possible to make this work by packaging your command-line tool in an app-like wrapper. That will allow you to sign it with the multicast entitlement and then include a provisioning profile to authorise that entitlement. See Signing a daemon with a restricted entitlement for general advice on how to do this.

Share and Enjoy

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

[1] Modulo silly things, like disabling SIP.

Have you applied for, and been granted access to, the multicast entitlement?

Share and Enjoy

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

I know about this entitlement, I've been using it for a while for multiple apps, but then why does it work without lldb or any entitlements? This is why it doesn't make much sense. If the entitlement is required, then I should be getting no route to host without lldb, which is not the case.

What I didn't try is to debug a binary with entitlements appiled, however it'd be very unreasonable to expect debug binaries to be signed which is a requirement to apply entitlements. I'm just trying to debug locally, on my own machine, these binaries are built on the same machine, never distributed, same as debugging through Xcode, which I can't because this is not an Xcode project.

For distribution it's 100% sensible, but I don't think the entitlement has anything to do with it.

however it'd be very unreasonable to expect debug binaries to be signed

All code should be signed. On Apple silicon, all code must be signed. Without it, the code won’t run [1].

When working with open source projects it’s common for the code to be ad-hoc signed by the linker. This is less than ideal, because you’re taking the hit for code signing without getting any of the benefits.

For day-to-day development my recommendation is that you sign your code with an Apple Development signing identity.

then why does it work without lldb or any entitlements?

On macOS, local network privacy is not enforced for command-line tools run from Terminal. That’s why, for example, you can do this:

% curl http://fluffy.local

without triggering an LNP alert.

This privilege seems to extend to child processes. For example, if I run Terminal, start vi in a window, and then run curl from within vi, it can access the local network.

In the case of the lldb tool, it runs the debugged program as a child process but something about its debugging infrastructure severs the responsibility chain, which means that the debugged program doesn’t benefit from Terminal’s largesse. That’s why it’s getting block by LNP.

Honestly, I’m not sure what the correct behaviour here. Sometimes you want the debugged program to be an independent thing, and sometimes you don’t.

Regardless, it should be possible to make this work by packaging your command-line tool in an app-like wrapper. That will allow you to sign it with the multicast entitlement and then include a provisioning profile to authorise that entitlement. See Signing a daemon with a restricted entitlement for general advice on how to do this.

Share and Enjoy

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

[1] Modulo silly things, like disabling SIP.

Thank you for the explanation, I forgot about the mandatory signing requirement on arm64, which is now being applied to x64_64 as well. I've yet to acquire an arm64 machine, but I guess I'd have found about this earlier if I did. It won't be hard to add a post process task to handle this case and trigger the permission dialog - I already have it for release builds, just a bit of adaptation and it's done. I'll do it as soon as I have some time.

Sequoia, multicast and lldb - no route to host
 
 
Q