Skip to content

Firmware upgrade (sysupgrade / owut / ASU) deletes the controller ACL file; device then fails every probe with "access denied" #45

Open

Description

@flubba

What happens

After upgrading an adopted (Managed) AP with Attended Sysupgrade, oonfeeWRT can no longer observe it:

daemon: probe <device>: ubus system.board: access denied after re-login (the ACL does not grant this method)

The login of the oonfeewrt rpcd user still works, but the rpcd ACL group oonfeewrt no longer grants anything.
The device then shows as unreachable in the UI.

Cause

Adoption writes /usr/share/rpcd/acl.d/oonfeewrt.json. That path is not a package conffile and is not listed in
/etc/sysupgrade.conf, so sysupgrade (and therefore owut and Attended Sysupgrade, which both use it with
"keep settings") does not carry it over. Packages and /etc/config/* survive, so the device looks fine otherwise:
/etc/config/rpcd still contains the oonfeewrt login with list read/write 'oonfeewrt', only the ACL file is gone.
Verified on three APs (OpenWrt 25.12.5 -> 25.12.6 and a SNAPSHOT build); the sysupgrade backup archive
(sysupgrade -b) contains only the files from /etc/sysupgrade.conf, and oonfeewrt.json was not among them.

Workaround

Copy deploy/acl/oonfeewrt.json back to /usr/share/rpcd/acl.d/, restart rpcd, and add the path to
/etc/sysupgrade.conf so the next upgrade keeps it. The existing "Review or refresh controller access payload"
action also works, but needs the device admin password.

Suggestion

Whenever the ACL file is installed (adopt, ACL refresh), also append its path to /etc/sysupgrade.conf if it is not
already there (idempotent, one line). That is the standard OpenWrt mechanism for keeping a non-conffile across
upgrades, it is covered by the same permission the ACL write already needs, and it keeps the rest of the
"one rpcd ACL file" footprint unchanged. The ACL-removal path should drop the line again.

A smaller alternative would be a hint in the firmware guide (docs/guide/firmware.md) that the ACL has to be
re-applied after a firmware upgrade, plus a clearer message in the device view than a generic probe failure.

Environment

oonfeeWRT v0.1.8 (official image), Tenda BE12 Pro (SNAPSHOT, owut upgrade), TP-Link Archer AX23 and D-Link
DAP-X1860 (25.12.6, Attended Sysupgrade).

Disclosure

The analysis and this text were prepared with Claude (AI assistant); operation, finding the problem, the fix on the
devices and the review were done by me.

Activity

  1. self-assigned this
    on Oct 19, 2026
  2. aiden0rchad commented on Oct 20, 2026

    @aiden0rchad
    Owner

    Thanks for the report. I've opened #46 with a fix and regression tests.

    • Adoption and ACL refresh register the ACL in /etc/sysupgrade.conf without duplicates, preserving other entries and file permissions.
    • Unadoption and rollback remove the ACL's backup entry.
    • The existing refresh action can recover an already missing ACL using the saved SSH host key, then verify a fresh controller login, device MAC, and capabilities. Managed and monitor-only scopes are preserved.

    For an affected AP, test a build from the PR and use Devices → device details → Review or refresh controller access payload with the device administrator credential. It should restore access without re-adoption. You can then check the backup list without flashing:

    sysupgrade -l | grep -Fx '/usr/share/rpcd/acl.d/oonfeewrt.json'

    The isolated Go suite, focused race checks, go vet, 563 UI tests, production build, and secret scan pass. Recovery refuses an unavailable or changed saved SSH identity; the firmware guide includes manual recovery guidance.

    GitHub CI currently stops at dependency audits in the unchanged UI/docs lockfiles (source-map-js and vite). Dependency updates are outside this ACL patch.

    Real firmware-upgrade validation is still pending. Please confirm recovery on your APs and retention after your next planned upgrade that keeps settings. I'll keep this issue open until you confirm.

  3. aiden0rchad commented on Oct 20, 2026

    @aiden0rchad
    Owner

    #46 is now merged into main. All PR CI checks passed; #47 cleared the dependency-audit blockers.

    Please test a build from current main. For an affected AP, use Devices → device details → Review or refresh controller access payload with the device administrator credential. Recovery requires a matching saved SSH host key and should restore access without re-adoption. Then check that the ACL is in the backup list:

    sysupgrade -l | grep -Fx '/usr/share/rpcd/acl.d/oonfeewrt.json'

    Real firmware-upgrade validation is still pending. Please confirm recovery on your APs and retention after your next planned upgrade that keeps settings. I'll keep this issue open until you confirm.

  4. aiden0rchad commented on Oct 25, 2026

    @aiden0rchad
    Owner

    @flubba let me know if that works for you, id be glad to solve this issue if you have more or its not working correctly

  5. flubba commented on Oct 25, 2026

    @flubba
    Author

    Thanks for the quick fix! I tested a build of current main (4af920f, built from deploy/Dockerfile) against my three managed APs. No firmware upgrade was involved; I simulated the post-upgrade state by hand.

    AP 1 (OpenWrt SNAPSHOT r33311, simulated post-upgrade state): I removed /usr/share/rpcd/acl.d/oonfeewrt.json and its /etc/sysupgrade.conf entry, then reloaded rpcd. The controller then logged access denied after re-login (the ACL does not grant this method). Review or refresh controller access payload with the root password restored access without re-adoption:

    • The ACL was restored byte-identical to the original, with mode 0644.
    • /etc/sysupgrade.conf contains the entry exactly once, and the existing /usr/share/rpcd/acl.d/hass.json entry is preserved.
    • sysupgrade -l | grep -Fx … matches. An actual sysupgrade -b archive contains usr/share/rpcd/acl.d/oonfeewrt.json.
    • The controller logged "device reachable again", with no further access-denied errors.

    AP 2 (r33311, ACL present, backup entry missing): Refresh added the entry once and preserved the other entries. The ACL was unchanged.

    AP 3 (Tenda, SNAPSHOT r37482): refresh refused with a false host-key mismatch:

    the device's SSH host key changed: expected SHA256:sDDYYm3UF…(RSA), got SHA256:fPsQAQLym…
    

    The RSA host key did not change. The owut upgrade to r37482 on 2026-10-19 added /etc/dropbear/dropbear_ecdsa_host_key, so dropbear now offers RSA, ECDSA and Ed25519. DialSSH pins only the fingerprint and leaves ssh.ClientConfig.HostKeyAlgorithms unset. Go's client prefers ECDSA, receives the new key, and compares it against the stored RSA fingerprint. ssh-keyscan confirms that RSA still matches the pinned value and that ECDSA is fPsQAQLym….

    This hits exactly the recovery scenario from this issue: a firmware upgrade that keeps settings can still add a host-key type, and recovery is then refused. A possible fix: store the key type together with the fingerprint, and set HostKeyAlgorithms to the algorithms for that type when dialing with a pin. For existing pins that have no stored type, try each offered key type in turn and accept only an exact fingerprint match.

    Real retention across a firmware upgrade is still pending; I'll confirm after my next sysupgrade.

    (Disclosure as before: I ran and reviewed the tests on my hardware; Claude did the analysis and drafted this text.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions