mirror of
https://github.com/jmcorgan/fips.git
synced 2026-10-30 07:37:36 +00:00
macOS never grants Bluetooth to a root launchd daemon: CoreBluetooth answers it Unauthorized whatever the privacy settings say, so the packaged daemon could not use the CoreBluetooth backend at all. When CoreBluetooth refuses the daemon, it listens on ble-agent.sock beside the control socket (/var/run/fips, group fips), and a per-user LaunchAgent runs `fips-ble-agent --ble-agent` in the login session, lending its radio to the daemon over a small framed protocol (io_macos/agent*.rs). Each agent connection that says a valid hello is installed as the radio, replacing the previous one, so the transport is unchanged; a lost agent is a radio switched off. A connection has five seconds to say hello. The agent re-resolves the socket path on every reconnect, so one started before the daemon created its runtime directory does not settle on a fallback path. The agent connects only once its radio is up, and its hello carries the PSM CoreBluetooth published, read afresh for every connection. Before the radio is up `listen` reports only the requested fallback, so a hello sent then told the daemon PSM 133 while the listener was on another, and kept telling it so across reconnects and Bluetooth toggles. fips-ble-agent is a hard link to fips, so Activity Monitor tells the two processes apart. The agent logs to ~/Library/Logs/fips/ble-agent.log, rolled like the daemon's log, rather than to a shared path in /tmp another account could plant a file or symlink in. Install, upgrade and uninstall stop and start the agent in every GUI session, so none keeps running a replaced binary. The agent ends on the stop signal the process holds from the start, so a bootout does not wait out launchd's timeout. The daemon/agent pair is tested end to end over a real Unix socket and MockBleIo on every host: listener PSM, advertising, adverts, dialled and inbound channels both ways, refusal, a lost agent, a connection that never says hello, and an agent whose radio comes up after it starts.
34 lines
1.3 KiB
Plaintext
34 lines
1.3 KiB
Plaintext
<?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>Label</key>
|
|
<string>com.fips.ble-agent</string>
|
|
<!-- macOS never lets a root launchd daemon use Bluetooth: CoreBluetooth
|
|
answers it Unauthorized whatever the privacy settings say. This agent
|
|
runs the same binary in the user's login session, where Bluetooth
|
|
permission can be granted, and lends the radio to the daemon over
|
|
/var/run/fips/ble-agent.sock. It needs the user in the `fips` group.
|
|
fips-ble-agent is a hard link to fips, so Activity Monitor shows the
|
|
agent under its own name. -->
|
|
<key>ProgramArguments</key>
|
|
<array>
|
|
<string>/usr/local/bin/fips-ble-agent</string>
|
|
<string>--ble-agent</string>
|
|
</array>
|
|
<key>LimitLoadToSessionType</key>
|
|
<string>Aqua</string>
|
|
<key>RunAtLoad</key>
|
|
<true/>
|
|
<key>KeepAlive</key>
|
|
<true/>
|
|
<key>ThrottleInterval</key>
|
|
<integer>10</integer>
|
|
<!-- The agent logs to ~/Library/Logs/fips/ble-agent.log itself, rolled
|
|
like the daemon's log: launchd cannot expand ~ here, and a shared
|
|
path such as /tmp would let one account plant a file or symlink the
|
|
next account's agent appends to. stdout and stderr default to
|
|
/dev/null. -->
|
|
</dict>
|
|
</plist>
|