diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 9ff1333f8..79e827303 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc. + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -773,10 +773,28 @@ netdev_linux_alloc(void) return &netdev->up; } -static void -netdev_linux_common_construct(struct netdev_linux *netdev) +static int +netdev_linux_common_construct(struct netdev *netdev_) { + /* Prevent any attempt to create (or open) a network device named "default" + * or "all". These device names are effectively reserved on Linux because + * /proc/sys/net/ipv4/conf/ always contains directories by these names. By + * itself this wouldn't call for any special treatment, but in practice if + * a program tries to create devices with these names, it causes the kernel + * to fire a "new device" notification event even though creation failed, + * and in turn that causes OVS to wake up and try to create them again, + * which ends up as a 100% CPU loop. */ + struct netdev_linux *netdev = netdev_linux_cast(netdev_); + const char *name = netdev_->name; + if (!strcmp(name, "default") || !strcmp(name, "all")) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "%s: Linux forbids network device with this name", + name); + return EINVAL; + } + ovs_mutex_init(&netdev->mutex); + return 0; } /* Creates system and internal devices. */ @@ -784,9 +802,10 @@ static int netdev_linux_construct(struct netdev *netdev_) { struct netdev_linux *netdev = netdev_linux_cast(netdev_); - int error; - - netdev_linux_common_construct(netdev); + int error = netdev_linux_common_construct(netdev_); + if (error) { + return error; + } error = get_flags(&netdev->up, &netdev->ifi_flags); if (error == ENODEV) { @@ -817,9 +836,11 @@ netdev_linux_construct_tap(struct netdev *netdev_) static const char tap_dev[] = "/dev/net/tun"; const char *name = netdev_->name; struct ifreq ifr; - int error; - netdev_linux_common_construct(netdev); + int error = netdev_linux_common_construct(netdev_); + if (error) { + return error; + } /* Open tap device. */ netdev->tap_fd = open(tap_dev, O_RDWR);