Message ID | 20240420070116.4023672-1-edumazet@google.com (mailing list archive) |
---|---|
State | Accepted |
Commit | c58e88d49097bd12dfcfef4f075b43f5d5830941 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [v2,net] icmp: prevent possible NULL dereferences from icmp_build_probe() | expand |
On 4/20/24 1:01 AM, Eric Dumazet wrote: > First problem is a double call to __in_dev_get_rcu(), because > the second one could return NULL. > > if (__in_dev_get_rcu(dev) && __in_dev_get_rcu(dev)->ifa_list) > > Second problem is a read from dev->ip6_ptr with no NULL check: > > if (!list_empty(&rcu_dereference(dev->ip6_ptr)->addr_list)) > > Use the correct RCU API to fix these. > > v2: add missing include <net/addrconf.h> > > Fixes: d329ea5bd884 ("icmp: add response to RFC 8335 PROBE messages") > Signed-off-by: Eric Dumazet <edumazet@google.com> > Cc: Andreas Roeseler <andreas.a.roeseler@gmail.com> > --- > net/ipv4/icmp.c | 12 ++++++++++-- > 1 file changed, 10 insertions(+), 2 deletions(-) > Reviewed-by: David Ahern <dsahern@kernel.org>
Hello: This patch was applied to netdev/net.git (main) by David S. Miller <davem@davemloft.net>: On Sat, 20 Apr 2024 07:01:16 +0000 you wrote: > First problem is a double call to __in_dev_get_rcu(), because > the second one could return NULL. > > if (__in_dev_get_rcu(dev) && __in_dev_get_rcu(dev)->ifa_list) > > Second problem is a read from dev->ip6_ptr with no NULL check: > > [...] Here is the summary with links: - [v2,net] icmp: prevent possible NULL dereferences from icmp_build_probe() https://git.kernel.org/netdev/net/c/c58e88d49097 You are awesome, thank you!
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index e63a3bf99617627e17669f9b3aaee1cbbf178ebf..437e782b9663bb59acb900c0558137ddd401cd02 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -92,6 +92,7 @@ #include <net/inet_common.h> #include <net/ip_fib.h> #include <net/l3mdev.h> +#include <net/addrconf.h> /* * Build xmit assembly blocks @@ -1032,6 +1033,8 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr) struct icmp_ext_hdr *ext_hdr, _ext_hdr; struct icmp_ext_echo_iio *iio, _iio; struct net *net = dev_net(skb->dev); + struct inet6_dev *in6_dev; + struct in_device *in_dev; struct net_device *dev; char buff[IFNAMSIZ]; u16 ident_len; @@ -1115,10 +1118,15 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr) /* Fill bits in reply message */ if (dev->flags & IFF_UP) status |= ICMP_EXT_ECHOREPLY_ACTIVE; - if (__in_dev_get_rcu(dev) && __in_dev_get_rcu(dev)->ifa_list) + + in_dev = __in_dev_get_rcu(dev); + if (in_dev && rcu_access_pointer(in_dev->ifa_list)) status |= ICMP_EXT_ECHOREPLY_IPV4; - if (!list_empty(&rcu_dereference(dev->ip6_ptr)->addr_list)) + + in6_dev = __in6_dev_get(dev); + if (in6_dev && !list_empty(&in6_dev->addr_list)) status |= ICMP_EXT_ECHOREPLY_IPV6; + dev_put(dev); icmphdr->un.echo.sequence |= htons(status); return true;
First problem is a double call to __in_dev_get_rcu(), because the second one could return NULL. if (__in_dev_get_rcu(dev) && __in_dev_get_rcu(dev)->ifa_list) Second problem is a read from dev->ip6_ptr with no NULL check: if (!list_empty(&rcu_dereference(dev->ip6_ptr)->addr_list)) Use the correct RCU API to fix these. v2: add missing include <net/addrconf.h> Fixes: d329ea5bd884 ("icmp: add response to RFC 8335 PROBE messages") Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Andreas Roeseler <andreas.a.roeseler@gmail.com> --- net/ipv4/icmp.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)