Implement bounded registry APIs and opt-in platform configuration

This commit is contained in:
lucannez64 committed 2026-10-17 23:32:01 +02:00
1 parent 3ed48bd2ac
commit d87ad2ce45
9 files changed
+1284 -19

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
# Explicit platform identity overrides
By default, Darling keeps the existing host-derived UUID and `DARLING-` serial.
No override file is generated by installation or launch. This tool imports
values supplied by the user; it does not generate Apple serials or replace OS,
CPU, GPU, or security metadata.
Preview an OpenCore `config.plist`, a flat GenSMBIOS JSON file, or an existing
`darling-smbios.conf` without changing the selected prefix:
```sh
python3 tools/configure-darling-platform.py --prefix /absolute/prefix --import /path/to/config.plist
```
After reviewing the preview, shut down that prefix and explicitly save:
```sh
DPREFIX=/absolute/prefix python3 build/runtime/tools/stop-darling-runtime.py
python3 tools/configure-darling-platform.py --prefix /absolute/prefix --import /path/to/config.plist --write
```
The default prefix selection is `--prefix`, then `DPREFIX`, then saved
`build/config.json`, then `~/.darling`. Writing refuses a live prefix. The
configuration is activated when that prefix's iokitd starts again; it is an
immutable startup snapshot. An absent or invalid configuration preserves the
existing defaults. Invalid daemon-side configuration is reported once.
The file is `<prefix>/private/etc/darling-platform.plist`. It uses this schema:
```json
{
"schema": 1,
"properties": {
"IOPlatformSerialNumber": "USER-SUPPLIED",
"model": "UserSuppliedModel"
}
}
```
Supported properties:
| Property | Configuration value | IOKit value |
|---|---|---|
| `IOPlatformSerialNumber` | Printable ASCII string, 1–64 characters | NSString |
| `IOPlatformUUID` | Nonzero UUID; normalized to uppercase | NSString |
| `manufacturer`, `model`, `product-name`, `board-id` | Printable ASCII string, 1–128 characters | NUL-terminated NSData |
| `mlb-serial-number` | Printable ASCII string, 1–64 characters | NUL-terminated NSData |
| `ROM` | Exactly 6 bytes; JSON accepts hexadecimal text | NSData |
| `system-id` | Exactly 16 bytes; JSON accepts hexadecimal text | NSData |
Supplying a model also supplies the matching product name unless one is
explicitly provided. Supplying a UUID derives its EFI little-endian `system-id`;
a conflicting explicit system ID is rejected. No other missing fields are
invented. These properties belong to the existing platform service; the tool
does not manufacture a firmware/NVRAM registry hierarchy.
For OpenCore, the importer reads `PlatformInfo/Generic` (or a standalone Generic
dictionary): `SystemProductName`, `SystemSerialNumber`, `SystemUUID`, `MLB`,
and `ROM`. It ignores unrelated boot and security settings. GenSMBIOS aliases
include `Type`, `Serial`, `Board Serial`, and `SmUUID`. Legacy `SMBIOS_*` identity
keys are accepted from `.conf`; parsing never executes shell expressions.
Existing configured fields survive a partial import. A new explicit UUID
replaces its previously derived system ID. `--set KEY=VALUE` can update an
individual field. Unknown schema versions, unsupported properties, malformed
values, and duplicate JSON fields are rejected.
Writes are atomic with mode 0600. Repeating the same write changes nothing. The
first previous configuration is kept as
`darling-platform.plist.before-platform-change`, also with mode 0600. Importing
an older `.conf` never edits that source. Symlinks escaping the prefix are
rejected. To restore the original defaults, remove the override file while the
prefix is stopped, then restart it.
+2
View File
@@ -25,6 +25,8 @@ from main after PRs #43 and #42. It does not claim to resolve account bans.
the address of its input pointer. Hardware debug-state support remains
unsupported.
The deferred compatibility groups are implemented in the [following stack layer](pr41-deferred-implementation.md).
## Work left outside this adaptation
The original PR's rendered source changes were inspected against its merge base,
@@ -0,0 +1,98 @@
# PR #41 deferred compatibility work
This follow-up is stacked on the compatibility extraction in PR #44. It
implements the four groups deferred in that review, with explicit configuration
and observable errors rather than automatic identity changes.
## Shell spawning
Diagnostics are quiet by default; `DARLING_SHELLSPAWN_DEBUG=1` enables the
existing diagnostic output. The environment and arguments are no longer dumped
on normal launches.
Stdio sources are duplicated before any standard descriptor is replaced, so
aliases involving descriptors 0–2 are safe. Stream cleanup closes each owned
descriptor once instead of repeatedly closing stream 0. Both fork branches drop
unneeded descriptors, and error paths clean up the exec-status pipe. The
control socket is kept out of the stdio slots. Terminal signal forwarding uses
the remapped stdin. Unrelated descriptors and the configured shell selection
are preserved.
## CPU frequency
`hw.cpufrequency` is an unsigned 64-bit frequency in Hz, matching XNU's named
API. Linux cpufreq kHz values are checked for invalid input and overflow before
conversion. The exported host sysfs location is tried as well as `/sys`; an
available native CPUID base-frequency leaf is a fallback. No fixed CPU speed is
invented when no source exists.
Numeric `HW_CPU_FREQ` retains the legacy 32-bit representation through a
separate compatibility entry, matching XNU's distinction between the modern
named API and the numeric compatibility API. Consumers needing frequencies
above the 32-bit range should use the named 64-bit API.
## IOKit registry
- Inline and out-of-line path lookup validate termination, path shape, plane
membership, and length. Paths resolve registered entries with case-sensitive
names; no synthetic firmware nodes are inserted.
- Path output uses inline storage when possible and a bounded sender buffer for
long physical-copy replies. Incoming OOL mappings are released on success and
error paths. The daemon's main queue serializes request processing and reply
copying, so reply storage remains live through the send.
- Plane membership follows registered ancestry. Deleting a parent or child
removes both graph links. Plane-name keys own their strings, and cyclic
registration is refused.
- Raw property access handles strings, data, integer numbers at their reported
widths, and XNU's `Yes`/`No` representation of booleans. It bounds writes by
both the requested count and the fixed MIG array. Missing and unsupported
values return errors; small buffers return IPC errors without writes.
## Platform configuration
[Platform identity configuration](../PLATFORM_IDENTITY.md) documents the schema,
OpenCore/GenSMBIOS/legacy imports, startup snapshot, defaults, and rollback.
Neither installation nor launch generates an override file. Existing host-based
identifiers remain stable unless the user explicitly supplies replacements.
## Validation
Portable regression checks:
```sh
python3 -m unittest discover -s tests
python3 scripts/prepare.py --check-only
python3 scripts/validate.py
python3 tools/riot-launcher-offline-check.py
python3 tools/riot-input-offline-check.py
python3 tools/riot-runtime-cleanup-offline-check.py
```
The unit tests compile the actual patched fd helper and frequency code. They
exercise fd aliases, unrelated descriptors, repeated failed remaps, conversion
overflow, buffer widths, schema validation, imports, idempotency, backups,
per-prefix isolation, malformed input, and preservation of existing identities.
With the source patches prepared, build an isolated iokitd candidate and probe:
```sh
python3 build/runtime/tools/build-riot-registry-compatibility-check.py
darling shell /Volumes/SystemRoot/ABSOLUTE_PROJECT_PATH/build/riot-registry-compatibility-check
```
The probe uses the actual daemon objects and MIG handlers, and creates its own
Mach ports. It does not register a daemon or replace the running iokitd. It
checks traversal, deletion, cycles, malformed OOL input, 1,000 direct OOL
lookups, 100 real IPC path round trips, property widths/bounds, and binary
serialization round trips. It also checks daemon-side identity validation.
For a rebuilt kernel containing the frequency patch:
```sh
python3 build/runtime/tools/build-riot-cpu-frequency-check.py
darling shell /Volumes/SystemRoot/ABSOLUTE_PROJECT_PATH/build/riot-cpu-frequency-check
```
Local validation also ran the fd helper inside Darling and used an isolated
kernel override for the frequency probe. The configured production runtime was
not replaced, no real identity was changed, and no match capture is required.