Эх сурвалжийг харах

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (27 commits)
  af_unix: limit recursion level
  pch_gbe driver: The wrong of initializer entry
  pch_gbe dreiver: chang author
  ucc_geth: fix ucc halt problem in half duplex mode
  inet: Fix __inet_inherit_port() to correctly increment bsockets and num_owners
  ehea: Add some info messages and fix an issue
  hso: fix disable_net
  NET: wan/x25_asy, move lapb_unregister to x25_asy_close_tty
  cxgb4vf: fix setting unicast/multicast addresses ...
  net, ppp: Report correct error code if unit allocation failed
  DECnet: don't leak uninitialized stack byte
  au1000_eth: fix invalid address accessing the MAC enable register
  dccp: fix error in updating the GAR
  tcp: restrict net.ipv4.tcp_adv_win_scale (#20312)
  netns: Don't leak others' openreq-s in proc
  Net: ceph: Makefile: Remove unnessary code
  vhost/net: fix rcu check usage
  econet: fix CVE-2010-3848
  econet: fix CVE-2010-3850
  econet: disallow NULL remote addr for sendmsg(), fixes CVE-2010-3849
  ...
Linus Torvalds 14 жил өмнө
parent
commit
a01af8e4a4

+ 1 - 0
Documentation/networking/ip-sysctl.txt

@@ -144,6 +144,7 @@ tcp_adv_win_scale - INTEGER
 	Count buffering overhead as bytes/2^tcp_adv_win_scale
 	Count buffering overhead as bytes/2^tcp_adv_win_scale
 	(if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
 	(if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
 	if it is <= 0.
 	if it is <= 0.
+	Possible values are [-31, 31], inclusive.
 	Default: 2
 	Default: 2
 
 
 tcp_allowed_congestion_control - STRING
 tcp_allowed_congestion_control - STRING

+ 4 - 3
drivers/isdn/icn/icn.c

@@ -1627,7 +1627,7 @@ __setup("icn=", icn_setup);
 static int __init icn_init(void)
 static int __init icn_init(void)
 {
 {
 	char *p;
 	char *p;
-	char rev[10];
+	char rev[20];
 
 
 	memset(&dev, 0, sizeof(icn_dev));
 	memset(&dev, 0, sizeof(icn_dev));
 	dev.memaddr = (membase & 0x0ffc000);
 	dev.memaddr = (membase & 0x0ffc000);
@@ -1637,9 +1637,10 @@ static int __init icn_init(void)
 	spin_lock_init(&dev.devlock);
 	spin_lock_init(&dev.devlock);
 
 
 	if ((p = strchr(revision, ':'))) {
 	if ((p = strchr(revision, ':'))) {
-		strcpy(rev, p + 1);
+		strncpy(rev, p + 1, 20);
 		p = strchr(rev, '$');
 		p = strchr(rev, '$');
-		*p = 0;
+		if (p)
+			*p = 0;
 	} else
 	} else
 		strcpy(rev, " ??? ");
 		strcpy(rev, " ??? ");
 	printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,
 	printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,

+ 3 - 3
drivers/net/Kconfig

@@ -2543,10 +2543,10 @@ config PCH_GBE
 	depends on PCI
 	depends on PCI
 	select MII
 	select MII
 	---help---
 	---help---
-	  This is a gigabit ethernet driver for Topcliff PCH.
-	  Topcliff PCH is the platform controller hub that is used in Intel's
+	  This is a gigabit ethernet driver for EG20T PCH.
+	  EG20T PCH is the platform controller hub that is used in Intel's
 	  general embedded platform.
 	  general embedded platform.
-	  Topcliff PCH has Gigabit Ethernet interface.
+	  EG20T PCH has Gigabit Ethernet interface.
 	  Using this interface, it is able to access system devices connected
 	  Using this interface, it is able to access system devices connected
 	  to Gigabit Ethernet.
 	  to Gigabit Ethernet.
 	  This driver enables Gigabit Ethernet function.
 	  This driver enables Gigabit Ethernet function.

+ 5 - 5
drivers/net/au1000_eth.c

@@ -155,10 +155,10 @@ static void au1000_enable_mac(struct net_device *dev, int force_reset)
 	spin_lock_irqsave(&aup->lock, flags);
 	spin_lock_irqsave(&aup->lock, flags);
 
 
 	if (force_reset || (!aup->mac_enabled)) {
 	if (force_reset || (!aup->mac_enabled)) {
-		writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
+		writel(MAC_EN_CLOCK_ENABLE, aup->enable);
 		au_sync_delay(2);
 		au_sync_delay(2);
 		writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
 		writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
-				| MAC_EN_CLOCK_ENABLE), &aup->enable);
+				| MAC_EN_CLOCK_ENABLE), aup->enable);
 		au_sync_delay(2);
 		au_sync_delay(2);
 
 
 		aup->mac_enabled = 1;
 		aup->mac_enabled = 1;
@@ -503,9 +503,9 @@ static void au1000_reset_mac_unlocked(struct net_device *dev)
 
 
 	au1000_hard_stop(dev);
 	au1000_hard_stop(dev);
 
 
-	writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
+	writel(MAC_EN_CLOCK_ENABLE, aup->enable);
 	au_sync_delay(2);
 	au_sync_delay(2);
-	writel(0, &aup->enable);
+	writel(0, aup->enable);
 	au_sync_delay(2);
 	au_sync_delay(2);
 
 
 	aup->tx_full = 0;
 	aup->tx_full = 0;
@@ -1119,7 +1119,7 @@ static int __devinit au1000_probe(struct platform_device *pdev)
 	/* set a random MAC now in case platform_data doesn't provide one */
 	/* set a random MAC now in case platform_data doesn't provide one */
 	random_ether_addr(dev->dev_addr);
 	random_ether_addr(dev->dev_addr);
 
 
-	writel(0, &aup->enable);
+	writel(0, aup->enable);
 	aup->mac_enabled = 0;
 	aup->mac_enabled = 0;
 
 
 	pd = pdev->dev.platform_data;
 	pd = pdev->dev.platform_data;

+ 45 - 28
drivers/net/cxgb4vf/cxgb4vf_main.c

@@ -816,40 +816,48 @@ static struct net_device_stats *cxgb4vf_get_stats(struct net_device *dev)
 }
 }
 
 
 /*
 /*
- * Collect up to maxaddrs worth of a netdevice's unicast addresses into an
- * array of addrss pointers and return the number collected.
+ * Collect up to maxaddrs worth of a netdevice's unicast addresses, starting
+ * at a specified offset within the list, into an array of addrss pointers and
+ * return the number collected.
  */
  */
-static inline int collect_netdev_uc_list_addrs(const struct net_device *dev,
-					       const u8 **addr,
-					       unsigned int maxaddrs)
+static inline unsigned int collect_netdev_uc_list_addrs(const struct net_device *dev,
+							const u8 **addr,
+							unsigned int offset,
+							unsigned int maxaddrs)
 {
 {
+	unsigned int index = 0;
 	unsigned int naddr = 0;
 	unsigned int naddr = 0;
 	const struct netdev_hw_addr *ha;
 	const struct netdev_hw_addr *ha;
 
 
-	for_each_dev_addr(dev, ha) {
-		addr[naddr++] = ha->addr;
-		if (naddr >= maxaddrs)
-			break;
-	}
+	for_each_dev_addr(dev, ha)
+		if (index++ >= offset) {
+			addr[naddr++] = ha->addr;
+			if (naddr >= maxaddrs)
+				break;
+		}
 	return naddr;
 	return naddr;
 }
 }
 
 
 /*
 /*
- * Collect up to maxaddrs worth of a netdevice's multicast addresses into an
- * array of addrss pointers and return the number collected.
+ * Collect up to maxaddrs worth of a netdevice's multicast addresses, starting
+ * at a specified offset within the list, into an array of addrss pointers and
+ * return the number collected.
  */
  */
-static inline int collect_netdev_mc_list_addrs(const struct net_device *dev,
-					       const u8 **addr,
-					       unsigned int maxaddrs)
+static inline unsigned int collect_netdev_mc_list_addrs(const struct net_device *dev,
+							const u8 **addr,
+							unsigned int offset,
+							unsigned int maxaddrs)
 {
 {
+	unsigned int index = 0;
 	unsigned int naddr = 0;
 	unsigned int naddr = 0;
 	const struct netdev_hw_addr *ha;
 	const struct netdev_hw_addr *ha;
 
 
-	netdev_for_each_mc_addr(ha, dev) {
-		addr[naddr++] = ha->addr;
-		if (naddr >= maxaddrs)
-			break;
-	}
+	netdev_for_each_mc_addr(ha, dev)
+		if (index++ >= offset) {
+			addr[naddr++] = ha->addr;
+			if (naddr >= maxaddrs)
+				break;
+		}
 	return naddr;
 	return naddr;
 }
 }
 
 
@@ -862,16 +870,20 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
 	u64 mhash = 0;
 	u64 mhash = 0;
 	u64 uhash = 0;
 	u64 uhash = 0;
 	bool free = true;
 	bool free = true;
-	u16 filt_idx[7];
+	unsigned int offset, naddr;
 	const u8 *addr[7];
 	const u8 *addr[7];
-	int ret, naddr = 0;
+	int ret;
 	const struct port_info *pi = netdev_priv(dev);
 	const struct port_info *pi = netdev_priv(dev);
 
 
 	/* first do the secondary unicast addresses */
 	/* first do the secondary unicast addresses */
-	naddr = collect_netdev_uc_list_addrs(dev, addr, ARRAY_SIZE(addr));
-	if (naddr > 0) {
+	for (offset = 0; ; offset += naddr) {
+		naddr = collect_netdev_uc_list_addrs(dev, addr, offset,
+						     ARRAY_SIZE(addr));
+		if (naddr == 0)
+			break;
+
 		ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
 		ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
-					  naddr, addr, filt_idx, &uhash, sleep);
+					  naddr, addr, NULL, &uhash, sleep);
 		if (ret < 0)
 		if (ret < 0)
 			return ret;
 			return ret;
 
 
@@ -879,12 +891,17 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
 	}
 	}
 
 
 	/* next set up the multicast addresses */
 	/* next set up the multicast addresses */
-	naddr = collect_netdev_mc_list_addrs(dev, addr, ARRAY_SIZE(addr));
-	if (naddr > 0) {
+	for (offset = 0; ; offset += naddr) {
+		naddr = collect_netdev_mc_list_addrs(dev, addr, offset,
+						     ARRAY_SIZE(addr));
+		if (naddr == 0)
+			break;
+
 		ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
 		ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
-					  naddr, addr, filt_idx, &mhash, sleep);
+					  naddr, addr, NULL, &mhash, sleep);
 		if (ret < 0)
 		if (ret < 0)
 			return ret;
 			return ret;
+		free = false;
 	}
 	}
 
 
 	return t4vf_set_addr_hash(pi->adapter, pi->viid, uhash != 0,
 	return t4vf_set_addr_hash(pi->adapter, pi->viid, uhash != 0,

+ 59 - 35
drivers/net/cxgb4vf/t4vf_hw.c

@@ -1014,48 +1014,72 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
 			unsigned int naddr, const u8 **addr, u16 *idx,
 			unsigned int naddr, const u8 **addr, u16 *idx,
 			u64 *hash, bool sleep_ok)
 			u64 *hash, bool sleep_ok)
 {
 {
-	int i, ret;
+	int offset, ret = 0;
+	unsigned nfilters = 0;
+	unsigned int rem = naddr;
 	struct fw_vi_mac_cmd cmd, rpl;
 	struct fw_vi_mac_cmd cmd, rpl;
-	struct fw_vi_mac_exact *p;
-	size_t len16;
 
 
-	if (naddr > ARRAY_SIZE(cmd.u.exact))
+	if (naddr > FW_CLS_TCAM_NUM_ENTRIES)
 		return -EINVAL;
 		return -EINVAL;
-	len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
-				      u.exact[naddr]), 16);
 
 
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
-				     FW_CMD_REQUEST |
-				     FW_CMD_WRITE |
-				     (free ? FW_CMD_EXEC : 0) |
-				     FW_VI_MAC_CMD_VIID(viid));
-	cmd.freemacs_to_len16 = cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
-					    FW_CMD_LEN16(len16));
+	for (offset = 0; offset < naddr; /**/) {
+		unsigned int fw_naddr = (rem < ARRAY_SIZE(cmd.u.exact)
+					 ? rem
+					 : ARRAY_SIZE(cmd.u.exact));
+		size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
+						     u.exact[fw_naddr]), 16);
+		struct fw_vi_mac_exact *p;
+		int i;
 
 
-	for (i = 0, p = cmd.u.exact; i < naddr; i++, p++) {
-		p->valid_to_idx =
-			cpu_to_be16(FW_VI_MAC_CMD_VALID |
-				    FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
-		memcpy(p->macaddr, addr[i], sizeof(p->macaddr));
-	}
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
+					     FW_CMD_REQUEST |
+					     FW_CMD_WRITE |
+					     (free ? FW_CMD_EXEC : 0) |
+					     FW_VI_MAC_CMD_VIID(viid));
+		cmd.freemacs_to_len16 =
+			cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
+				    FW_CMD_LEN16(len16));
+
+		for (i = 0, p = cmd.u.exact; i < fw_naddr; i++, p++) {
+			p->valid_to_idx = cpu_to_be16(
+				FW_VI_MAC_CMD_VALID |
+				FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
+			memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr));
+		}
+
+
+		ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl,
+					sleep_ok);
+		if (ret && ret != -ENOMEM)
+			break;
 
 
-	ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl, sleep_ok);
-	if (ret)
-		return ret;
-
-	for (i = 0, p = rpl.u.exact; i < naddr; i++, p++) {
-		u16 index = FW_VI_MAC_CMD_IDX_GET(be16_to_cpu(p->valid_to_idx));
-
-		if (idx)
-			idx[i] = (index >= FW_CLS_TCAM_NUM_ENTRIES
-				  ? 0xffff
-				  : index);
-		if (index < FW_CLS_TCAM_NUM_ENTRIES)
-			ret++;
-		else if (hash)
-			*hash |= (1 << hash_mac_addr(addr[i]));
+		for (i = 0, p = rpl.u.exact; i < fw_naddr; i++, p++) {
+			u16 index = FW_VI_MAC_CMD_IDX_GET(
+				be16_to_cpu(p->valid_to_idx));
+
+			if (idx)
+				idx[offset+i] =
+					(index >= FW_CLS_TCAM_NUM_ENTRIES
+					 ? 0xffff
+					 : index);
+			if (index < FW_CLS_TCAM_NUM_ENTRIES)
+				nfilters++;
+			else if (hash)
+				*hash |= (1ULL << hash_mac_addr(addr[offset+i]));
+		}
+
+		free = false;
+		offset += fw_naddr;
+		rem -= fw_naddr;
 	}
 	}
+
+	/*
+	 * If there were no errors or we merely ran out of room in our MAC
+	 * address arena, return the number of filters actually written.
+	 */
+	if (ret == 0 || ret == -ENOMEM)
+		ret = nfilters;
 	return ret;
 	return ret;
 }
 }
 
 

+ 14 - 4
drivers/net/ehea/ehea_main.c

@@ -400,6 +400,7 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
 			skb_arr_rq1[index] = netdev_alloc_skb(dev,
 			skb_arr_rq1[index] = netdev_alloc_skb(dev,
 							      EHEA_L_PKT_SIZE);
 							      EHEA_L_PKT_SIZE);
 			if (!skb_arr_rq1[index]) {
 			if (!skb_arr_rq1[index]) {
+				ehea_info("Unable to allocate enough skb in the array\n");
 				pr->rq1_skba.os_skbs = fill_wqes - i;
 				pr->rq1_skba.os_skbs = fill_wqes - i;
 				break;
 				break;
 			}
 			}
@@ -422,13 +423,20 @@ static void ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
 	struct net_device *dev = pr->port->netdev;
 	struct net_device *dev = pr->port->netdev;
 	int i;
 	int i;
 
 
-	for (i = 0; i < pr->rq1_skba.len; i++) {
+	if (nr_rq1a > pr->rq1_skba.len) {
+		ehea_error("NR_RQ1A bigger than skb array len\n");
+		return;
+	}
+
+	for (i = 0; i < nr_rq1a; i++) {
 		skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
 		skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
-		if (!skb_arr_rq1[i])
+		if (!skb_arr_rq1[i]) {
+			ehea_info("No enough memory to allocate skb array\n");
 			break;
 			break;
+		}
 	}
 	}
 	/* Ring doorbell */
 	/* Ring doorbell */
-	ehea_update_rq1a(pr->qp, nr_rq1a);
+	ehea_update_rq1a(pr->qp, i);
 }
 }
 
 
 static int ehea_refill_rq_def(struct ehea_port_res *pr,
 static int ehea_refill_rq_def(struct ehea_port_res *pr,
@@ -735,8 +743,10 @@ static int ehea_proc_rwqes(struct net_device *dev,
 
 
 					skb = netdev_alloc_skb(dev,
 					skb = netdev_alloc_skb(dev,
 							       EHEA_L_PKT_SIZE);
 							       EHEA_L_PKT_SIZE);
-					if (!skb)
+					if (!skb) {
+						ehea_info("Not enough memory to allocate skb\n");
 						break;
 						break;
+					}
 				}
 				}
 				skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
 				skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
 						 cqe->num_bytes_transfered - 4);
 						 cqe->num_bytes_transfered - 4);

+ 3 - 3
drivers/net/pch_gbe/pch_gbe_main.c

@@ -1,6 +1,6 @@
 /*
 /*
  * Copyright (C) 1999 - 2010 Intel Corporation.
  * Copyright (C) 1999 - 2010 Intel Corporation.
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
  *
  *
  * This code was derived from the Intel e1000e Linux driver.
  * This code was derived from the Intel e1000e Linux driver.
  *
  *
@@ -2464,8 +2464,8 @@ static void __exit pch_gbe_exit_module(void)
 module_init(pch_gbe_init_module);
 module_init(pch_gbe_init_module);
 module_exit(pch_gbe_exit_module);
 module_exit(pch_gbe_exit_module);
 
 
-MODULE_DESCRIPTION("OKI semiconductor PCH Gigabit ethernet Driver");
-MODULE_AUTHOR("OKI semiconductor, <masa-korg@dsn.okisemi.com>");
+MODULE_DESCRIPTION("EG20T PCH Gigabit ethernet Driver");
+MODULE_AUTHOR("OKI SEMICONDUCTOR, <toshiharu-linux@dsn.okisemi.com>");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, pch_gbe_pcidev_id);
 MODULE_DEVICE_TABLE(pci, pch_gbe_pcidev_id);

+ 4 - 4
drivers/net/pch_gbe/pch_gbe_param.c

@@ -434,8 +434,8 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
 			.err  = "using default of "
 			.err  = "using default of "
 				__MODULE_STRING(PCH_GBE_DEFAULT_TXD),
 				__MODULE_STRING(PCH_GBE_DEFAULT_TXD),
 			.def  = PCH_GBE_DEFAULT_TXD,
 			.def  = PCH_GBE_DEFAULT_TXD,
-			.arg  = { .r = { .min = PCH_GBE_MIN_TXD } },
-			.arg  = { .r = { .max = PCH_GBE_MAX_TXD } }
+			.arg  = { .r = { .min = PCH_GBE_MIN_TXD,
+					 .max = PCH_GBE_MAX_TXD } }
 		};
 		};
 		struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
 		struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
 		tx_ring->count = TxDescriptors;
 		tx_ring->count = TxDescriptors;
@@ -450,8 +450,8 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
 			.err  = "using default of "
 			.err  = "using default of "
 				__MODULE_STRING(PCH_GBE_DEFAULT_RXD),
 				__MODULE_STRING(PCH_GBE_DEFAULT_RXD),
 			.def  = PCH_GBE_DEFAULT_RXD,
 			.def  = PCH_GBE_DEFAULT_RXD,
-			.arg  = { .r = { .min = PCH_GBE_MIN_RXD } },
-			.arg  = { .r = { .max = PCH_GBE_MAX_RXD } }
+			.arg  = { .r = { .min = PCH_GBE_MIN_RXD,
+					 .max = PCH_GBE_MAX_RXD } }
 		};
 		};
 		struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
 		struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
 		rx_ring->count = RxDescriptors;
 		rx_ring->count = RxDescriptors;

+ 22 - 21
drivers/net/ppp_generic.c

@@ -2584,16 +2584,16 @@ ppp_create_interface(struct net *net, int unit, int *retp)
 	 */
 	 */
 	dev_net_set(dev, net);
 	dev_net_set(dev, net);
 
 
-	ret = -EEXIST;
 	mutex_lock(&pn->all_ppp_mutex);
 	mutex_lock(&pn->all_ppp_mutex);
 
 
 	if (unit < 0) {
 	if (unit < 0) {
 		unit = unit_get(&pn->units_idr, ppp);
 		unit = unit_get(&pn->units_idr, ppp);
 		if (unit < 0) {
 		if (unit < 0) {
-			*retp = unit;
+			ret = unit;
 			goto out2;
 			goto out2;
 		}
 		}
 	} else {
 	} else {
+		ret = -EEXIST;
 		if (unit_find(&pn->units_idr, unit))
 		if (unit_find(&pn->units_idr, unit))
 			goto out2; /* unit already exists */
 			goto out2; /* unit already exists */
 		/*
 		/*
@@ -2668,10 +2668,10 @@ static void ppp_shutdown_interface(struct ppp *ppp)
 		ppp->closing = 1;
 		ppp->closing = 1;
 		ppp_unlock(ppp);
 		ppp_unlock(ppp);
 		unregister_netdev(ppp->dev);
 		unregister_netdev(ppp->dev);
+		unit_put(&pn->units_idr, ppp->file.index);
 	} else
 	} else
 		ppp_unlock(ppp);
 		ppp_unlock(ppp);
 
 
-	unit_put(&pn->units_idr, ppp->file.index);
 	ppp->file.dead = 1;
 	ppp->file.dead = 1;
 	ppp->owner = NULL;
 	ppp->owner = NULL;
 	wake_up_interruptible(&ppp->file.rwait);
 	wake_up_interruptible(&ppp->file.rwait);
@@ -2859,8 +2859,7 @@ static void __exit ppp_cleanup(void)
  * by holding all_ppp_mutex
  * by holding all_ppp_mutex
  */
  */
 
 
-/* associate pointer with specified number */
-static int unit_set(struct idr *p, void *ptr, int n)
+static int __unit_alloc(struct idr *p, void *ptr, int n)
 {
 {
 	int unit, err;
 	int unit, err;
 
 
@@ -2871,10 +2870,24 @@ again:
 	}
 	}
 
 
 	err = idr_get_new_above(p, ptr, n, &unit);
 	err = idr_get_new_above(p, ptr, n, &unit);
-	if (err == -EAGAIN)
-		goto again;
+	if (err < 0) {
+		if (err == -EAGAIN)
+			goto again;
+		return err;
+	}
+
+	return unit;
+}
+
+/* associate pointer with specified number */
+static int unit_set(struct idr *p, void *ptr, int n)
+{
+	int unit;
 
 
-	if (unit != n) {
+	unit = __unit_alloc(p, ptr, n);
+	if (unit < 0)
+		return unit;
+	else if (unit != n) {
 		idr_remove(p, unit);
 		idr_remove(p, unit);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
@@ -2885,19 +2898,7 @@ again:
 /* get new free unit number and associate pointer with it */
 /* get new free unit number and associate pointer with it */
 static int unit_get(struct idr *p, void *ptr)
 static int unit_get(struct idr *p, void *ptr)
 {
 {
-	int unit, err;
-
-again:
-	if (!idr_pre_get(p, GFP_KERNEL)) {
-		printk(KERN_ERR "PPP: No free memory for idr\n");
-		return -ENOMEM;
-	}
-
-	err = idr_get_new_above(p, ptr, 0, &unit);
-	if (err == -EAGAIN)
-		goto again;
-
-	return unit;
+	return __unit_alloc(p, ptr, 0);
 }
 }
 
 
 /* put unit number back to a pool */
 /* put unit number back to a pool */

+ 2 - 1
drivers/net/ucc_geth.h

@@ -899,7 +899,8 @@ struct ucc_geth_hardware_statistics {
 #define UCC_GETH_UTFS_INIT                      512	/* Tx virtual FIFO size
 #define UCC_GETH_UTFS_INIT                      512	/* Tx virtual FIFO size
 							 */
 							 */
 #define UCC_GETH_UTFET_INIT                     256	/* 1/2 utfs */
 #define UCC_GETH_UTFET_INIT                     256	/* 1/2 utfs */
-#define UCC_GETH_UTFTT_INIT                     512
+#define UCC_GETH_UTFTT_INIT                     256	/* 1/2 utfs
+							   due to errata */
 /* Gigabit Ethernet (1000 Mbps) */
 /* Gigabit Ethernet (1000 Mbps) */
 #define UCC_GETH_URFS_GIGA_INIT                 4096/*2048*/	/* Rx virtual
 #define UCC_GETH_URFS_GIGA_INIT                 4096/*2048*/	/* Rx virtual
 								   FIFO size */
 								   FIFO size */

+ 6 - 4
drivers/net/usb/hso.c

@@ -2994,12 +2994,14 @@ static int hso_probe(struct usb_interface *interface,
 
 
 	case HSO_INTF_BULK:
 	case HSO_INTF_BULK:
 		/* It's a regular bulk interface */
 		/* It's a regular bulk interface */
-		if (((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) &&
-		    !disable_net)
-			hso_dev = hso_create_net_device(interface, port_spec);
-		else
+		if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) {
+			if (!disable_net)
+				hso_dev =
+				    hso_create_net_device(interface, port_spec);
+		} else {
 			hso_dev =
 			hso_dev =
 			    hso_create_bulk_serial_device(interface, port_spec);
 			    hso_create_bulk_serial_device(interface, port_spec);
+		}
 		if (!hso_dev)
 		if (!hso_dev)
 			goto exit;
 			goto exit;
 		break;
 		break;

+ 6 - 5
drivers/net/wan/x25_asy.c

@@ -498,7 +498,6 @@ norbuff:
 static int x25_asy_close(struct net_device *dev)
 static int x25_asy_close(struct net_device *dev)
 {
 {
 	struct x25_asy *sl = netdev_priv(dev);
 	struct x25_asy *sl = netdev_priv(dev);
-	int err;
 
 
 	spin_lock(&sl->lock);
 	spin_lock(&sl->lock);
 	if (sl->tty)
 	if (sl->tty)
@@ -507,10 +506,6 @@ static int x25_asy_close(struct net_device *dev)
 	netif_stop_queue(dev);
 	netif_stop_queue(dev);
 	sl->rcount = 0;
 	sl->rcount = 0;
 	sl->xleft  = 0;
 	sl->xleft  = 0;
-	err = lapb_unregister(dev);
-	if (err != LAPB_OK)
-		printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
-			err);
 	spin_unlock(&sl->lock);
 	spin_unlock(&sl->lock);
 	return 0;
 	return 0;
 }
 }
@@ -595,6 +590,7 @@ static int x25_asy_open_tty(struct tty_struct *tty)
 static void x25_asy_close_tty(struct tty_struct *tty)
 static void x25_asy_close_tty(struct tty_struct *tty)
 {
 {
 	struct x25_asy *sl = tty->disc_data;
 	struct x25_asy *sl = tty->disc_data;
+	int err;
 
 
 	/* First make sure we're connected. */
 	/* First make sure we're connected. */
 	if (!sl || sl->magic != X25_ASY_MAGIC)
 	if (!sl || sl->magic != X25_ASY_MAGIC)
@@ -605,6 +601,11 @@ static void x25_asy_close_tty(struct tty_struct *tty)
 		dev_close(sl->dev);
 		dev_close(sl->dev);
 	rtnl_unlock();
 	rtnl_unlock();
 
 
+	err = lapb_unregister(sl->dev);
+	if (err != LAPB_OK)
+		printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
+			err);
+
 	tty->disc_data = NULL;
 	tty->disc_data = NULL;
 	sl->tty = NULL;
 	sl->tty = NULL;
 	x25_asy_free(sl);
 	x25_asy_free(sl);

+ 1 - 1
drivers/net/wireless/ath/ath9k/recv.c

@@ -518,7 +518,7 @@ bool ath_stoprecv(struct ath_softc *sc)
 	bool stopped;
 	bool stopped;
 
 
 	spin_lock_bh(&sc->rx.rxbuflock);
 	spin_lock_bh(&sc->rx.rxbuflock);
-	ath9k_hw_stoppcurecv(ah);
+	ath9k_hw_abortpcurecv(ah);
 	ath9k_hw_setrxfilter(ah, 0);
 	ath9k_hw_setrxfilter(ah, 0);
 	stopped = ath9k_hw_stopdmarecv(ah);
 	stopped = ath9k_hw_stopdmarecv(ah);
 
 

+ 1 - 1
drivers/net/wireless/ath/carl9170/main.c

@@ -647,7 +647,7 @@ init:
 	}
 	}
 
 
 unlock:
 unlock:
-	if (err && (vif_id != -1)) {
+	if (err && (vif_id >= 0)) {
 		vif_priv->active = false;
 		vif_priv->active = false;
 		bitmap_release_region(&ar->vif_bitmap, vif_id, 0);
 		bitmap_release_region(&ar->vif_bitmap, vif_id, 0);
 		ar->vifs--;
 		ar->vifs--;

+ 1 - 0
drivers/net/wireless/b43/sdio.c

@@ -163,6 +163,7 @@ static int b43_sdio_probe(struct sdio_func *func,
 err_free_ssb:
 err_free_ssb:
 	kfree(sdio);
 	kfree(sdio);
 err_disable_func:
 err_disable_func:
+	sdio_claim_host(func);
 	sdio_disable_func(func);
 	sdio_disable_func(func);
 err_release_host:
 err_release_host:
 	sdio_release_host(func);
 	sdio_release_host(func);

+ 1 - 0
drivers/ssb/b43_pci_bridge.c

@@ -24,6 +24,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4315) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4315) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BCM_GVC,  0x4318) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },

+ 3 - 2
drivers/vhost/net.c

@@ -129,8 +129,9 @@ static void handle_tx(struct vhost_net *net)
 	size_t hdr_size;
 	size_t hdr_size;
 	struct socket *sock;
 	struct socket *sock;
 
 
-	sock = rcu_dereference_check(vq->private_data,
-				     lockdep_is_held(&vq->mutex));
+	/* TODO: check that we are running from vhost_worker?
+	 * Not sure it's worth it, it's straight-forward enough. */
+	sock = rcu_dereference_check(vq->private_data, 1);
 	if (!sock)
 	if (!sock)
 		return;
 		return;
 
 

+ 1 - 0
include/linux/pci_ids.h

@@ -2047,6 +2047,7 @@
 #define PCI_DEVICE_ID_AFAVLAB_P030	0x2182
 #define PCI_DEVICE_ID_AFAVLAB_P030	0x2182
 #define PCI_SUBDEVICE_ID_AFAVLAB_P061		0x2150
 #define PCI_SUBDEVICE_ID_AFAVLAB_P061		0x2150
 
 
+#define PCI_VENDOR_ID_BCM_GVC          0x14a4
 #define PCI_VENDOR_ID_BROADCOM		0x14e4
 #define PCI_VENDOR_ID_BROADCOM		0x14e4
 #define PCI_DEVICE_ID_TIGON3_5752	0x1600
 #define PCI_DEVICE_ID_TIGON3_5752	0x1600
 #define PCI_DEVICE_ID_TIGON3_5752M	0x1601
 #define PCI_DEVICE_ID_TIGON3_5752M	0x1601

+ 2 - 0
include/net/af_unix.h

@@ -10,6 +10,7 @@ extern void unix_inflight(struct file *fp);
 extern void unix_notinflight(struct file *fp);
 extern void unix_notinflight(struct file *fp);
 extern void unix_gc(void);
 extern void unix_gc(void);
 extern void wait_for_unix_gc(void);
 extern void wait_for_unix_gc(void);
+extern struct sock *unix_get_socket(struct file *filp);
 
 
 #define UNIX_HASH_SIZE	256
 #define UNIX_HASH_SIZE	256
 
 
@@ -56,6 +57,7 @@ struct unix_sock {
 	spinlock_t		lock;
 	spinlock_t		lock;
 	unsigned int		gc_candidate : 1;
 	unsigned int		gc_candidate : 1;
 	unsigned int		gc_maybe_cycle : 1;
 	unsigned int		gc_maybe_cycle : 1;
+	unsigned char		recursion_level;
 	struct socket_wq	peer_wq;
 	struct socket_wq	peer_wq;
 };
 };
 #define unix_sk(__sk) ((struct unix_sock *)__sk)
 #define unix_sk(__sk) ((struct unix_sock *)__sk)

+ 0 - 22
net/ceph/Makefile

@@ -1,9 +1,6 @@
 #
 #
 # Makefile for CEPH filesystem.
 # Makefile for CEPH filesystem.
 #
 #
-
-ifneq ($(KERNELRELEASE),)
-
 obj-$(CONFIG_CEPH_LIB) += libceph.o
 obj-$(CONFIG_CEPH_LIB) += libceph.o
 
 
 libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
 libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
@@ -16,22 +13,3 @@ libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
 	ceph_fs.o ceph_strings.o ceph_hash.o \
 	ceph_fs.o ceph_strings.o ceph_hash.o \
 	pagevec.o
 	pagevec.o
 
 
-else
-#Otherwise we were called directly from the command
-# line; invoke the kernel build system.
-
-KERNELDIR ?= /lib/modules/$(shell uname -r)/build
-PWD := $(shell pwd)
-
-default: all
-
-all:
-	$(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules
-
-modules_install:
-	$(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules_install
-
-clean:
-	$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
-
-endif

+ 2 - 1
net/dccp/input.c

@@ -239,7 +239,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
 		dccp_update_gsr(sk, seqno);
 		dccp_update_gsr(sk, seqno);
 
 
 		if (dh->dccph_type != DCCP_PKT_SYNC &&
 		if (dh->dccph_type != DCCP_PKT_SYNC &&
-		    (ackno != DCCP_PKT_WITHOUT_ACK_SEQ))
+		    ackno != DCCP_PKT_WITHOUT_ACK_SEQ &&
+		    after48(ackno, dp->dccps_gar))
 			dp->dccps_gar = ackno;
 			dp->dccps_gar = ackno;
 	} else {
 	} else {
 		unsigned long now = jiffies;
 		unsigned long now = jiffies;

+ 2 - 0
net/decnet/af_decnet.c

@@ -1556,6 +1556,8 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us
 			if (r_len > sizeof(struct linkinfo_dn))
 			if (r_len > sizeof(struct linkinfo_dn))
 				r_len = sizeof(struct linkinfo_dn);
 				r_len = sizeof(struct linkinfo_dn);
 
 
+			memset(&link, 0, sizeof(link));
+
 			switch(sock->state) {
 			switch(sock->state) {
 				case SS_CONNECTING:
 				case SS_CONNECTING:
 					link.idn_linkstate = LL_CONNECTING;
 					link.idn_linkstate = LL_CONNECTING;

+ 42 - 49
net/econet/af_econet.c

@@ -31,6 +31,7 @@
 #include <linux/skbuff.h>
 #include <linux/skbuff.h>
 #include <linux/udp.h>
 #include <linux/udp.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <net/sock.h>
 #include <net/sock.h>
 #include <net/inet_common.h>
 #include <net/inet_common.h>
 #include <linux/stat.h>
 #include <linux/stat.h>
@@ -276,12 +277,12 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 #endif
 #endif
 #ifdef CONFIG_ECONET_AUNUDP
 #ifdef CONFIG_ECONET_AUNUDP
 	struct msghdr udpmsg;
 	struct msghdr udpmsg;
-	struct iovec iov[msg->msg_iovlen+1];
+	struct iovec iov[2];
 	struct aunhdr ah;
 	struct aunhdr ah;
 	struct sockaddr_in udpdest;
 	struct sockaddr_in udpdest;
 	__kernel_size_t size;
 	__kernel_size_t size;
-	int i;
 	mm_segment_t oldfs;
 	mm_segment_t oldfs;
+	char *userbuf;
 #endif
 #endif
 
 
 	/*
 	/*
@@ -297,23 +298,14 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 
 
 	mutex_lock(&econet_mutex);
 	mutex_lock(&econet_mutex);
 
 
-	if (saddr == NULL) {
-		struct econet_sock *eo = ec_sk(sk);
-
-		addr.station = eo->station;
-		addr.net     = eo->net;
-		port	     = eo->port;
-		cb	     = eo->cb;
-	} else {
-		if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
-			mutex_unlock(&econet_mutex);
-			return -EINVAL;
-		}
-		addr.station = saddr->addr.station;
-		addr.net = saddr->addr.net;
-		port = saddr->port;
-		cb = saddr->cb;
-	}
+        if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
+                mutex_unlock(&econet_mutex);
+                return -EINVAL;
+        }
+        addr.station = saddr->addr.station;
+        addr.net = saddr->addr.net;
+        port = saddr->port;
+        cb = saddr->cb;
 
 
 	/* Look for a device with the right network number. */
 	/* Look for a device with the right network number. */
 	dev = net2dev_map[addr.net];
 	dev = net2dev_map[addr.net];
@@ -328,17 +320,17 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 		}
 		}
 	}
 	}
 
 
-	if (len + 15 > dev->mtu) {
-		mutex_unlock(&econet_mutex);
-		return -EMSGSIZE;
-	}
-
 	if (dev->type == ARPHRD_ECONET) {
 	if (dev->type == ARPHRD_ECONET) {
 		/* Real hardware Econet.  We're not worthy etc. */
 		/* Real hardware Econet.  We're not worthy etc. */
 #ifdef CONFIG_ECONET_NATIVE
 #ifdef CONFIG_ECONET_NATIVE
 		unsigned short proto = 0;
 		unsigned short proto = 0;
 		int res;
 		int res;
 
 
+		if (len + 15 > dev->mtu) {
+			mutex_unlock(&econet_mutex);
+			return -EMSGSIZE;
+		}
+
 		dev_hold(dev);
 		dev_hold(dev);
 
 
 		skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
 		skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
@@ -351,7 +343,6 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 
 
 		eb = (struct ec_cb *)&skb->cb;
 		eb = (struct ec_cb *)&skb->cb;
 
 
-		/* BUG: saddr may be NULL */
 		eb->cookie = saddr->cookie;
 		eb->cookie = saddr->cookie;
 		eb->sec = *saddr;
 		eb->sec = *saddr;
 		eb->sent = ec_tx_done;
 		eb->sent = ec_tx_done;
@@ -415,6 +406,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 		return -ENETDOWN;		/* No socket - can't send */
 		return -ENETDOWN;		/* No socket - can't send */
 	}
 	}
 
 
+	if (len > 32768) {
+		err = -E2BIG;
+		goto error;
+	}
+
 	/* Make up a UDP datagram and hand it off to some higher intellect. */
 	/* Make up a UDP datagram and hand it off to some higher intellect. */
 
 
 	memset(&udpdest, 0, sizeof(udpdest));
 	memset(&udpdest, 0, sizeof(udpdest));
@@ -446,36 +442,26 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 
 
 	/* tack our header on the front of the iovec */
 	/* tack our header on the front of the iovec */
 	size = sizeof(struct aunhdr);
 	size = sizeof(struct aunhdr);
-	/*
-	 * XXX: that is b0rken.  We can't mix userland and kernel pointers
-	 * in iovec, since on a lot of platforms copy_from_user() will
-	 * *not* work with the kernel and userland ones at the same time,
-	 * regardless of what we do with set_fs().  And we are talking about
-	 * econet-over-ethernet here, so "it's only ARM anyway" doesn't
-	 * apply.  Any suggestions on fixing that code?		-- AV
-	 */
 	iov[0].iov_base = (void *)&ah;
 	iov[0].iov_base = (void *)&ah;
 	iov[0].iov_len = size;
 	iov[0].iov_len = size;
-	for (i = 0; i < msg->msg_iovlen; i++) {
-		void __user *base = msg->msg_iov[i].iov_base;
-		size_t iov_len = msg->msg_iov[i].iov_len;
-		/* Check it now since we switch to KERNEL_DS later. */
-		if (!access_ok(VERIFY_READ, base, iov_len)) {
-			mutex_unlock(&econet_mutex);
-			return -EFAULT;
-		}
-		iov[i+1].iov_base = base;
-		iov[i+1].iov_len = iov_len;
-		size += iov_len;
+
+	userbuf = vmalloc(len);
+	if (userbuf == NULL) {
+		err = -ENOMEM;
+		goto error;
 	}
 	}
 
 
+	iov[1].iov_base = userbuf;
+	iov[1].iov_len = len;
+	err = memcpy_fromiovec(userbuf, msg->msg_iov, len);
+	if (err)
+		goto error_free_buf;
+
 	/* Get a skbuff (no data, just holds our cb information) */
 	/* Get a skbuff (no data, just holds our cb information) */
 	if ((skb = sock_alloc_send_skb(sk, 0,
 	if ((skb = sock_alloc_send_skb(sk, 0,
 				       msg->msg_flags & MSG_DONTWAIT,
 				       msg->msg_flags & MSG_DONTWAIT,
-				       &err)) == NULL) {
-		mutex_unlock(&econet_mutex);
-		return err;
-	}
+				       &err)) == NULL)
+		goto error_free_buf;
 
 
 	eb = (struct ec_cb *)&skb->cb;
 	eb = (struct ec_cb *)&skb->cb;
 
 
@@ -491,7 +477,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 	udpmsg.msg_name = (void *)&udpdest;
 	udpmsg.msg_name = (void *)&udpdest;
 	udpmsg.msg_namelen = sizeof(udpdest);
 	udpmsg.msg_namelen = sizeof(udpdest);
 	udpmsg.msg_iov = &iov[0];
 	udpmsg.msg_iov = &iov[0];
-	udpmsg.msg_iovlen = msg->msg_iovlen + 1;
+	udpmsg.msg_iovlen = 2;
 	udpmsg.msg_control = NULL;
 	udpmsg.msg_control = NULL;
 	udpmsg.msg_controllen = 0;
 	udpmsg.msg_controllen = 0;
 	udpmsg.msg_flags=0;
 	udpmsg.msg_flags=0;
@@ -499,9 +485,13 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 	oldfs = get_fs(); set_fs(KERNEL_DS);	/* More privs :-) */
 	oldfs = get_fs(); set_fs(KERNEL_DS);	/* More privs :-) */
 	err = sock_sendmsg(udpsock, &udpmsg, size);
 	err = sock_sendmsg(udpsock, &udpmsg, size);
 	set_fs(oldfs);
 	set_fs(oldfs);
+
+error_free_buf:
+	vfree(userbuf);
 #else
 #else
 	err = -EPROTOTYPE;
 	err = -EPROTOTYPE;
 #endif
 #endif
+	error:
 	mutex_unlock(&econet_mutex);
 	mutex_unlock(&econet_mutex);
 
 
 	return err;
 	return err;
@@ -671,6 +661,9 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
 	err = 0;
 	err = 0;
 	switch (cmd) {
 	switch (cmd) {
 	case SIOCSIFADDR:
 	case SIOCSIFADDR:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
 		edev = dev->ec_ptr;
 		edev = dev->ec_ptr;
 		if (edev == NULL) {
 		if (edev == NULL) {
 			/* Magic up a new one. */
 			/* Magic up a new one. */

+ 1 - 2
net/ipv4/inet_hashtables.c

@@ -133,8 +133,7 @@ int __inet_inherit_port(struct sock *sk, struct sock *child)
 			}
 			}
 		}
 		}
 	}
 	}
-	sk_add_bind_node(child, &tb->owners);
-	inet_csk(child)->icsk_bind_hash = tb;
+	inet_bind_hash(child, tb, port);
 	spin_unlock(&head->lock);
 	spin_unlock(&head->lock);
 
 
 	return 0;
 	return 0;

+ 5 - 1
net/ipv4/sysctl_net_ipv4.c

@@ -26,6 +26,8 @@ static int zero;
 static int tcp_retr1_max = 255;
 static int tcp_retr1_max = 255;
 static int ip_local_port_range_min[] = { 1, 1 };
 static int ip_local_port_range_min[] = { 1, 1 };
 static int ip_local_port_range_max[] = { 65535, 65535 };
 static int ip_local_port_range_max[] = { 65535, 65535 };
+static int tcp_adv_win_scale_min = -31;
+static int tcp_adv_win_scale_max = 31;
 
 
 /* Update system visible IP port range */
 /* Update system visible IP port range */
 static void set_local_port_range(int range[2])
 static void set_local_port_range(int range[2])
@@ -426,7 +428,9 @@ static struct ctl_table ipv4_table[] = {
 		.data		= &sysctl_tcp_adv_win_scale,
 		.data		= &sysctl_tcp_adv_win_scale,
 		.maxlen		= sizeof(int),
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &tcp_adv_win_scale_min,
+		.extra2		= &tcp_adv_win_scale_max,
 	},
 	},
 	{
 	{
 		.procname	= "tcp_tw_reuse",
 		.procname	= "tcp_tw_reuse",

+ 1 - 1
net/ipv4/tcp.c

@@ -2246,7 +2246,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 		/* Values greater than interface MTU won't take effect. However
 		/* Values greater than interface MTU won't take effect. However
 		 * at the point when this call is done we typically don't yet
 		 * at the point when this call is done we typically don't yet
 		 * know which interface is going to be used */
 		 * know which interface is going to be used */
-		if (val < 64 || val > MAX_TCP_WINDOW) {
+		if (val < TCP_MIN_MSS || val > MAX_TCP_WINDOW) {
 			err = -EINVAL;
 			err = -EINVAL;
 			break;
 			break;
 		}
 		}

+ 3 - 1
net/ipv4/tcp_ipv4.c

@@ -2043,7 +2043,9 @@ get_req:
 	}
 	}
 get_sk:
 get_sk:
 	sk_nulls_for_each_from(sk, node) {
 	sk_nulls_for_each_from(sk, node) {
-		if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
+		if (!net_eq(sock_net(sk), net))
+			continue;
+		if (sk->sk_family == st->family) {
 			cur = sk;
 			cur = sk;
 			goto out;
 			goto out;
 		}
 		}

+ 32 - 5
net/unix/af_unix.c

@@ -1343,9 +1343,25 @@ static void unix_destruct_scm(struct sk_buff *skb)
 	sock_wfree(skb);
 	sock_wfree(skb);
 }
 }
 
 
+#define MAX_RECURSION_LEVEL 4
+
 static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
 static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
 {
 {
 	int i;
 	int i;
+	unsigned char max_level = 0;
+	int unix_sock_count = 0;
+
+	for (i = scm->fp->count - 1; i >= 0; i--) {
+		struct sock *sk = unix_get_socket(scm->fp->fp[i]);
+
+		if (sk) {
+			unix_sock_count++;
+			max_level = max(max_level,
+					unix_sk(sk)->recursion_level);
+		}
+	}
+	if (unlikely(max_level > MAX_RECURSION_LEVEL))
+		return -ETOOMANYREFS;
 
 
 	/*
 	/*
 	 * Need to duplicate file references for the sake of garbage
 	 * Need to duplicate file references for the sake of garbage
@@ -1356,9 +1372,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
 	if (!UNIXCB(skb).fp)
 	if (!UNIXCB(skb).fp)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	for (i = scm->fp->count-1; i >= 0; i--)
-		unix_inflight(scm->fp->fp[i]);
-	return 0;
+	if (unix_sock_count) {
+		for (i = scm->fp->count - 1; i >= 0; i--)
+			unix_inflight(scm->fp->fp[i]);
+	}
+	return max_level;
 }
 }
 
 
 static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
 static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
@@ -1393,6 +1411,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	struct sk_buff *skb;
 	struct sk_buff *skb;
 	long timeo;
 	long timeo;
 	struct scm_cookie tmp_scm;
 	struct scm_cookie tmp_scm;
+	int max_level;
 
 
 	if (NULL == siocb->scm)
 	if (NULL == siocb->scm)
 		siocb->scm = &tmp_scm;
 		siocb->scm = &tmp_scm;
@@ -1431,8 +1450,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
 		goto out;
 		goto out;
 
 
 	err = unix_scm_to_skb(siocb->scm, skb, true);
 	err = unix_scm_to_skb(siocb->scm, skb, true);
-	if (err)
+	if (err < 0)
 		goto out_free;
 		goto out_free;
+	max_level = err + 1;
 	unix_get_secdata(siocb->scm, skb);
 	unix_get_secdata(siocb->scm, skb);
 
 
 	skb_reset_transport_header(skb);
 	skb_reset_transport_header(skb);
@@ -1514,6 +1534,8 @@ restart:
 	if (sock_flag(other, SOCK_RCVTSTAMP))
 	if (sock_flag(other, SOCK_RCVTSTAMP))
 		__net_timestamp(skb);
 		__net_timestamp(skb);
 	skb_queue_tail(&other->sk_receive_queue, skb);
 	skb_queue_tail(&other->sk_receive_queue, skb);
+	if (max_level > unix_sk(other)->recursion_level)
+		unix_sk(other)->recursion_level = max_level;
 	unix_state_unlock(other);
 	unix_state_unlock(other);
 	other->sk_data_ready(other, len);
 	other->sk_data_ready(other, len);
 	sock_put(other);
 	sock_put(other);
@@ -1544,6 +1566,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	int sent = 0;
 	int sent = 0;
 	struct scm_cookie tmp_scm;
 	struct scm_cookie tmp_scm;
 	bool fds_sent = false;
 	bool fds_sent = false;
+	int max_level;
 
 
 	if (NULL == siocb->scm)
 	if (NULL == siocb->scm)
 		siocb->scm = &tmp_scm;
 		siocb->scm = &tmp_scm;
@@ -1607,10 +1630,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 
 
 		/* Only send the fds in the first buffer */
 		/* Only send the fds in the first buffer */
 		err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
 		err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
-		if (err) {
+		if (err < 0) {
 			kfree_skb(skb);
 			kfree_skb(skb);
 			goto out_err;
 			goto out_err;
 		}
 		}
+		max_level = err + 1;
 		fds_sent = true;
 		fds_sent = true;
 
 
 		err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
 		err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
@@ -1626,6 +1650,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 			goto pipe_err_free;
 			goto pipe_err_free;
 
 
 		skb_queue_tail(&other->sk_receive_queue, skb);
 		skb_queue_tail(&other->sk_receive_queue, skb);
+		if (max_level > unix_sk(other)->recursion_level)
+			unix_sk(other)->recursion_level = max_level;
 		unix_state_unlock(other);
 		unix_state_unlock(other);
 		other->sk_data_ready(other, size);
 		other->sk_data_ready(other, size);
 		sent += size;
 		sent += size;
@@ -1845,6 +1871,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 		unix_state_lock(sk);
 		unix_state_lock(sk);
 		skb = skb_dequeue(&sk->sk_receive_queue);
 		skb = skb_dequeue(&sk->sk_receive_queue);
 		if (skb == NULL) {
 		if (skb == NULL) {
+			unix_sk(sk)->recursion_level = 0;
 			if (copied >= target)
 			if (copied >= target)
 				goto unlock;
 				goto unlock;
 
 

+ 8 - 1
net/unix/garbage.c

@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait);
 unsigned int unix_tot_inflight;
 unsigned int unix_tot_inflight;
 
 
 
 
-static struct sock *unix_get_socket(struct file *filp)
+struct sock *unix_get_socket(struct file *filp)
 {
 {
 	struct sock *u_sock = NULL;
 	struct sock *u_sock = NULL;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct inode *inode = filp->f_path.dentry->d_inode;
@@ -259,9 +259,16 @@ static void inc_inflight_move_tail(struct unix_sock *u)
 }
 }
 
 
 static bool gc_in_progress = false;
 static bool gc_in_progress = false;
+#define UNIX_INFLIGHT_TRIGGER_GC 16000
 
 
 void wait_for_unix_gc(void)
 void wait_for_unix_gc(void)
 {
 {
+	/*
+	 * If number of inflight sockets is insane,
+	 * force a garbage collect right now.
+	 */
+	if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
+		unix_gc();
 	wait_event(unix_gc_wait, gc_in_progress == false);
 	wait_event(unix_gc_wait, gc_in_progress == false);
 }
 }