diff options
author | David Howells <dhowells@redhat.com> | 2018-03-30 23:04:44 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-05-30 08:52:26 +0300 |
commit | 637b9b187f4e024979e9ca401042eee2b5390a1e (patch) | |
tree | 94f689b0760721a982739c6b4372eff76c22a459 | |
parent | 4a9fabcd3440357e45b4b52f47478d57858cede4 (diff) | |
download | linux-637b9b187f4e024979e9ca401042eee2b5390a1e.tar.xz |
rxrpc: Don't treat call aborts as conn aborts
[ Upstream commit 57b0c9d49b94bbeb53649b7fbd264603c1ebd585 ]
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.dionne@auristor.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | net/rxrpc/input.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index e56e23ed2229..5edb636dbc4d 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c @@ -1175,16 +1175,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; |