|
@@ -1125,12 +1125,13 @@ void rxrpc_data_ready(struct sock *udp_sk)
|
|
{
|
|
{
|
|
struct rxrpc_connection *conn;
|
|
struct rxrpc_connection *conn;
|
|
struct rxrpc_channel *chan;
|
|
struct rxrpc_channel *chan;
|
|
- struct rxrpc_call *call;
|
|
|
|
|
|
+ struct rxrpc_call *call = NULL;
|
|
struct rxrpc_skb_priv *sp;
|
|
struct rxrpc_skb_priv *sp;
|
|
struct rxrpc_local *local = udp_sk->sk_user_data;
|
|
struct rxrpc_local *local = udp_sk->sk_user_data;
|
|
|
|
+ struct rxrpc_sock *rx;
|
|
struct sk_buff *skb;
|
|
struct sk_buff *skb;
|
|
unsigned int channel;
|
|
unsigned int channel;
|
|
- int ret, skew;
|
|
|
|
|
|
+ int ret, skew = 0;
|
|
|
|
|
|
_enter("%p", udp_sk);
|
|
_enter("%p", udp_sk);
|
|
|
|
|
|
@@ -1181,12 +1182,6 @@ void rxrpc_data_ready(struct sock *udp_sk)
|
|
|
|
|
|
trace_rxrpc_rx_packet(sp);
|
|
trace_rxrpc_rx_packet(sp);
|
|
|
|
|
|
- if (sp->hdr.type >= RXRPC_N_PACKET_TYPES ||
|
|
|
|
- !((RXRPC_SUPPORTED_PACKET_TYPES >> sp->hdr.type) & 1)) {
|
|
|
|
- _proto("Rx Bad Packet Type %u", sp->hdr.type);
|
|
|
|
- goto bad_message;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
switch (sp->hdr.type) {
|
|
switch (sp->hdr.type) {
|
|
case RXRPC_PACKET_TYPE_VERSION:
|
|
case RXRPC_PACKET_TYPE_VERSION:
|
|
if (rxrpc_to_client(sp))
|
|
if (rxrpc_to_client(sp))
|
|
@@ -1198,24 +1193,63 @@ void rxrpc_data_ready(struct sock *udp_sk)
|
|
if (rxrpc_to_server(sp))
|
|
if (rxrpc_to_server(sp))
|
|
goto discard;
|
|
goto discard;
|
|
/* Fall through */
|
|
/* Fall through */
|
|
|
|
+ case RXRPC_PACKET_TYPE_ACK:
|
|
|
|
+ case RXRPC_PACKET_TYPE_ACKALL:
|
|
|
|
+ if (sp->hdr.callNumber == 0)
|
|
|
|
+ goto bad_message;
|
|
|
|
+ /* Fall through */
|
|
|
|
+ case RXRPC_PACKET_TYPE_ABORT:
|
|
|
|
+ break;
|
|
|
|
|
|
case RXRPC_PACKET_TYPE_DATA:
|
|
case RXRPC_PACKET_TYPE_DATA:
|
|
- if (sp->hdr.callNumber == 0)
|
|
|
|
|
|
+ if (sp->hdr.callNumber == 0 ||
|
|
|
|
+ sp->hdr.seq == 0)
|
|
goto bad_message;
|
|
goto bad_message;
|
|
if (sp->hdr.flags & RXRPC_JUMBO_PACKET &&
|
|
if (sp->hdr.flags & RXRPC_JUMBO_PACKET &&
|
|
!rxrpc_validate_jumbo(skb))
|
|
!rxrpc_validate_jumbo(skb))
|
|
goto bad_message;
|
|
goto bad_message;
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case RXRPC_PACKET_TYPE_CHALLENGE:
|
|
|
|
+ if (rxrpc_to_server(sp))
|
|
|
|
+ goto discard;
|
|
|
|
+ break;
|
|
|
|
+ case RXRPC_PACKET_TYPE_RESPONSE:
|
|
|
|
+ if (rxrpc_to_client(sp))
|
|
|
|
+ goto discard;
|
|
|
|
+ break;
|
|
|
|
+
|
|
/* Packet types 9-11 should just be ignored. */
|
|
/* Packet types 9-11 should just be ignored. */
|
|
case RXRPC_PACKET_TYPE_PARAMS:
|
|
case RXRPC_PACKET_TYPE_PARAMS:
|
|
case RXRPC_PACKET_TYPE_10:
|
|
case RXRPC_PACKET_TYPE_10:
|
|
case RXRPC_PACKET_TYPE_11:
|
|
case RXRPC_PACKET_TYPE_11:
|
|
goto discard;
|
|
goto discard;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ _proto("Rx Bad Packet Type %u", sp->hdr.type);
|
|
|
|
+ goto bad_message;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (sp->hdr.serviceId == 0)
|
|
|
|
+ goto bad_message;
|
|
|
|
+
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
|
|
|
|
|
|
+ if (rxrpc_to_server(sp)) {
|
|
|
|
+ /* Weed out packets to services we're not offering. Packets
|
|
|
|
+ * that would begin a call are explicitly rejected and the rest
|
|
|
|
+ * are just discarded.
|
|
|
|
+ */
|
|
|
|
+ rx = rcu_dereference(local->service);
|
|
|
|
+ if (!rx || (sp->hdr.serviceId != rx->srx.srx_service &&
|
|
|
|
+ sp->hdr.serviceId != rx->second_service)) {
|
|
|
|
+ if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA &&
|
|
|
|
+ sp->hdr.seq == 1)
|
|
|
|
+ goto unsupported_service;
|
|
|
|
+ goto discard_unlock;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
conn = rxrpc_find_connection_rcu(local, skb);
|
|
conn = rxrpc_find_connection_rcu(local, skb);
|
|
if (conn) {
|
|
if (conn) {
|
|
if (sp->hdr.securityIndex != conn->security_ix)
|
|
if (sp->hdr.securityIndex != conn->security_ix)
|
|
@@ -1297,14 +1331,10 @@ void rxrpc_data_ready(struct sock *udp_sk)
|
|
if (!test_bit(RXRPC_CALL_RX_HEARD, &call->flags))
|
|
if (!test_bit(RXRPC_CALL_RX_HEARD, &call->flags))
|
|
set_bit(RXRPC_CALL_RX_HEARD, &call->flags);
|
|
set_bit(RXRPC_CALL_RX_HEARD, &call->flags);
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
- skew = 0;
|
|
|
|
- call = NULL;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (!call || atomic_read(&call->usage) == 0) {
|
|
if (!call || atomic_read(&call->usage) == 0) {
|
|
if (rxrpc_to_client(sp) ||
|
|
if (rxrpc_to_client(sp) ||
|
|
- sp->hdr.callNumber == 0 ||
|
|
|
|
sp->hdr.type != RXRPC_PACKET_TYPE_DATA)
|
|
sp->hdr.type != RXRPC_PACKET_TYPE_DATA)
|
|
goto bad_message_unlock;
|
|
goto bad_message_unlock;
|
|
if (sp->hdr.seq != 1)
|
|
if (sp->hdr.seq != 1)
|
|
@@ -1340,6 +1370,13 @@ wrong_security:
|
|
skb->priority = RXKADINCONSISTENCY;
|
|
skb->priority = RXKADINCONSISTENCY;
|
|
goto post_abort;
|
|
goto post_abort;
|
|
|
|
|
|
|
|
+unsupported_service:
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
+ trace_rxrpc_abort(0, "INV", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
|
|
|
|
+ RX_INVALID_OPERATION, EOPNOTSUPP);
|
|
|
|
+ skb->priority = RX_INVALID_OPERATION;
|
|
|
|
+ goto post_abort;
|
|
|
|
+
|
|
reupgrade:
|
|
reupgrade:
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
trace_rxrpc_abort(0, "UPG", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
|
|
trace_rxrpc_abort(0, "UPG", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
|