magisk-zapret2/docs/owner-schema-v9.md
loop-uh e14c46afb1 Publish the DNS hosts file from /data instead of the module tree
The DNS manager used to apply a selection by writing
system/etc/hosts into the live module directory and asking for a
reboot, so the root manager would pick it up while assembling
/system. That put the module's own tree in the path of whatever the
manager does between boots: KernelSU v3 moved that assembly into a
separate metamodule, a second hosts module publishing the same path
raced it silently, and an upgrade replaced the tree and discarded the
user's selection with it.

The published file now lives in /data/adb/zapret2-hosts and the module
bind-mounts it over /system/etc/hosts from post-fs-data.sh, which is
the same mechanism on Magisk, KernelSU and APatch. hosts-overlay.sh
owns that mount: it snapshots the untouched system file before
covering it, carries a pre-2.3.0 in-tree overlay over and takes it out
of the tree, relabels the source so netd can still read it, and yields
to another enabled hosts module instead of fighting it for the path.

Because the module publishes the mount itself, an edit now takes
effect immediately: publication is still an atomic rename, and --apply
republishes the mount rather than waiting for a reboot. A rename
leaves the live mount on the replaced inode, so the mount identity is
recorded when it is published and consulted only against a live mount
— a foreign mount is never released.

Rollback, uninstall and purge follow the file to its new home, and the
installer carries an existing selection across the upgrade that would
otherwise drop it.

Also releases the tethering runtime key and owner state v9, and lifts
the packaged lifecycle contract to 9.
2026-07-28 00:56:30 +03:00

39 lines
2 KiB
Markdown

# Owner metadata schema v9
Schema v9 adds `tethering` to the authenticated firewall generation. It is the
canonical `0`/`1` capture-topology decision copied from `runtime.ini [core]`,
and it participates in the per-family specification and firewall fingerprint.
A tethered generation anchors both owned chains a second time, into
`mangle FORWARD`, so traffic forwarded to devices on the phone's hotspot meets
the same rules the local traffic does. It publishes no additional chain and no
additional rule: a forwarded request is the same conntrack original direction
with the server port as destination, and its reply is the same reply direction
with the server port as source. Because the field is part of the record, health
verification re-verifies a live generation against the topology it published
rather than the one currently configured, and a changed setting becomes a
topology replacement instead of a health failure. Teardown answers to the
baseline it captured, so anchors published by a tethered generation are removed
even after the setting has been turned off.
Schema v8 made the compiled preset capture policy part of the authenticated
firewall generation through four fields:
- `tcp_pkt_out`
- `tcp_pkt_in`
- `udp_pkt_out`
- `udp_pkt_in`
All four are canonical positive decimal packet bounds copied from the active
TXT preset by `command-builder.sh`. They participate in the per-family
specification and firewall fingerprint. Start, health verification, teardown,
and rollback therefore use the same protocol-specific values;
none may read a competing runtime or Android setting.
The schema also binds the command SHA-256, boot identity, stable
`ZAPRET2_OUT`/`ZAPRET2_IN` namespace, exact port unions, capability flags, rule
counts, family specifications, and fingerprint. Health verification projects
that bounded receipt through the same reconciler that publishes the direct
chain rules. There are no generation-bound payload chains or firewall WAL.
Runtime code recognizes and publishes only v9; package replacement starts a
fresh generation after the mandatory reboot.