]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
ipv4/route: fail early when inet dev is missing
authorPaolo Abeni <pabeni@redhat.com>
Wed, 6 Mar 2019 09:42:53 +0000 (10:42 +0100)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Wed, 14 Aug 2019 09:18:49 +0000 (11:18 +0200)
BugLink: https://bugs.launchpad.net/bugs/1837952
[ Upstream commit 22c74764aa2943ecdf9f07c900d8a9c8ba6c9265 ]

If a non local multicast packet reaches ip_route_input_rcu() while
the ingress device IPv4 private data (in_dev) is NULL, we end up
doing a NULL pointer dereference in IN_DEV_MFORWARD().

Since the later call to ip_route_input_mc() is going to fail if
!in_dev, we can fail early in such scenario and avoid the dangerous
code path.

v1 -> v2:
 - clarified the commit message, no code changes

Reported-by: Tianhao Zhao <tizhao@redhat.com>
Fixes: e58e41596811 ("net: Enable support for VRF with ipv4 multicast")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
net/ipv4/route.c

index f1f79e29cc1a31959c53d992ec99b239c3619cfc..5a2d253e920e2744099b9ce85e6df418618056f5 100644 (file)
@@ -2129,12 +2129,13 @@ int ip_route_input_rcu(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                int our = 0;
                int err = -EINVAL;
 
-               if (in_dev)
-                       our = ip_check_mc_rcu(in_dev, daddr, saddr,
-                                             ip_hdr(skb)->protocol);
+               if (!in_dev)
+                       return err;
+               our = ip_check_mc_rcu(in_dev, daddr, saddr,
+                                     ip_hdr(skb)->protocol);
 
                /* check l3 master if no match yet */
-               if ((!in_dev || !our) && netif_is_l3_slave(dev)) {
+               if (!our && netif_is_l3_slave(dev)) {
                        struct in_device *l3_in_dev;
 
                        l3_in_dev = __in_dev_get_rcu(skb->dev);