]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
rxrpc: Fix to use conn aborts for conn-wide failures
authorDavid Howells <dhowells@redhat.com>
Thu, 17 Jul 2025 07:43:45 +0000 (08:43 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 24 Jul 2025 06:58:40 +0000 (08:58 +0200)
[ Upstream commit f0295678ad304195927829b1dbf06553aa2187b0 ]

Fix rxrpc to use connection-level aborts for things that affect the whole
connection, such as the service ID not matching a local service.

Fixes: 57af281e5389 ("rxrpc: Tidy up abort generation infrastructure")
Reported-by: Jeffrey Altman <jaltman@auristor.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/20250717074350.3767366-6-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/rxrpc/ar-internal.h
net/rxrpc/call_accept.c
net/rxrpc/io_thread.c
net/rxrpc/output.c
net/rxrpc/security.c

index b2d64586958fbc6f5185698fd2cf7781a6291ba3..c4891a538ded04571c9553d166003c0824a04079 100644 (file)
@@ -42,6 +42,7 @@ enum rxrpc_skb_mark {
        RXRPC_SKB_MARK_SERVICE_CONN_SECURED, /* Service connection response has been verified */
        RXRPC_SKB_MARK_REJECT_BUSY,     /* Reject with BUSY */
        RXRPC_SKB_MARK_REJECT_ABORT,    /* Reject with ABORT (code in skb->priority) */
+       RXRPC_SKB_MARK_REJECT_CONN_ABORT, /* Reject with connection ABORT (code in skb->priority) */
 };
 
 /*
@@ -1197,6 +1198,8 @@ int rxrpc_encap_rcv(struct sock *, struct sk_buff *);
 void rxrpc_error_report(struct sock *);
 bool rxrpc_direct_abort(struct sk_buff *skb, enum rxrpc_abort_reason why,
                        s32 abort_code, int err);
+bool rxrpc_direct_conn_abort(struct sk_buff *skb, enum rxrpc_abort_reason why,
+                            s32 abort_code, int err);
 int rxrpc_io_thread(void *data);
 static inline void rxrpc_wake_up_io_thread(struct rxrpc_local *local)
 {
index 978f0c6ee3c8a3c013e19de74765836a6235f3de..3259916c926aef97ac5b4cfbb221b35a7c69b076 100644 (file)
@@ -373,8 +373,8 @@ bool rxrpc_new_incoming_call(struct rxrpc_local *local,
        spin_lock(&rx->incoming_lock);
        if (rx->sk.sk_state == RXRPC_SERVER_LISTEN_DISABLED ||
            rx->sk.sk_state == RXRPC_CLOSE) {
-               rxrpc_direct_abort(skb, rxrpc_abort_shut_down,
-                                  RX_INVALID_OPERATION, -ESHUTDOWN);
+               rxrpc_direct_conn_abort(skb, rxrpc_abort_shut_down,
+                                       RX_INVALID_OPERATION, -ESHUTDOWN);
                goto no_call;
        }
 
@@ -420,12 +420,12 @@ bool rxrpc_new_incoming_call(struct rxrpc_local *local,
 
 unsupported_service:
        read_unlock_irq(&local->services_lock);
-       return rxrpc_direct_abort(skb, rxrpc_abort_service_not_offered,
-                                 RX_INVALID_OPERATION, -EOPNOTSUPP);
+       return rxrpc_direct_conn_abort(skb, rxrpc_abort_service_not_offered,
+                                      RX_INVALID_OPERATION, -EOPNOTSUPP);
 unsupported_security:
        read_unlock_irq(&local->services_lock);
-       return rxrpc_direct_abort(skb, rxrpc_abort_service_not_offered,
-                                 RX_INVALID_OPERATION, -EKEYREJECTED);
+       return rxrpc_direct_conn_abort(skb, rxrpc_abort_service_not_offered,
+                                      RX_INVALID_OPERATION, -EKEYREJECTED);
 no_call:
        spin_unlock(&rx->incoming_lock);
        read_unlock_irq(&local->services_lock);
index 64f8d77b87312551705b6f432cc6bea84ba09e42..23dbcc4819990e581ec53b442a7551f4911cc548 100644 (file)
@@ -97,6 +97,20 @@ bool rxrpc_direct_abort(struct sk_buff *skb, enum rxrpc_abort_reason why,
        return false;
 }
 
+/*
+ * Directly produce a connection abort from a packet.
+ */
+bool rxrpc_direct_conn_abort(struct sk_buff *skb, enum rxrpc_abort_reason why,
+                            s32 abort_code, int err)
+{
+       struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+       trace_rxrpc_abort(0, why, sp->hdr.cid, 0, sp->hdr.seq, abort_code, err);
+       skb->mark = RXRPC_SKB_MARK_REJECT_CONN_ABORT;
+       skb->priority = abort_code;
+       return false;
+}
+
 static bool rxrpc_bad_message(struct sk_buff *skb, enum rxrpc_abort_reason why)
 {
        return rxrpc_direct_abort(skb, why, RX_PROTOCOL_ERROR, -EBADMSG);
index d0d04ee9667ef82477b8dc518793e63c03eed311..a480e7e2325ebd050eb92f5c450533c99e42e14f 100644 (file)
@@ -829,7 +829,13 @@ void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
        msg.msg_controllen = 0;
        msg.msg_flags = 0;
 
-       memset(&whdr, 0, sizeof(whdr));
+       whdr = (struct rxrpc_wire_header) {
+               .epoch          = htonl(sp->hdr.epoch),
+               .cid            = htonl(sp->hdr.cid),
+               .callNumber     = htonl(sp->hdr.callNumber),
+               .serviceId      = htons(sp->hdr.serviceId),
+               .flags          = ~sp->hdr.flags & RXRPC_CLIENT_INITIATED,
+       };
 
        switch (skb->mark) {
        case RXRPC_SKB_MARK_REJECT_BUSY:
@@ -837,6 +843,9 @@ void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
                size = sizeof(whdr);
                ioc = 1;
                break;
+       case RXRPC_SKB_MARK_REJECT_CONN_ABORT:
+               whdr.callNumber = 0;
+               fallthrough;
        case RXRPC_SKB_MARK_REJECT_ABORT:
                whdr.type = RXRPC_PACKET_TYPE_ABORT;
                code = htonl(skb->priority);
@@ -850,14 +859,6 @@ void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
        if (rxrpc_extract_addr_from_skb(&srx, skb) == 0) {
                msg.msg_namelen = srx.transport_len;
 
-               whdr.epoch      = htonl(sp->hdr.epoch);
-               whdr.cid        = htonl(sp->hdr.cid);
-               whdr.callNumber = htonl(sp->hdr.callNumber);
-               whdr.serviceId  = htons(sp->hdr.serviceId);
-               whdr.flags      = sp->hdr.flags;
-               whdr.flags      ^= RXRPC_CLIENT_INITIATED;
-               whdr.flags      &= RXRPC_CLIENT_INITIATED;
-
                iov_iter_kvec(&msg.msg_iter, WRITE, iov, ioc, size);
                ret = do_udp_sendmsg(local->socket, &msg, size);
                if (ret < 0)
index 9784adc8f275939c099bae9595edfbe27a47f18e..7a48fee3a6b1a80f189c46ccd123ac8d08fdb4ae 100644 (file)
@@ -137,15 +137,15 @@ const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *rx,
 
        sec = rxrpc_security_lookup(sp->hdr.securityIndex);
        if (!sec) {
-               rxrpc_direct_abort(skb, rxrpc_abort_unsupported_security,
-                                  RX_INVALID_OPERATION, -EKEYREJECTED);
+               rxrpc_direct_conn_abort(skb, rxrpc_abort_unsupported_security,
+                                       RX_INVALID_OPERATION, -EKEYREJECTED);
                return NULL;
        }
 
        if (sp->hdr.securityIndex != RXRPC_SECURITY_NONE &&
            !rx->securities) {
-               rxrpc_direct_abort(skb, rxrpc_abort_no_service_key,
-                                  sec->no_key_abort, -EKEYREJECTED);
+               rxrpc_direct_conn_abort(skb, rxrpc_abort_no_service_key,
+                                       sec->no_key_abort, -EKEYREJECTED);
                return NULL;
        }