If a call-level abort is received for the previous call to complete on a
connection channel, then that abort is queued for the connection processor
to handle.  Unfortunately, the connection processor then assumes without
checking that the abort is connection-level (ie. callNumber is 0) and
distributes it over all active calls on that connection, thereby
incorrectly aborting them.

Fix this by discarding aborts aimed at a completed call.

Further, discard all packets aimed at a call that's complete if there's
currently an active call on a channel, since the DATA packets associated
with the new call automatically terminate the old call.

Fixes: 18bfeba50dfd ("rxrpc: Perform terminal call ACK/ABORT retransmission 
from conn processor")
Reported-by: Marc Dionne <marc.dio...@auristor.com>
Signed-off-by: David Howells <dhowe...@redhat.com>
---

 net/rxrpc/input.c |   15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index d4f2509e018b..21800e6f5019 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -1242,16 +1242,19 @@ void rxrpc_data_ready(struct sock *udp_sk)
                        goto discard_unlock;
 
                if (sp->hdr.callNumber == chan->last_call) {
-                       /* For the previous service call, if completed 
successfully, we
-                        * discard all further packets.
+                       if (chan->call ||
+                           sp->hdr.type == RXRPC_PACKET_TYPE_ABORT)
+                               goto discard_unlock;
+
+                       /* For the previous service call, if completed
+                        * successfully, we discard all further packets.
                         */
                        if (rxrpc_conn_is_service(conn) &&
-                           (chan->last_type == RXRPC_PACKET_TYPE_ACK ||
-                            sp->hdr.type == RXRPC_PACKET_TYPE_ABORT))
+                           chan->last_type == RXRPC_PACKET_TYPE_ACK)
                                goto discard_unlock;
 
-                       /* But otherwise we need to retransmit the final packet 
from
-                        * data cached in the connection record.
+                       /* But otherwise we need to retransmit the final packet
+                        * from data cached in the connection record.
                         */
                        rxrpc_post_packet_to_conn(conn, skb);
                        goto out_unlock;

Reply via email to