l2tp: prevent lockdep issue in l2tp_tunnel_register()
[platform/kernel/linux-rpi.git] / net / tipc / link.c
index 1b7a487..8fdd3b2 100644 (file)
@@ -1298,8 +1298,11 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
                return false;
 #ifdef CONFIG_TIPC_CRYPTO
        case MSG_CRYPTO:
-               tipc_crypto_msg_rcv(l->net, skb);
-               return true;
+               if (TIPC_SKB_CB(skb)->decrypted) {
+                       tipc_crypto_msg_rcv(l->net, skb);
+                       return true;
+               }
+               fallthrough;
 #endif
        default:
                pr_warn("Dropping received illegal msg type\n");
@@ -2196,7 +2199,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
        struct tipc_msg *hdr = buf_msg(skb);
        struct tipc_gap_ack_blks *ga = NULL;
        bool reply = msg_probe(hdr), retransmitted = false;
-       u16 dlen = msg_data_sz(hdr), glen = 0;
+       u32 dlen = msg_data_sz(hdr), glen = 0;
        u16 peers_snd_nxt =  msg_next_sent(hdr);
        u16 peers_tol = msg_link_tolerance(hdr);
        u16 peers_prio = msg_linkprio(hdr);
@@ -2210,13 +2213,19 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
        void *data;
 
        trace_tipc_proto_rcv(skb, false, l->name);
+
+       if (dlen > U16_MAX)
+               goto exit;
+
        if (tipc_link_is_blocked(l) || !xmitq)
                goto exit;
 
        if (tipc_own_addr(l->net) > msg_prevnode(hdr))
                l->net_plane = msg_net_plane(hdr);
 
-       skb_linearize(skb);
+       if (skb_linearize(skb))
+               goto exit;
+
        hdr = buf_msg(skb);
        data = msg_data(hdr);
 
@@ -2278,6 +2287,11 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
                break;
 
        case STATE_MSG:
+               /* Validate Gap ACK blocks, drop if invalid */
+               glen = tipc_get_gap_ack_blks(&ga, l, hdr, true);
+               if (glen > dlen)
+                       break;
+
                l->rcv_nxt_state = msg_seqno(hdr) + 1;
 
                /* Update own tolerance if peer indicates a non-zero value */
@@ -2303,9 +2317,6 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
                        break;
                }
 
-               /* Receive Gap ACK blocks from peer if any */
-               glen = tipc_get_gap_ack_blks(&ga, l, hdr, true);
-
                tipc_mon_rcv(l->net, data + glen, dlen - glen, l->addr,
                             &l->mon_state, l->bearer_id);