aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ipvlan/ipvlan_main.c
diff options
context:
space:
mode:
authorGirish Moodalbail <girish.moodalbail@oracle.com>2017-11-17 02:16:17 -0500
committerDavid S. Miller <davem@davemloft.net>2017-11-17 20:37:00 -0500
commitfe18da60500b8b8aa2621fb1de7132cb1f0aebcf (patch)
treeda29d087913ef4c822a8003aa0415b8bac1f5d11 /drivers/net/ipvlan/ipvlan_main.c
parentcebe84c6190d741045a322f5343f717139993c08 (diff)
ipvlan: NULL pointer dereference panic in ipvlan_port_destroy
When call to register_netdevice() (called from ipvlan_link_new()) fails, we call ipvlan_uninit() (through ndo_uninit()) to destroy the ipvlan port. After returning unsuccessfully from register_netdevice() we go ahead and call ipvlan_port_destroy() again which causes NULL pointer dereference panic. Fix the issue by making ipvlan_init() and ipvlan_uninit() call symmetric. The ipvlan port will now be created inside ipvlan_init() and will be destroyed in ipvlan_uninit(). Fixes: 2ad7bf363841 (ipvlan: Initial check-in of the IPVLAN driver) Signed-off-by: Girish Moodalbail <girish.moodalbail@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ipvlan/ipvlan_main.c')
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c104
1 files changed, 55 insertions, 49 deletions
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index a266aa435d4d..30cb803e2fe5 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -107,16 +107,6 @@ static int ipvlan_port_create(struct net_device *dev)
107 struct ipvl_port *port; 107 struct ipvl_port *port;
108 int err, idx; 108 int err, idx;
109 109
110 if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK) {
111 netdev_err(dev, "Master is either lo or non-ether device\n");
112 return -EINVAL;
113 }
114
115 if (netdev_is_rx_handler_busy(dev)) {
116 netdev_err(dev, "Device is already in use.\n");
117 return -EBUSY;
118 }
119
120 port = kzalloc(sizeof(struct ipvl_port), GFP_KERNEL); 110 port = kzalloc(sizeof(struct ipvl_port), GFP_KERNEL);
121 if (!port) 111 if (!port)
122 return -ENOMEM; 112 return -ENOMEM;
@@ -179,8 +169,9 @@ static void ipvlan_port_destroy(struct net_device *dev)
179static int ipvlan_init(struct net_device *dev) 169static int ipvlan_init(struct net_device *dev)
180{ 170{
181 struct ipvl_dev *ipvlan = netdev_priv(dev); 171 struct ipvl_dev *ipvlan = netdev_priv(dev);
182 const struct net_device *phy_dev = ipvlan->phy_dev; 172 struct net_device *phy_dev = ipvlan->phy_dev;
183 struct ipvl_port *port = ipvlan->port; 173 struct ipvl_port *port;
174 int err;
184 175
185 dev->state = (dev->state & ~IPVLAN_STATE_MASK) | 176 dev->state = (dev->state & ~IPVLAN_STATE_MASK) |
186 (phy_dev->state & IPVLAN_STATE_MASK); 177 (phy_dev->state & IPVLAN_STATE_MASK);
@@ -196,18 +187,27 @@ static int ipvlan_init(struct net_device *dev)
196 if (!ipvlan->pcpu_stats) 187 if (!ipvlan->pcpu_stats)
197 return -ENOMEM; 188 return -ENOMEM;
198 189
190 if (!netif_is_ipvlan_port(phy_dev)) {
191 err = ipvlan_port_create(phy_dev);
192 if (err < 0) {
193 free_percpu(ipvlan->pcpu_stats);
194 return err;
195 }
196 }
197 port = ipvlan_port_get_rtnl(phy_dev);
199 port->count += 1; 198 port->count += 1;
200
201 return 0; 199 return 0;
202} 200}
203 201
204static void ipvlan_uninit(struct net_device *dev) 202static void ipvlan_uninit(struct net_device *dev)
205{ 203{
206 struct ipvl_dev *ipvlan = netdev_priv(dev); 204 struct ipvl_dev *ipvlan = netdev_priv(dev);
207 struct ipvl_port *port = ipvlan->port; 205 struct net_device *phy_dev = ipvlan->phy_dev;
206 struct ipvl_port *port;
208 207
209 free_percpu(ipvlan->pcpu_stats); 208 free_percpu(ipvlan->pcpu_stats);
210 209
210 port = ipvlan_port_get_rtnl(phy_dev);
211 port->count -= 1; 211 port->count -= 1;
212 if (!port->count) 212 if (!port->count)
213 ipvlan_port_destroy(port->dev); 213 ipvlan_port_destroy(port->dev);
@@ -554,7 +554,6 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
554 struct net_device *phy_dev; 554 struct net_device *phy_dev;
555 int err; 555 int err;
556 u16 mode = IPVLAN_MODE_L3; 556 u16 mode = IPVLAN_MODE_L3;
557 bool create = false;
558 557
559 if (!tb[IFLA_LINK]) 558 if (!tb[IFLA_LINK])
560 return -EINVAL; 559 return -EINVAL;
@@ -568,28 +567,41 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
568 567
569 phy_dev = tmp->phy_dev; 568 phy_dev = tmp->phy_dev;
570 } else if (!netif_is_ipvlan_port(phy_dev)) { 569 } else if (!netif_is_ipvlan_port(phy_dev)) {
571 err = ipvlan_port_create(phy_dev); 570 /* Exit early if the underlying link is invalid or busy */
572 if (err < 0) 571 if (phy_dev->type != ARPHRD_ETHER ||
573 return err; 572 phy_dev->flags & IFF_LOOPBACK) {
574 create = true; 573 netdev_err(phy_dev,
575 } 574 "Master is either lo or non-ether device\n");
575 return -EINVAL;
576 }
576 577
577 if (data && data[IFLA_IPVLAN_MODE]) 578 if (netdev_is_rx_handler_busy(phy_dev)) {
578 mode = nla_get_u16(data[IFLA_IPVLAN_MODE]); 579 netdev_err(phy_dev, "Device is already in use.\n");
580 return -EBUSY;
581 }
582 }
579 583
580 port = ipvlan_port_get_rtnl(phy_dev);
581 ipvlan->phy_dev = phy_dev; 584 ipvlan->phy_dev = phy_dev;
582 ipvlan->dev = dev; 585 ipvlan->dev = dev;
583 ipvlan->port = port;
584 ipvlan->sfeatures = IPVLAN_FEATURES; 586 ipvlan->sfeatures = IPVLAN_FEATURES;
585 ipvlan_adjust_mtu(ipvlan, phy_dev); 587 ipvlan_adjust_mtu(ipvlan, phy_dev);
586 INIT_LIST_HEAD(&ipvlan->addrs); 588 INIT_LIST_HEAD(&ipvlan->addrs);
587 589
588 /* Flags are per port and latest update overrides. User has 590 /* TODO Probably put random address here to be presented to the
589 * to be consistent in setting it just like the mode attribute. 591 * world but keep using the physical-dev address for the outgoing
592 * packets.
590 */ 593 */
591 if (data && data[IFLA_IPVLAN_FLAGS]) 594 memcpy(dev->dev_addr, phy_dev->dev_addr, ETH_ALEN);
592 ipvlan->port->flags = nla_get_u16(data[IFLA_IPVLAN_FLAGS]); 595
596 dev->priv_flags |= IFF_IPVLAN_SLAVE;
597
598 err = register_netdevice(dev);
599 if (err < 0)
600 return err;
601
602 /* ipvlan_init() would have created the port, if required */
603 port = ipvlan_port_get_rtnl(phy_dev);
604 ipvlan->port = port;
593 605
594 /* If the port-id base is at the MAX value, then wrap it around and 606 /* If the port-id base is at the MAX value, then wrap it around and
595 * begin from 0x1 again. This may be due to a busy system where lots 607 * begin from 0x1 again. This may be due to a busy system where lots
@@ -609,31 +621,28 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
609 err = ida_simple_get(&port->ida, 0x1, port->dev_id_start, 621 err = ida_simple_get(&port->ida, 0x1, port->dev_id_start,
610 GFP_KERNEL); 622 GFP_KERNEL);
611 if (err < 0) 623 if (err < 0)
612 goto destroy_ipvlan_port; 624 goto unregister_netdev;
613 dev->dev_id = err; 625 dev->dev_id = err;
626
614 /* Increment id-base to the next slot for the future assignment */ 627 /* Increment id-base to the next slot for the future assignment */
615 port->dev_id_start = err + 1; 628 port->dev_id_start = err + 1;
616 629
617 /* TODO Probably put random address here to be presented to the 630 err = netdev_upper_dev_link(phy_dev, dev, extack);
618 * world but keep using the physical-dev address for the outgoing 631 if (err)
619 * packets. 632 goto remove_ida;
620 */
621 memcpy(dev->dev_addr, phy_dev->dev_addr, ETH_ALEN);
622 633
623 dev->priv_flags |= IFF_IPVLAN_SLAVE; 634 /* Flags are per port and latest update overrides. User has
635 * to be consistent in setting it just like the mode attribute.
636 */
637 if (data && data[IFLA_IPVLAN_FLAGS])
638 port->flags = nla_get_u16(data[IFLA_IPVLAN_FLAGS]);
624 639
625 err = register_netdevice(dev); 640 if (data && data[IFLA_IPVLAN_MODE])
626 if (err < 0) 641 mode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
627 goto remove_ida;
628 642
629 err = netdev_upper_dev_link(phy_dev, dev, extack);
630 if (err) {
631 goto unregister_netdev;
632 }
633 err = ipvlan_set_port_mode(port, mode); 643 err = ipvlan_set_port_mode(port, mode);
634 if (err) { 644 if (err)
635 goto unlink_netdev; 645 goto unlink_netdev;
636 }
637 646
638 list_add_tail_rcu(&ipvlan->pnode, &port->ipvlans); 647 list_add_tail_rcu(&ipvlan->pnode, &port->ipvlans);
639 netif_stacked_transfer_operstate(phy_dev, dev); 648 netif_stacked_transfer_operstate(phy_dev, dev);
@@ -641,13 +650,10 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
641 650
642unlink_netdev: 651unlink_netdev:
643 netdev_upper_dev_unlink(phy_dev, dev); 652 netdev_upper_dev_unlink(phy_dev, dev);
644unregister_netdev:
645 unregister_netdevice(dev);
646remove_ida: 653remove_ida:
647 ida_simple_remove(&port->ida, dev->dev_id); 654 ida_simple_remove(&port->ida, dev->dev_id);
648destroy_ipvlan_port: 655unregister_netdev:
649 if (create) 656 unregister_netdevice(dev);
650 ipvlan_port_destroy(phy_dev);
651 return err; 657 return err;
652} 658}
653EXPORT_SYMBOL_GPL(ipvlan_link_new); 659EXPORT_SYMBOL_GPL(ipvlan_link_new);