Commit a01af8e4 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents a9735c81 25888e30
...@@ -144,6 +144,7 @@ tcp_adv_win_scale - INTEGER ...@@ -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
......
...@@ -1627,7 +1627,7 @@ __setup("icn=", icn_setup); ...@@ -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,8 +1637,9 @@ static int __init icn_init(void) ...@@ -1637,8 +1637,9 @@ 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, '$');
if (p)
*p = 0; *p = 0;
} else } else
strcpy(rev, " ??? "); strcpy(rev, " ??? ");
......
...@@ -2543,10 +2543,10 @@ config PCH_GBE ...@@ -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. This is a gigabit ethernet driver for EG20T PCH.
Topcliff PCH is the platform controller hub that is used in Intel's 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.
......
...@@ -155,10 +155,10 @@ static void au1000_enable_mac(struct net_device *dev, int force_reset) ...@@ -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) ...@@ -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) ...@@ -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;
......
...@@ -816,17 +816,21 @@ static struct net_device_stats *cxgb4vf_get_stats(struct net_device *dev) ...@@ -816,17 +816,21 @@ 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 * Collect up to maxaddrs worth of a netdevice's unicast addresses, starting
* array of addrss pointers and return the number collected. * 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, static inline unsigned int collect_netdev_uc_list_addrs(const struct net_device *dev,
const u8 **addr, const u8 **addr,
unsigned int offset,
unsigned int maxaddrs) 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) { for_each_dev_addr(dev, ha)
if (index++ >= offset) {
addr[naddr++] = ha->addr; addr[naddr++] = ha->addr;
if (naddr >= maxaddrs) if (naddr >= maxaddrs)
break; break;
...@@ -835,17 +839,21 @@ static inline int collect_netdev_uc_list_addrs(const struct net_device *dev, ...@@ -835,17 +839,21 @@ static inline int collect_netdev_uc_list_addrs(const struct net_device *dev,
} }
/* /*
* Collect up to maxaddrs worth of a netdevice's multicast addresses into an * Collect up to maxaddrs worth of a netdevice's multicast addresses, starting
* array of addrss pointers and return the number collected. * 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, static inline unsigned int collect_netdev_mc_list_addrs(const struct net_device *dev,
const u8 **addr, const u8 **addr,
unsigned int offset,
unsigned int maxaddrs) 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) { netdev_for_each_mc_addr(ha, dev)
if (index++ >= offset) {
addr[naddr++] = ha->addr; addr[naddr++] = ha->addr;
if (naddr >= maxaddrs) if (naddr >= maxaddrs)
break; break;
...@@ -862,16 +870,20 @@ static int set_addr_filters(const struct net_device *dev, bool sleep) ...@@ -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)); for (offset = 0; ; offset += naddr) {
if (naddr > 0) { 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) ...@@ -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)); for (offset = 0; ; offset += naddr) {
if (naddr > 0) { 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,
......
...@@ -1014,15 +1014,22 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free, ...@@ -1014,15 +1014,22 @@ 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); 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;
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) | cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
...@@ -1030,32 +1037,49 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free, ...@@ -1030,32 +1037,49 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
FW_CMD_WRITE | FW_CMD_WRITE |
(free ? FW_CMD_EXEC : 0) | (free ? FW_CMD_EXEC : 0) |
FW_VI_MAC_CMD_VIID(viid)); FW_VI_MAC_CMD_VIID(viid));
cmd.freemacs_to_len16 = cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) | cmd.freemacs_to_len16 =
cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
FW_CMD_LEN16(len16)); FW_CMD_LEN16(len16));
for (i = 0, p = cmd.u.exact; i < naddr; i++, p++) { for (i = 0, p = cmd.u.exact; i < fw_naddr; i++, p++) {
p->valid_to_idx = p->valid_to_idx = cpu_to_be16(
cpu_to_be16(FW_VI_MAC_CMD_VALID | FW_VI_MAC_CMD_VALID |
FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC)); FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
memcpy(p->macaddr, addr[i], sizeof(p->macaddr)); memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr));
} }
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++) { ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl,
u16 index = FW_VI_MAC_CMD_IDX_GET(be16_to_cpu(p->valid_to_idx)); sleep_ok);
if (ret && ret != -ENOMEM)
break;
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) if (idx)
idx[i] = (index >= FW_CLS_TCAM_NUM_ENTRIES idx[offset+i] =
(index >= FW_CLS_TCAM_NUM_ENTRIES
? 0xffff ? 0xffff
: index); : index);
if (index < FW_CLS_TCAM_NUM_ENTRIES) if (index < FW_CLS_TCAM_NUM_ENTRIES)
ret++; nfilters++;
else if (hash) else if (hash)
*hash |= (1 << hash_mac_addr(addr[i])); *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;
} }
......
...@@ -400,6 +400,7 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes) ...@@ -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) ...@@ -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,9 +743,11 @@ static int ehea_proc_rwqes(struct net_device *dev, ...@@ -735,9 +743,11 @@ 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);
ehea_fill_skb(dev, skb, cqe); ehea_fill_skb(dev, skb, cqe);
......
/* /*
* 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) ...@@ -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_DESCRIPTION("EG20T PCH Gigabit ethernet Driver");
MODULE_AUTHOR("OKI semiconductor, <masa-korg@dsn.okisemi.com>"); 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);
......
...@@ -434,8 +434,8 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter) ...@@ -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 = { .min = PCH_GBE_MIN_TXD,
.arg = { .r = { .max = PCH_GBE_MAX_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) ...@@ -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 = { .min = PCH_GBE_MIN_RXD,
.arg = { .r = { .max = PCH_GBE_MAX_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;
......
...@@ -2584,16 +2584,16 @@ ppp_create_interface(struct net *net, int unit, int *retp) ...@@ -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) ...@@ -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) ...@@ -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_alloc(struct idr *p, void *ptr, int n)
static int unit_set(struct idr *p, void *ptr, int n)
{ {
int unit, err; int unit, err;
...@@ -2871,10 +2870,24 @@ static int unit_set(struct idr *p, void *ptr, int n) ...@@ -2871,10 +2870,24 @@ static int unit_set(struct idr *p, void *ptr, int n)
} }
err = idr_get_new_above(p, ptr, n, &unit); err = idr_get_new_above(p, ptr, n, &unit);
if (err < 0) {
if (err == -EAGAIN) if (err == -EAGAIN)
goto again; 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 @@ static int unit_set(struct idr *p, void *ptr, int n) ...@@ -2885,19 +2898,7 @@ static int unit_set(struct idr *p, void *ptr, int n)
/* 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; return __unit_alloc(p, ptr, 0);
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;
} }
/* put unit number back to a pool */ /* put unit number back to a pool */
......
...@@ -899,7 +899,8 @@ struct ucc_geth_hardware_statistics { ...@@ -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 */
......
...@@ -2994,12 +2994,14 @@ static int hso_probe(struct usb_interface *interface, ...@@ -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) && if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) {
!disable_net) if (!disable_net)
hso_dev = hso_create_net_device(interface, port_spec); hso_dev =
else 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;
......
...@@ -498,7 +498,6 @@ static int x25_asy_open(struct net_device *dev) ...@@ -498,7 +498,6 @@ static int x25_asy_open(struct net_device *dev)
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) ...@@ -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) ...@@ -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) ...@@ -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);
......
...@@ -518,7 +518,7 @@ bool ath_stoprecv(struct ath_softc *sc) ...@@ -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);
......
...@@ -647,7 +647,7 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw, ...@@ -647,7 +647,7 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
} }
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--;
......
...@@ -163,6 +163,7 @@ static int b43_sdio_probe(struct sdio_func *func, ...@@ -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);
......
...@@ -24,6 +24,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { ...@@ -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) },
......
...@@ -129,8 +129,9 @@ static void handle_tx(struct vhost_net *net) ...@@ -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, /* TODO: check that we are running from vhost_worker?
lockdep_is_held(&vq->mutex)); * 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;
......
...@@ -2047,6 +2047,7 @@ ...@@ -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
......
...@@ -10,6 +10,7 @@ extern void unix_inflight(struct file *fp); ...@@ -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 { ...@@ -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)
......
# #
# 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 \ ...@@ -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
...@@ -239,7 +239,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) ...@@ -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;
......
...@@ -1556,6 +1556,8 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us ...@@ -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;
......
...@@ -31,6 +31,7 @@ ...@@ -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, ...@@ -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,15 +298,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -297,15 +298,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
mutex_lock(&econet_mutex); mutex_lock(&econet_mutex);
if (saddr == NULL) { if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
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); mutex_unlock(&econet_mutex);
return -EINVAL; return -EINVAL;
} }
...@@ -313,7 +306,6 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -313,7 +306,6 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
addr.net = saddr->addr.net; addr.net = saddr->addr.net;
port = saddr->port; port = saddr->port;
cb = saddr->cb; 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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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; userbuf = vmalloc(len);
size_t iov_len = msg->msg_iov[i].iov_len; if (userbuf == NULL) {
/* Check it now since we switch to KERNEL_DS later. */ err = -ENOMEM;
if (!access_ok(VERIFY_READ, base, iov_len)) { goto error;
mutex_unlock(&econet_mutex);
return -EFAULT;
}
iov[i+1].iov_base = base;
iov[i+1].iov_len = iov_len;
size += iov_len;
} }
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) { &err)) == NULL)
mutex_unlock(&econet_mutex); goto error_free_buf;
return err;
}
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, ...@@ -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, ...@@ -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) ...@@ -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. */
......
...@@ -133,8 +133,7 @@ int __inet_inherit_port(struct sock *sk, struct sock *child) ...@@ -133,8 +133,7 @@ int __inet_inherit_port(struct sock *sk, struct sock *child)
} }
} }
} }
sk_add_bind_node(child, &tb->owners); inet_bind_hash(child, tb, port);
inet_csk(child)->icsk_bind_hash = tb;
spin_unlock(&head->lock); spin_unlock(&head->lock);
return 0; return 0;
......
...@@ -26,6 +26,8 @@ static int zero; ...@@ -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[] = { ...@@ -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",
......
...@@ -2246,7 +2246,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, ...@@ -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;
} }
......
...@@ -2043,7 +2043,9 @@ static void *listening_get_next(struct seq_file *seq, void *cur) ...@@ -2043,7 +2043,9 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
} }
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;
} }
......
...@@ -1343,9 +1343,25 @@ static void unix_destruct_scm(struct sk_buff *skb) ...@@ -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) ...@@ -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--) if (unix_sock_count) {
for (i = scm->fp->count - 1; i >= 0; i--)
unix_inflight(scm->fp->fp[i]); unix_inflight(scm->fp->fp[i]);
return 0; }
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, ...@@ -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, ...@@ -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 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1514,6 +1534,8 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
......
...@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait); ...@@ -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) ...@@ -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);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment