[PATCH net-next 2/3] llc: report a closed connection for out of service sockets

From: Kees Cook

Date: Tue Sep 01 2026 - 17:03:52 EST


An unsolicited frame can move a bound PF_LLC socket from
LLC_CONN_STATE_ADM to LLC_CONN_OUT_OF_SVC while the socket stays open
from userspace's point of view. Both upper layer entry points handle
that badly:

- llc_establish_connection() has no state check at all, so with the
state machine now refusing the event, connect(2) would return the
state machine's "1" failure indication as a positive syscall return
value.

- llc_build_and_send_pkt() special cases LLC_CONN_STATE_ADM as
-ECONNABORTED but falls through to -EBUSY for LLC_CONN_OUT_OF_SVC.
-EBUSY describes a connection that is momentarily unable to send, not
one that no longer exists.

Report -ECONNABORTED from both.

There is deliberately no Fixes: tag here. The connect(2) return value
only becomes observable once the previous patch makes the state machine
refuse the event, and the llc_build_and_send_pkt() change is a
long-standing errno inaccuracy with no memory safety impact. Backporting
this on its own would fix nothing.

Build tested ARCH=x86_64 net/llc/ with GCC 14.2.0, CONFIG_LLC2=y and =m.

Assisted-by: Claude:claude-opus-5[1m]
Signed-off-by: Kees Cook <kees@xxxxxxxxxx>
---
net/llc/llc_if.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c
index 1514362e613d..f1a3f3372c4f 100644
--- a/net/llc/llc_if.c
+++ b/net/llc/llc_if.c
@@ -41,7 +41,8 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
int rc = -ECONNABORTED;
struct llc_sock *llc = llc_sk(sk);

- if (unlikely(llc->state == LLC_CONN_STATE_ADM))
+ if (unlikely(llc->state == LLC_CONN_STATE_ADM ||
+ llc->state == LLC_CONN_OUT_OF_SVC))
goto out_free;
rc = -EBUSY;
if (unlikely(llc_data_accept_state(llc->state) || /* data_conn_refuse */
@@ -82,6 +83,15 @@ int llc_establish_connection(struct sock *sk, const u8 *lmac, u8 *dmac, u8 dsap)
struct llc_sock *llc = llc_sk(sk);
struct sock *existing;

+ /*
+ * A socket parked in LLC_CONN_OUT_OF_SVC has no state machine to run,
+ * so there is nothing to establish. Report it as a closed connection
+ * rather than handing llc_conn_state_process() an event it can only
+ * throw away.
+ */
+ if (unlikely(llc->state == LLC_CONN_OUT_OF_SVC))
+ return -ECONNABORTED;
+
laddr.lsap = llc->sap->laddr.lsap;
daddr.lsap = dsap;
memcpy(daddr.mac, dmac, sizeof(daddr.mac));
--
2.34.1