session: enforce session ACLs for non-root ubus callers - #38
Open
JuliusBairaktaris wants to merge 1 commit into
Open
session: enforce session ACLs for non-root ubus callers#38JuliusBairaktaris wants to merge 1 commit into
JuliusBairaktaris wants to merge 1 commit into
Conversation
Reaching rpcd over ubus is treated as authorisation: rpc_file_access() and its three uci.c siblings return true outright when a request carries no ubus_rpc_session, and rc, sys and iwinfo never look at a session at all. That holds only while ubusd's uid 0 exemption is the sole way in. The moment a /usr/share/acl.d entry lets a non-root uid reach the file object, "no session" means unrestricted read, write and exec as root, and rc init and system.password_set are open to whoever holds that uid. Guard every object rpcd registers: a caller ubusd reports as non-root must satisfy the session ACL the ubus proxies already check before forwarding - rpc_session_access(sid, "ubus", object, method) - with the default session when the request carries no id, so the unauthenticated group governs pre-auth access. Callers at uid 0 are unaffected. The check is installed by walking ctx->objects once after the api_init calls and swapping each method's handler for the guard, which keeps it in one place and covers the file, sys, iwinfo, ucode and exec plugins without an ops or ABI change. The session object keeps the six methods that act on nothing but the id handed to them - access, destroy, get, login, set and unset - reachable without an ACL, because they are how a caller authenticates and reaches its own session; create, grant, revoke and list are guarded like everything else. Assisted-by: Claude:claude-opus-5 Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Author
|
This is the prerequisite for granting any non-root daemon an Blocks openwrt/openwrt#24558 (running uhttpd, pppd and odhcpd unprivileged), and is a prerequisite for #40. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reaching rpcd over ubus is treated as authorisation.
rpc_file_access()and its threeuci.csiblings return true outright when a request carries noubus_rpc_session, andrc,sysandiwinfonever look at a session at all. That is safe only while ubusd's uid 0 exemption is the sole way in.It stops being safe as soon as a
/usr/share/acl.dentry lets a non-root uid reach one of those objects — something OpenWrt is about to do for a jailed uhttpd (openwrt/openwrt#24558). With such a grant in place, "no session" means unrestricted read, write and exec as root, andrc initandsystem.password_setare open to whoever holds that uid.This guards every object rpcd registers: a caller ubusd reports as non-root has to satisfy
rpc_session_access(sid, "ubus", object, method)— the same checkuhttpd's ubus proxy and cgi-io already perform before forwarding — with the default session when the request carries no id, so rpcd's ownunauthenticatedgroup governs pre-auth access. Callers at uid 0 are unaffected, so every existing shell and script path behaves exactly as before.The check is installed by walking
ctx->objectsonce after theapi_initcalls and swapping each method's handler for the guard. That keeps it in one place and covers thefile,sys,iwinfo,ucodeandexecplugins without an ops or ABI change.The
sessionobject keeps the six methods that act on nothing but the id handed to them —access,destroy,get,login,set,unset— reachable without an ACL, since they are how a caller authenticates and reaches its own session.create,grant,revokeandlistare guarded like everything else;grantin particular would otherwise let anyone holding the default session id escalate it.Testing
ipq807x router, OpenWrt snapshot with LuCI.
As uid 0, unchanged:
ubus call file exec,ubus call uci getandubus call system boardall behave as before.As a non-root uid holding an
acl.dgrant for thefileanduciobjects and presenting no session:Without this commit the second call returns the contents of
/etc/shadow.LuCI is unaffected end to end — login, page render, and
/ubus-proxieduci get,file readandluci-rpc getNetworkDevicesall carry a session id already, which is what the guard checks.No ubusd ACL file shipped by OpenWrt today grants a non-root uid access to an rpcd object —
luci-base.json,dnsmasq_acl.json,ntpd.json,logd.jsonandwpad_acl.jsonname procd, netifd and hostapd objects only — so nothing changes for existing installs.