On Thu, Jun 18, 2026 at 6:12 PM Bryam Vargas <[email protected]> wrote: > > Hello John, and LSM folks, > > I have been working on the Landlock TCP Fast Open connect bypass [1]. Stephen > Smalley's SELinux fix for the same issue [3] -- "Similar to Landlock, SELinux > was > not updated when TCP Fast Open support was introduced ..." -- made me go back > and > check the rest of the connect-mediating LSMs, since I had only been looking at > Landlock. With Landlock [2], SELinux [3], and now TOMOYO [4] all getting > fixes, > AppArmor is the last one with the same gap and no fix yet. > > Root cause (shared with the others) > ----------------------------------- > security_socket_connect() has a single call site, net/socket.c (the connect(2) > syscall). TCP Fast Open performs an implicit connect inside sendmsg: > > tcp_sendmsg -> tcp_sendmsg_fastopen -> __inet_stream_connect(..., > is_sendmsg=1) > -> sk->sk_prot->connect() > net/ipv4/{tcp.c,af_inet.c} > > This never calls security_socket_connect(); the only LSM hook on the path is > security_socket_sendmsg(). mptcp_sendmsg_fastopen reaches the same code and > is a > second producer. > > AppArmor > -------- > apparmor_socket_connect() requests AA_MAY_CONNECT; apparmor_socket_sendmsg() > (via > aa_sock_msg_perm) requests AA_MAY_SEND. These are distinct bits, and > apparmor_parser > compiles them independently: "network send inet stream," yields accept mask > 0x02 > while "network connect inet stream," yields 0x40. So an egress-restriction > profile > that grants send but not connect is bypassed by MSG_FASTOPEN. > > Reproduced on 6.12.88 with apparmor active. Under a profile granting the > inet/inet6 > stream lifecycle except connect: > > aa-exec -p egress_restricted -- ./probe > [TCP ] connect(2)=EACCES(blocked) sendto(MSG_FASTOPEN)=OK(reached) => > connection established > [TCP6] connect(2)=EACCES(blocked) sendto(MSG_FASTOPEN)=OK(reached) => > connection established > > (The coarse "network inet stream," idiom grants connect anyway, so this only > bites the > fine-grained "allow send, deny connect" policy that the asymmetry is meant to > serve.) > > Fix > --- > Same shape as the TOMOYO [4] and SELinux [3] fixes: in > apparmor_socket_sendmsg (or > aa_sock_msg_perm), when MSG_FASTOPEN is set and msg_name carries a > destination on a > not-yet-connected stream socket, additionally require aa_sk_perm(OP_CONNECT, > AA_MAY_CONNECT, sk). I am happy to send that patch and the reproducer.
We would appreciate having the patch and the reproducer to look over. Ideally, the reproducer could be integrated as a regression test into the upstream repo at https://gitlab.com/apparmor/apparmor/-/tree/master/tests/regression/apparmor?ref_type=heads, but we can also assist with that step. > > (A single core check in __inet_stream_connect(), gated on is_sendmsg, would > have > covered all five LSMs and both the TCP and MPTCP producers in one place -- > the kernel > already mediates the analogous implicit-connect-on-send for AF_UNIX via > security_unix_may_send and for SCTP via security_sctp_bind_connect. But since > the > other four LSMs are taking per-hook fixes, AppArmor matching them is the > consistent > move; mentioning the core option only in case it is preferred.) > > [1] Landlock: LANDLOCK_ACCESS_NET_CONNECT_TCP bypass via TCP Fast Open > (report) > https://lore.kernel.org/r/[email protected] > [2] landlock: fix TCP Fast Open connection bypass (Matthieu Buffet) > https://lore.kernel.org/r/[email protected] > [3] selinux: check connect-related permissions on TCP Fast Open (Stephen > Smalley) > > https://lore.kernel.org/r/[email protected] > [4] tomoyo: Enforce connect policy in TCP Fast Open (Matthieu Buffet) > https://lore.kernel.org/r/[email protected] > > Thanks, > Bryam Vargas > >
