Patch "tipc: do not update mtu if msg_max is too small in mtu negotiation" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    tipc: do not update mtu if msg_max is too small in mtu negotiation

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     tipc-do-not-update-mtu-if-msg_max-is-too-small-in-mt.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 8b69368f9f627d32c4f67927451439540958e383
Author: Xin Long <lucien.xin@xxxxxxxxx>
Date:   Sun May 14 15:52:28 2023 -0400

    tipc: do not update mtu if msg_max is too small in mtu negotiation
    
    [ Upstream commit 56077b56cd3fb78e1c8619e29581ba25a5c55e86 ]
    
    When doing link mtu negotiation, a malicious peer may send Activate msg
    with a very small mtu, e.g. 4 in Shuang's testing, without checking for
    the minimum mtu, l->mtu will be set to 4 in tipc_link_proto_rcv(), then
    n->links[bearer_id].mtu is set to 4294967228, which is a overflow of
    '4 - INT_H_SIZE - EMSG_OVERHEAD' in tipc_link_mss().
    
    With tipc_link.mtu = 4, tipc_link_xmit() kept printing the warning:
    
     tipc: Too large msg, purging xmit list 1 5 0 40 4!
     tipc: Too large msg, purging xmit list 1 15 0 60 4!
    
    And with tipc_link_entry.mtu 4294967228, a huge skb was allocated in
    named_distribute(), and when purging it in tipc_link_xmit(), a crash
    was even caused:
    
      general protection fault, probably for non-canonical address 0x2100001011000dd: 0000 [#1] PREEMPT SMP PTI
      CPU: 0 PID: 0 Comm: swapper/0 Kdump: loaded Not tainted 6.3.0.neta #19
      RIP: 0010:kfree_skb_list_reason+0x7e/0x1f0
      Call Trace:
       <IRQ>
       skb_release_data+0xf9/0x1d0
       kfree_skb_reason+0x40/0x100
       tipc_link_xmit+0x57a/0x740 [tipc]
       tipc_node_xmit+0x16c/0x5c0 [tipc]
       tipc_named_node_up+0x27f/0x2c0 [tipc]
       tipc_node_write_unlock+0x149/0x170 [tipc]
       tipc_rcv+0x608/0x740 [tipc]
       tipc_udp_recv+0xdc/0x1f0 [tipc]
       udp_queue_rcv_one_skb+0x33e/0x620
       udp_unicast_rcv_skb.isra.72+0x75/0x90
       __udp4_lib_rcv+0x56d/0xc20
       ip_protocol_deliver_rcu+0x100/0x2d0
    
    This patch fixes it by checking the new mtu against tipc_bearer_min_mtu(),
    and not updating mtu if it is too small.
    
    Fixes: ed193ece2649 ("tipc: simplify link mtu negotiation")
    Reported-by: Shuang Li <shuali@xxxxxxxxxx>
    Signed-off-by: Xin Long <lucien.xin@xxxxxxxxx>
    Acked-by: Jon Maloy <jmaloy@xxxxxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/net/tipc/link.c b/net/tipc/link.c
index 8fdd3b23bd123..655a2e1b6dfe4 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -2199,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;
-	u32 dlen = msg_data_sz(hdr), glen = 0;
+	u32 dlen = msg_data_sz(hdr), glen = 0, msg_max;
 	u16 peers_snd_nxt =  msg_next_sent(hdr);
 	u16 peers_tol = msg_link_tolerance(hdr);
 	u16 peers_prio = msg_linkprio(hdr);
@@ -2238,6 +2238,9 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
 	switch (mtyp) {
 	case RESET_MSG:
 	case ACTIVATE_MSG:
+		msg_max = msg_max_pkt(hdr);
+		if (msg_max < tipc_bearer_min_mtu(l->net, l->bearer_id))
+			break;
 		/* Complete own link name with peer's interface name */
 		if_name =  strrchr(l->name, ':') + 1;
 		if (sizeof(l->name) - (if_name - l->name) <= TIPC_MAX_IF_NAME)
@@ -2282,8 +2285,8 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
 		l->peer_session = msg_session(hdr);
 		l->in_session = true;
 		l->peer_bearer_id = msg_bearer_id(hdr);
-		if (l->mtu > msg_max_pkt(hdr))
-			l->mtu = msg_max_pkt(hdr);
+		if (l->mtu > msg_max)
+			l->mtu = msg_max;
 		break;
 
 	case STATE_MSG:



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux