tipc_get_gap_ack_blks() reads the Gap ACK block header fields (len, ugack_cnt, bgack_cnt) from msg_data(hdr) without first checking that the message data area is large enough to hold the header struct. A peer that has negotiated TIPC_GAP_ACK_BLOCK capability can send a STATE_MSG or broadcast PROTOCOL message with a data area shorter than sizeof(struct tipc_gap_ack_blks), causing an out-of-bounds read of up to 4 bytes past the valid skb data. In the backward-compatible code path, a 1-byte out-of-bounds write also occurs through "p->bgack_cnt = 0". Both callers (tipc_link_proto_rcv and tipc_bcast_sync_rcv) validate the returned size against msg_data_sz() after the function returns, so the invalid data is never used further. However, the OOB accesses inside the function itself are undefined behavior and are detectable by KASAN. Add a check at the start of the function that msg_data_sz(hdr) is at least sizeof(*p) before reading any fields, jumping to the p = NULL path when the data area is too small. Fixes: d7626b5acff9 ("tipc: introduce Gap ACK blocks for broadcast link") Cc: stable@vger.kernel.org --- net/tipc/link.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/tipc/link.c b/net/tipc/link.c index 6427c69f8929..0be86cbdc913 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1419,6 +1419,8 @@ u16 tipc_get_gap_ack_blks(struct tipc_gap_ack_blks **ga, struct tipc_link *l, /* Does peer support the Gap ACK blocks feature? */ if (l->peer_caps & TIPC_GAP_ACK_BLOCK) { + if (msg_data_sz(hdr) < sizeof(*p)) + goto out; p = (struct tipc_gap_ack_blks *)msg_data(hdr); sz = ntohs(p->len); /* Sanity check */ @@ -1435,6 +1437,7 @@ u16 tipc_get_gap_ack_blks(struct tipc_gap_ack_blks **ga, struct tipc_link *l, } } /* Other cases: ignore! */ +out: p = NULL; ok: -- 2.43.0