Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tipc: improve size validations for received domain records

The function tipc_mon_rcv() allows a node to receive and process
domain_record structs from peer nodes to track their views of the
network topology.

This patch verifies that the number of members in a received domain
record does not exceed the limit defined by MAX_MON_DOMAIN, something
that may otherwise lead to a stack overflow.

tipc_mon_rcv() is called from the function tipc_link_proto_rcv(), where
we are reading a 32 bit message data length field into a uint16. To
avert any risk of bit overflow, we add an extra sanity check for this in
that function. We cannot see that happen with the current code, but
future designers being unaware of this risk, may introduce it by
allowing delivery of very large (> 64k) sk buffers from the bearer
layer. This potential problem was identified by Eric Dumazet.

This fixes CVE-2022-0435

Reported-by: Samuel Page <samuel.page@appgate.com>
Reported-by: Eric Dumazet <edumazet@google.com>
Fixes: 35c55c9877f8 ("tipc: add neighbor monitoring framework")
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
Reviewed-by: Xin Long <lucien.xin@gmail.com>
Reviewed-by: Samuel Page <samuel.page@appgate.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Jon Maloy and committed by
Linus Torvalds
9aa422ad f4bc5bbb

+9 -2
+7 -2
net/tipc/link.c
··· 2200 2200 struct tipc_msg *hdr = buf_msg(skb); 2201 2201 struct tipc_gap_ack_blks *ga = NULL; 2202 2202 bool reply = msg_probe(hdr), retransmitted = false; 2203 - u16 dlen = msg_data_sz(hdr), glen = 0; 2203 + u32 dlen = msg_data_sz(hdr), glen = 0; 2204 2204 u16 peers_snd_nxt = msg_next_sent(hdr); 2205 2205 u16 peers_tol = msg_link_tolerance(hdr); 2206 2206 u16 peers_prio = msg_linkprio(hdr); ··· 2214 2214 void *data; 2215 2215 2216 2216 trace_tipc_proto_rcv(skb, false, l->name); 2217 + 2218 + if (dlen > U16_MAX) 2219 + goto exit; 2220 + 2217 2221 if (tipc_link_is_blocked(l) || !xmitq) 2218 2222 goto exit; 2219 2223 ··· 2313 2309 2314 2310 /* Receive Gap ACK blocks from peer if any */ 2315 2311 glen = tipc_get_gap_ack_blks(&ga, l, hdr, true); 2316 - 2312 + if(glen > dlen) 2313 + break; 2317 2314 tipc_mon_rcv(l->net, data + glen, dlen - glen, l->addr, 2318 2315 &l->mon_state, l->bearer_id); 2319 2316
+2
net/tipc/monitor.c
··· 496 496 state->probing = false; 497 497 498 498 /* Sanity check received domain record */ 499 + if (new_member_cnt > MAX_MON_DOMAIN) 500 + return; 499 501 if (dlen < dom_rec_len(arrv_dom, 0)) 500 502 return; 501 503 if (dlen != dom_rec_len(arrv_dom, new_member_cnt))