| From cc76adddd26abce2f18876a3da05d1cf6958e311 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 3 Feb 2026 19:25:09 +0000 |
| Subject: inet: RAW sockets using IPPROTO_RAW MUST drop incoming ICMP |
| |
| From: Eric Dumazet <edumazet@google.com> |
| |
| [ Upstream commit c89477ad79446867394360b29bb801010fc3ff22 ] |
| |
| Yizhou Zhao reported that simply having one RAW socket on protocol |
| IPPROTO_RAW (255) was dangerous. |
| |
| socket(AF_INET, SOCK_RAW, 255); |
| |
| A malicious incoming ICMP packet can set the protocol field to 255 |
| and match this socket, leading to FNHE cache changes. |
| |
| inner = IP(src="192.168.2.1", dst="8.8.8.8", proto=255)/Raw("TEST") |
| pkt = IP(src="192.168.1.1", dst="192.168.2.1")/ICMP(type=3, code=4, nexthopmtu=576)/inner |
| |
| "man 7 raw" states: |
| |
| A protocol of IPPROTO_RAW implies enabled IP_HDRINCL and is able |
| to send any IP protocol that is specified in the passed header. |
| Receiving of all IP protocols via IPPROTO_RAW is not possible |
| using raw sockets. |
| |
| Make sure we drop these malicious packets. |
| |
| Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") |
| Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn> |
| Link: https://lore.kernel.org/netdev/20251109134600.292125-1-zhaoyz24@mails.tsinghua.edu.cn/ |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Reviewed-by: David Ahern <dsahern@kernel.org> |
| Reviewed-by: Ido Schimmel <idosch@nvidia.com> |
| Link: https://patch.msgid.link/20260203192509.682208-1-edumazet@google.com |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/ipv4/icmp.c | 14 ++++++++++---- |
| net/ipv6/icmp.c | 6 ++++++ |
| 2 files changed, 16 insertions(+), 4 deletions(-) |
| |
| diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c |
| index 508b23204edc5..c0373d1172d73 100644 |
| --- a/net/ipv4/icmp.c |
| +++ b/net/ipv4/icmp.c |
| @@ -840,16 +840,22 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info) |
| /* Checkin full IP header plus 8 bytes of protocol to |
| * avoid additional coding at protocol handlers. |
| */ |
| - if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) { |
| - __ICMP_INC_STATS(dev_net_rcu(skb->dev), ICMP_MIB_INERRORS); |
| - return; |
| - } |
| + if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) |
| + goto out; |
| + |
| + /* IPPROTO_RAW sockets are not supposed to receive anything. */ |
| + if (protocol == IPPROTO_RAW) |
| + goto out; |
| |
| raw_icmp_error(skb, protocol, info); |
| |
| ipprot = rcu_dereference(inet_protos[protocol]); |
| if (ipprot && ipprot->err_handler) |
| ipprot->err_handler(skb, info); |
| + return; |
| + |
| +out: |
| + __ICMP_INC_STATS(dev_net_rcu(skb->dev), ICMP_MIB_INERRORS); |
| } |
| |
| static bool icmp_tag_validation(int proto) |
| diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c |
| index 13a796bfc2f93..c8609147fce89 100644 |
| --- a/net/ipv6/icmp.c |
| +++ b/net/ipv6/icmp.c |
| @@ -871,6 +871,12 @@ enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type, |
| if (reason != SKB_NOT_DROPPED_YET) |
| goto out; |
| |
| + if (nexthdr == IPPROTO_RAW) { |
| + /* Add a more specific reason later ? */ |
| + reason = SKB_DROP_REASON_NOT_SPECIFIED; |
| + goto out; |
| + } |
| + |
| /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. |
| Without this we will not able f.e. to make source routed |
| pmtu discovery. |
| -- |
| 2.51.0 |
| |