lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Mon, 29 Jan 2007 18:48:06 +0100 (CET)
From:	Jiri Benc <jbenc@...e.cz>
To:	netdev@...r.kernel.org
Cc:	"John W. Linville" <linville@...driver.com>,
	Stephen Hemminger <shemminger@...l.org>,
	David Miller <davem@...emloft.net>
Subject: [RFC PATCH 1/6] invisible network devices

The d80211 stack needs a network interface (called 'wmaster') used for
communication with the hardware (it has 802.11 qdisc attached which perform
MAC level QoS). This interface is not intended for users and it confuses
them.

As a short time solution, this patch allows net_device to be registered as
"invisible". This means it is not in the dev name hash list, its ifindex is
-1 and protocols are not notified about its registration/unregistration.

Signed-off-by: Jiri Benc <jbenc@...e.cz>

---
 include/linux/netdevice.h |    2 
 net/core/dev.c            |  223 ++++++++++++++++++++++++++++++----------------
 2 files changed, 151 insertions(+), 74 deletions(-)

--- dscape.orig/include/linux/netdevice.h
+++ dscape/include/linux/netdevice.h
@@ -975,6 +975,8 @@ extern struct net_device *alloc_netdev(i
 				       void (*setup)(struct net_device *));
 extern int		register_netdev(struct net_device *dev);
 extern void		unregister_netdev(struct net_device *dev);
+extern int		register_invisible_netdevice(struct net_device *dev);
+extern void		unregister_invisible_netdevice(struct net_device *dev);
 /* Functions used for multicast support */
 extern void		dev_mc_upload(struct net_device *dev);
 extern int 		dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
--- dscape.orig/net/core/dev.c
+++ dscape/net/core/dev.c
@@ -2891,37 +2891,10 @@ static inline void net_set_todo(struct n
 	spin_unlock(&net_todo_list_lock);
 }
 
-/**
- *	register_netdevice	- register a network device
- *	@dev: device to register
- *
- *	Take a completed network device structure and add it to the kernel
- *	interfaces. A %NETDEV_REGISTER message is sent to the netdev notifier
- *	chain. 0 is returned on success. A negative errno code is returned
- *	on a failure to set up the device, or if the name is a duplicate.
- *
- *	Callers must hold the rtnl semaphore. You may want
- *	register_netdev() instead of this.
- *
- *	BUGS:
- *	The locking appears insufficient to guarantee two parallel registers
- *	will not get the same name.
- */
-
-int register_netdevice(struct net_device *dev)
+static int init_netdevice(struct net_device *dev)
 {
-	struct hlist_head *head;
-	struct hlist_node *p;
 	int ret;
 
-	BUG_ON(dev_boot_phase);
-	ASSERT_RTNL();
-
-	might_sleep();
-
-	/* When net_device's are persistent, this will be fatal. */
-	BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
-
 	spin_lock_init(&dev->queue_lock);
 	spin_lock_init(&dev->_xmit_lock);
 	dev->xmit_lock_owner = -1;
@@ -2929,7 +2902,7 @@ int register_netdevice(struct net_device
 	spin_lock_init(&dev->ingress_lock);
 #endif
 
-	dev->iflink = -1;
+	dev->iflink = dev->ifindex = -1;
 
 	/* Init, if this function is available */
 	if (dev->init) {
@@ -2940,27 +2913,13 @@ int register_netdevice(struct net_device
 			goto out;
 		}
 	}
- 
-	if (!dev_valid_name(dev->name)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	dev->ifindex = dev_new_index();
-	if (dev->iflink == -1)
-		dev->iflink = dev->ifindex;
-
-	/* Check for existence of name */
-	head = dev_name_hash(dev->name);
-	hlist_for_each(p, head) {
-		struct net_device *d
-			= hlist_entry(p, struct net_device, name_hlist);
-		if (!strncmp(d->name, dev->name, IFNAMSIZ)) {
-			ret = -EEXIST;
- 			goto out;
-		}
- 	}
+	ret = 0;
+out:
+	return ret;
+}
 
+static void setup_netdevice(struct net_device *dev)
+{
 	/* Fix illegal SG+CSUM combinations. */
 	if ((dev->features & NETIF_F_SG) &&
 	    !(dev->features & NETIF_F_ALL_CSUM)) {
@@ -2999,17 +2958,75 @@ int register_netdevice(struct net_device
 	if (!dev->rebuild_header)
 		dev->rebuild_header = default_rebuild_header;
 
-	ret = netdev_register_sysfs(dev);
-	if (ret)
-		goto out;
-	dev->reg_state = NETREG_REGISTERED;
-
 	/*
 	 *	Default initial state at registry is that the
 	 *	device is present.
 	 */
 
 	set_bit(__LINK_STATE_PRESENT, &dev->state);
+}
+
+/**
+ *	register_netdevice	- register a network device
+ *	@dev: device to register
+ *
+ *	Take a completed network device structure and add it to the kernel
+ *	interfaces. A %NETDEV_REGISTER message is sent to the netdev notifier
+ *	chain. 0 is returned on success. A negative errno code is returned
+ *	on a failure to set up the device, or if the name is a duplicate.
+ *
+ *	Callers must hold the rtnl semaphore. You may want
+ *	register_netdev() instead of this.
+ *
+ *	BUGS:
+ *	The locking appears insufficient to guarantee two parallel registers
+ *	will not get the same name.
+ */
+
+int register_netdevice(struct net_device *dev)
+{
+	struct hlist_head *head;
+	struct hlist_node *p;
+	int ret;
+
+	BUG_ON(dev_boot_phase);
+	ASSERT_RTNL();
+
+	might_sleep();
+
+	/* When net_device's are persistent, this will be fatal. */
+	BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
+
+	ret = init_netdevice(dev);
+	if (ret)
+		goto out;
+
+	if (!dev_valid_name(dev->name)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	dev->ifindex = dev_new_index();
+	if (dev->iflink == -1)
+		dev->iflink = dev->ifindex;
+
+	/* Check for existence of name */
+	head = dev_name_hash(dev->name);
+	hlist_for_each(p, head) {
+		struct net_device *d
+			= hlist_entry(p, struct net_device, name_hlist);
+		if (!strncmp(d->name, dev->name, IFNAMSIZ)) {
+			ret = -EEXIST;
+ 			goto out;
+		}
+ 	}
+
+	ret = netdev_register_sysfs(dev);
+	if (ret)
+		goto out;
+
+	setup_netdevice(dev);
+	dev->reg_state = NETREG_REGISTERED;
 
 	dev->next = NULL;
 	dev_init_scheduler(dev);
@@ -3030,6 +3047,31 @@ out:
 	return ret;
 }
 
+int register_invisible_netdevice(struct net_device *dev)
+{
+	int ret;
+
+	BUG_ON(dev_boot_phase);
+	might_sleep();
+	BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
+
+	ret = init_netdevice(dev);
+	if (ret)
+		goto out;
+
+	setup_netdevice(dev);
+	dev->reg_state = NETREG_REGISTERED;
+
+	dev->next = NULL;
+	dev_init_scheduler(dev);
+	dev_hold(dev);
+
+	ret = 0;
+out:
+	return ret;
+}
+EXPORT_SYMBOL(register_invisible_netdevice);
+
 /**
  *	register_netdev	- register a network device
  *	@dev: device to register
@@ -3118,6 +3160,23 @@ static void netdev_wait_allrefs(struct n
 	}
 }
 
+static void destruct_netdevice(struct net_device *dev)
+{
+	netdev_wait_allrefs(dev);
+
+	/* paranoia */
+	BUG_ON(atomic_read(&dev->refcnt));
+	BUG_TRAP(!dev->ip_ptr);
+	BUG_TRAP(!dev->ip6_ptr);
+	BUG_TRAP(!dev->dn_ptr);
+
+	/* It must be the very last action,
+	 * after this 'dev' may point to freed up memory.
+	 */
+	if (dev->destructor)
+		dev->destructor(dev);
+}
+
 /* The sequence is:
  *
  *	rtnl_lock();
@@ -3175,19 +3234,7 @@ void netdev_run_todo(void)
 		netdev_unregister_sysfs(dev);
 		dev->reg_state = NETREG_UNREGISTERED;
 
-		netdev_wait_allrefs(dev);
-
-		/* paranoia */
-		BUG_ON(atomic_read(&dev->refcnt));
-		BUG_TRAP(!dev->ip_ptr);
-		BUG_TRAP(!dev->ip6_ptr);
-		BUG_TRAP(!dev->dn_ptr);
-
-		/* It must be the very last action,
-		 * after this 'dev' may point to freed up memory.
-		 */
-		if (dev->destructor)
-			dev->destructor(dev);
+		destruct_netdevice(dev);
 	}
 
 out:
@@ -3269,6 +3316,17 @@ void synchronize_net(void) 
 	synchronize_rcu();
 }
 
+static void uninit_netdevice(struct net_device *dev)
+{
+	/*
+	 *	Flush the multicast chain
+	 */
+	dev_mc_discard(dev);
+
+	if (dev->uninit)
+		dev->uninit(dev);
+}
+
 /**
  *	unregister_netdevice - remove device from the kernel
  *	@dev: device
@@ -3332,14 +3390,8 @@ int unregister_netdevice(struct net_devi
 	   this device. They should clean all the things.
 	*/
 	raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
-	
-	/*
-	 *	Flush the multicast chain
-	 */
-	dev_mc_discard(dev);
 
-	if (dev->uninit)
-		dev->uninit(dev);
+	uninit_netdevice(dev);
 
 	/* Notifier chain MUST detach us from master device. */
 	BUG_TRAP(!dev->master);
@@ -3353,6 +3405,29 @@ int unregister_netdevice(struct net_devi
 	return 0;
 }
 
+void unregister_invisible_netdevice(struct net_device *dev)
+{
+	BUG_ON(dev_boot_phase);
+	BUG_ON(dev->reg_state != NETREG_REGISTERED);
+	might_sleep();
+
+	dev_close(dev);
+	dev->reg_state = NETREG_UNREGISTERING;
+	synchronize_net();
+	dev_shutdown(dev);
+
+	uninit_netdevice(dev);
+
+	BUG_TRAP(!dev->master);
+
+	synchronize_net();
+	dev_put(dev);
+
+	dev->reg_state = NETREG_UNREGISTERED;
+	destruct_netdevice(dev);
+}
+EXPORT_SYMBOL(unregister_invisible_netdevice);
+
 /**
  *	unregister_netdev - remove device from the kernel
  *	@dev: device

-- 
Jiri Benc
SUSE Labs
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ