The AMT message handlers cache pointers into the skb linear area (grec,
iph, ip6h, eth) and keep using them across ip_mc_may_pull() /
pskb_may_pull(). On a non-linear skb (e.g. a reassembled fragmented AMT
membership update) such a pull can reallocate skb->head via
pskb_expand_head(), leaving those pointers dangling into freed memory.
Linearize the skb on entry to amt_rcv() so no later pull reallocates the
head. This is a no-op for the common linear skb, and covers all handlers
at once. Drop the packet if linearization fails.
BUG: KASAN: slab-use-after-free in amt_igmpv3_report_handler (drivers/net/amt.c:2023)
Read of size 4 at addr ffff888013fdd71c by task exploit
Call Trace:
<IRQ>
amt_igmpv3_report_handler (drivers/net/amt.c:2023)
amt_update_handler (drivers/net/amt.c:2503)
amt_rcv (drivers/net/amt.c:2846)
udp_queue_rcv_one_skb (net/ipv4/udp.c:2389)
udp_unicast_rcv_skb (net/ipv4/udp.c:2580)
ip_protocol_deliver_rcu (net/ipv4/ip_input.c:207)
ip_local_deliver_finish (net/ipv4/ip_input.c:242)
ip_local_deliver (net/ipv4/ip_input.c:262)
ip_rcv (net/ipv4/ip_input.c:612)
__netif_receive_skb_one_core (net/core/dev.c:6212)
Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface")
Reported-by: AutonomousCodeSecurity@microsoft.com
Signed-off-by: Xiang Mei (Microsoft) <redacted>
---
drivers/net/amt.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index 951dd10e192b..2bce99d45d2c 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -2785,6 +2785,10 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
}
skb->dev = amt->dev;
+ if (skb_linearize(skb)) {
+ err = true;
+ goto drop;
+ }
iph = ip_hdr(skb);
type = amt_parse_type(skb);
if (type == -1) {--
2.43.0