Follow-up with analysis of the parser and the compiled policy.
TL;DR: JJ is right that the test profile needs the "create" permission.
The "deny connect breaks create" effect I saw earlier was real but only
on a different (coarse/compat) code path; on the path the QRT test
actually uses, create is denied simply because the profile never grants
it.
Details, from analyzing the compiled policy with a small userspace tool
that models the kernel's network DFA match (aa_profile_af_perm ->
aa_match_to_prot -> early_match):
1. The QRT test profile (tests/regression/apparmor/net_inet_tcp_fastopen.sh,
gen_send_no_connect) uses "abi <kernel>," and grants:
network (send,receive,accept,listen,bind) ip=127.0.0.1 port=$port,
...
deny network (connect) ip=127.0.0.1,
Note: it grants bind/listen/accept/send/receive but NOT create. The test
binary calls socket() to stand up an in-process listener, which needs the
"create" permission.
2. Compiling that exact profile (both the distro 5.0.2 parser and current
apparmor master) and walking the policy DFA the way the kernel does for
socket(AF_INET, SOCK_STREAM, 0):
create -> state with allow = 0x8000 (lock only) -> DENIED
Adding "create" to the allow rules makes it:
allow = create,lock,continue-match -> ALLOWED
So create is denied because the profile does not grant create. This matches
JJ's observation.
3. Why it regressed between 5.0.0~beta1 and 5.0.2 (same kernel): the parser
now treats "create" as a distinct, separately-mediated permission for
inet/inet6 stream sockets, so a profile that grants bind/listen/accept but
not create no longer lets socket() through. Presumably in 5.0.0~beta1
create was implied or not separately enforced for this case.
4. Separately, there IS a genuine parser bug in the coarse (legacy
net_allowed_af) downgrade path, but it is NOT what the QRT test hits. To
see it, compile a profile WITHOUT an abi rule (so the parser falls back to
the default policy abi, which lacks network_v8/v9 and therefore downgrades
to the legacy per-AF socket-type table). Then:
profile t { file, network (create) ip=127.0.0.1, }
gives net_allowed_af[inet].allow = 0x43e (create present), but adding
deny network (connect) ip=127.0.0.1,
makes net_allowed_af[inet].allow = 0x0 -- the entire family allow mask is
wiped, not just connect. The cause is parser/network.cc update_compat_net()
OR-ing the socket *type* (entry.type) into the deny mask for every inet
mapping the conditional rule enumerates, which cannot express a per-
operation deny in the legacy model. Again: this is a real bug but it is a
different code path from the fine-grained one the QRT test uses.
So the actionable fix for the QRT test is to add "create" to the listener
socket rules in net_inet_tcp_fastopen.sh (and possibly audit other
fine-grained inet tests for the same missing create). The legacy downgrade
mismatch in update_compat_net() is worth a separate fix.
Tooling note: I added zstd decompression and a "query network" command to
go-apparmor/apparmor-insight to do this analysis from userspace; happy to
share if useful.
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2163740
Title:
net_inet_tcp_fastopen from ubuntu_qrt_apparmor failed on Resolute
To manage notifications about this bug go to:
https://bugs.launchpad.net/apparmor/+bug/2163740/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs