Commit 29cfcddc 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:
  net/ipv4: Eliminate kstrdup memory leak
  net/caif/cfrfml.c: use asm/unaligned.h
  ax25: missplaced sock_put(sk)
  qlge: reset the chip before freeing the buffers
  l2tp: test for ethernet header in l2tp_eth_dev_recv()
  tcp: select(writefds) don't hang up when a peer close connection
  tcp: fix three tcp sysctls tuning
  tcp: Combat per-cpu skew in orphan tests.
  pxa168_eth: silence gcc warnings
  pxa168_eth: update call to phy_mii_ioctl()
  pxa168_eth: fix error handling in prope
  pxa168_eth: remove unneeded null check
  phylib: Fix race between returning phydev and calling adjust_link
  caif-driver: add HAS_DMA dependency
  3c59x: Fix deadlock between boomerang_interrupt and boomerang_start_tx
  qlcnic: fix poll implementation
  netxen: fix poll implementation
  bridge: netfilter: fix a memory leak
parents 303fd2c2 c34186ed
...@@ -633,7 +633,8 @@ struct vortex_private { ...@@ -633,7 +633,8 @@ struct vortex_private {
open:1, open:1,
medialock:1, medialock:1,
must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */
large_frames:1; /* accept large frames */ large_frames:1, /* accept large frames */
handling_irq:1; /* private in_irq indicator */
int drv_flags; int drv_flags;
u16 status_enable; u16 status_enable;
u16 intr_enable; u16 intr_enable;
...@@ -2133,6 +2134,15 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2133,6 +2134,15 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->name, vp->cur_tx); dev->name, vp->cur_tx);
} }
/*
* We can't allow a recursion from our interrupt handler back into the
* tx routine, as they take the same spin lock, and that causes
* deadlock. Just return NETDEV_TX_BUSY and let the stack try again in
* a bit
*/
if (vp->handling_irq)
return NETDEV_TX_BUSY;
if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) { if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) {
if (vortex_debug > 0) if (vortex_debug > 0)
pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n", pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n",
...@@ -2335,11 +2345,13 @@ boomerang_interrupt(int irq, void *dev_id) ...@@ -2335,11 +2345,13 @@ boomerang_interrupt(int irq, void *dev_id)
ioaddr = vp->ioaddr; ioaddr = vp->ioaddr;
/* /*
* It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout
* and boomerang_start_xmit * and boomerang_start_xmit
*/ */
spin_lock(&vp->lock); spin_lock(&vp->lock);
vp->handling_irq = 1;
status = ioread16(ioaddr + EL3_STATUS); status = ioread16(ioaddr + EL3_STATUS);
...@@ -2447,6 +2459,7 @@ boomerang_interrupt(int irq, void *dev_id) ...@@ -2447,6 +2459,7 @@ boomerang_interrupt(int irq, void *dev_id)
pr_debug("%s: exiting interrupt, status %4.4x.\n", pr_debug("%s: exiting interrupt, status %4.4x.\n",
dev->name, status); dev->name, status);
handler_exit: handler_exit:
vp->handling_irq = 0;
spin_unlock(&vp->lock); spin_unlock(&vp->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -15,7 +15,7 @@ config CAIF_TTY ...@@ -15,7 +15,7 @@ config CAIF_TTY
config CAIF_SPI_SLAVE config CAIF_SPI_SLAVE
tristate "CAIF SPI transport driver for slave interface" tristate "CAIF SPI transport driver for slave interface"
depends on CAIF depends on CAIF && HAS_DMA
default n default n
---help--- ---help---
The CAIF Link layer SPI Protocol driver for Slave SPI interface. The CAIF Link layer SPI Protocol driver for Slave SPI interface.
......
...@@ -2131,9 +2131,16 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) ...@@ -2131,9 +2131,16 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
static void netxen_nic_poll_controller(struct net_device *netdev) static void netxen_nic_poll_controller(struct net_device *netdev)
{ {
int ring;
struct nx_host_sds_ring *sds_ring;
struct netxen_adapter *adapter = netdev_priv(netdev); struct netxen_adapter *adapter = netdev_priv(netdev);
struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
disable_irq(adapter->irq); disable_irq(adapter->irq);
netxen_intr(adapter->irq, adapter); for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
netxen_intr(adapter->irq, sds_ring);
}
enable_irq(adapter->irq); enable_irq(adapter->irq);
} }
#endif #endif
......
...@@ -466,6 +466,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, ...@@ -466,6 +466,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
phydev->interface = interface; phydev->interface = interface;
phydev->state = PHY_READY;
/* Do initial configuration here, now that /* Do initial configuration here, now that
* we have certain key parameters * we have certain key parameters
* (dev_flags and interface) */ * (dev_flags and interface) */
......
...@@ -654,15 +654,15 @@ static void eth_port_start(struct net_device *dev) ...@@ -654,15 +654,15 @@ static void eth_port_start(struct net_device *dev)
/* Assignment of Tx CTRP of given queue */ /* Assignment of Tx CTRP of given queue */
tx_curr_desc = pep->tx_curr_desc_q; tx_curr_desc = pep->tx_curr_desc_q;
wrl(pep, ETH_C_TX_DESC_1, wrl(pep, ETH_C_TX_DESC_1,
(u32) ((struct tx_desc *)pep->tx_desc_dma + tx_curr_desc)); (u32) (pep->tx_desc_dma + tx_curr_desc * sizeof(struct tx_desc)));
/* Assignment of Rx CRDP of given queue */ /* Assignment of Rx CRDP of given queue */
rx_curr_desc = pep->rx_curr_desc_q; rx_curr_desc = pep->rx_curr_desc_q;
wrl(pep, ETH_C_RX_DESC_0, wrl(pep, ETH_C_RX_DESC_0,
(u32) ((struct rx_desc *)pep->rx_desc_dma + rx_curr_desc)); (u32) (pep->rx_desc_dma + rx_curr_desc * sizeof(struct rx_desc)));
wrl(pep, ETH_F_RX_DESC_0, wrl(pep, ETH_F_RX_DESC_0,
(u32) ((struct rx_desc *)pep->rx_desc_dma + rx_curr_desc)); (u32) (pep->rx_desc_dma + rx_curr_desc * sizeof(struct rx_desc)));
/* Clear all interrupts */ /* Clear all interrupts */
wrl(pep, INT_CAUSE, 0); wrl(pep, INT_CAUSE, 0);
...@@ -1350,7 +1350,7 @@ static int pxa168_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, ...@@ -1350,7 +1350,7 @@ static int pxa168_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr,
{ {
struct pxa168_eth_private *pep = netdev_priv(dev); struct pxa168_eth_private *pep = netdev_priv(dev);
if (pep->phy != NULL) if (pep->phy != NULL)
return phy_mii_ioctl(pep->phy, if_mii(ifr), cmd); return phy_mii_ioctl(pep->phy, ifr, cmd);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -1414,10 +1414,8 @@ static int ethernet_phy_setup(struct net_device *dev) ...@@ -1414,10 +1414,8 @@ static int ethernet_phy_setup(struct net_device *dev)
{ {
struct pxa168_eth_private *pep = netdev_priv(dev); struct pxa168_eth_private *pep = netdev_priv(dev);
if (pep->pd != NULL) { if (pep->pd->init)
if (pep->pd->init) pep->pd->init();
pep->pd->init();
}
pep->phy = phy_scan(pep, pep->pd->phy_addr & 0x1f); pep->phy = phy_scan(pep, pep->pd->phy_addr & 0x1f);
if (pep->phy != NULL) if (pep->phy != NULL)
phy_init(pep, pep->pd->speed, pep->pd->duplex); phy_init(pep, pep->pd->speed, pep->pd->duplex);
...@@ -1499,7 +1497,7 @@ static int pxa168_eth_probe(struct platform_device *pdev) ...@@ -1499,7 +1497,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
dev = alloc_etherdev(sizeof(struct pxa168_eth_private)); dev = alloc_etherdev(sizeof(struct pxa168_eth_private));
if (!dev) { if (!dev) {
err = -ENOMEM; err = -ENOMEM;
goto out; goto err_clk;
} }
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
...@@ -1509,12 +1507,12 @@ static int pxa168_eth_probe(struct platform_device *pdev) ...@@ -1509,12 +1507,12 @@ static int pxa168_eth_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) { if (res == NULL) {
err = -ENODEV; err = -ENODEV;
goto out; goto err_netdev;
} }
pep->base = ioremap(res->start, res->end - res->start + 1); pep->base = ioremap(res->start, res->end - res->start + 1);
if (pep->base == NULL) { if (pep->base == NULL) {
err = -ENOMEM; err = -ENOMEM;
goto out; goto err_netdev;
} }
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
BUG_ON(!res); BUG_ON(!res);
...@@ -1551,7 +1549,7 @@ static int pxa168_eth_probe(struct platform_device *pdev) ...@@ -1551,7 +1549,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
pep->smi_bus = mdiobus_alloc(); pep->smi_bus = mdiobus_alloc();
if (pep->smi_bus == NULL) { if (pep->smi_bus == NULL) {
err = -ENOMEM; err = -ENOMEM;
goto out; goto err_base;
} }
pep->smi_bus->priv = pep; pep->smi_bus->priv = pep;
pep->smi_bus->name = "pxa168_eth smi"; pep->smi_bus->name = "pxa168_eth smi";
...@@ -1560,31 +1558,31 @@ static int pxa168_eth_probe(struct platform_device *pdev) ...@@ -1560,31 +1558,31 @@ static int pxa168_eth_probe(struct platform_device *pdev)
snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id); snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id);
pep->smi_bus->parent = &pdev->dev; pep->smi_bus->parent = &pdev->dev;
pep->smi_bus->phy_mask = 0xffffffff; pep->smi_bus->phy_mask = 0xffffffff;
if (mdiobus_register(pep->smi_bus) < 0) { err = mdiobus_register(pep->smi_bus);
err = -ENOMEM; if (err)
goto out; goto err_free_mdio;
}
pxa168_init_hw(pep); pxa168_init_hw(pep);
err = ethernet_phy_setup(dev); err = ethernet_phy_setup(dev);
if (err) if (err)
goto out; goto err_mdiobus;
SET_NETDEV_DEV(dev, &pdev->dev); SET_NETDEV_DEV(dev, &pdev->dev);
err = register_netdev(dev); err = register_netdev(dev);
if (err) if (err)
goto out; goto err_mdiobus;
return 0; return 0;
out:
if (pep->clk) { err_mdiobus:
clk_disable(pep->clk); mdiobus_unregister(pep->smi_bus);
clk_put(pep->clk); err_free_mdio:
pep->clk = NULL; mdiobus_free(pep->smi_bus);
} err_base:
if (pep->base) { iounmap(pep->base);
iounmap(pep->base); err_netdev:
pep->base = NULL; free_netdev(dev);
} err_clk:
if (dev) clk_disable(clk);
free_netdev(dev); clk_put(clk);
return err; return err;
} }
......
...@@ -2188,9 +2188,16 @@ static int qlcnic_rx_poll(struct napi_struct *napi, int budget) ...@@ -2188,9 +2188,16 @@ static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev) static void qlcnic_poll_controller(struct net_device *netdev)
{ {
int ring;
struct qlcnic_host_sds_ring *sds_ring;
struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
disable_irq(adapter->irq); disable_irq(adapter->irq);
qlcnic_intr(adapter->irq, adapter); for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
qlcnic_intr(adapter->irq, sds_ring);
}
enable_irq(adapter->irq); enable_irq(adapter->irq);
} }
#endif #endif
......
...@@ -3919,12 +3919,12 @@ static int ql_adapter_down(struct ql_adapter *qdev) ...@@ -3919,12 +3919,12 @@ static int ql_adapter_down(struct ql_adapter *qdev)
for (i = 0; i < qdev->rss_ring_count; i++) for (i = 0; i < qdev->rss_ring_count; i++)
netif_napi_del(&qdev->rx_ring[i].napi); netif_napi_del(&qdev->rx_ring[i].napi);
ql_free_rx_buffers(qdev);
status = ql_adapter_reset(qdev); status = ql_adapter_reset(qdev);
if (status) if (status)
netif_err(qdev, ifdown, qdev->ndev, "reset(func #%d) FAILED!\n", netif_err(qdev, ifdown, qdev->ndev, "reset(func #%d) FAILED!\n",
qdev->func); qdev->func);
ql_free_rx_buffers(qdev);
return status; return status;
} }
......
...@@ -268,11 +268,21 @@ static inline int between(__u32 seq1, __u32 seq2, __u32 seq3) ...@@ -268,11 +268,21 @@ static inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
return seq3 - seq2 >= seq1 - seq2; return seq3 - seq2 >= seq1 - seq2;
} }
static inline int tcp_too_many_orphans(struct sock *sk, int num) static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
{ {
return (num > sysctl_tcp_max_orphans) || struct percpu_counter *ocp = sk->sk_prot->orphan_count;
(sk->sk_wmem_queued > SOCK_MIN_SNDBUF && int orphans = percpu_counter_read_positive(ocp);
atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]);
if (orphans << shift > sysctl_tcp_max_orphans) {
orphans = percpu_counter_sum_positive(ocp);
if (orphans << shift > sysctl_tcp_max_orphans)
return true;
}
if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])
return true;
return false;
} }
/* syncookies: remember time of last synqueue overflow */ /* syncookies: remember time of last synqueue overflow */
......
...@@ -112,8 +112,8 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25) ...@@ -112,8 +112,8 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
if (sk) { if (sk) {
sock_hold(sk); sock_hold(sk);
ax25_destroy_socket(ax25); ax25_destroy_socket(ax25);
sock_put(sk);
bh_unlock_sock(sk); bh_unlock_sock(sk);
sock_put(sk);
} else } else
ax25_destroy_socket(ax25); ax25_destroy_socket(ax25);
return; return;
......
...@@ -162,8 +162,8 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb) ...@@ -162,8 +162,8 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb)
if (tmp) { if (tmp) {
memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info)); memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info));
atomic_set(&tmp->use, 1); atomic_set(&tmp->use, 1);
nf_bridge_put(nf_bridge);
} }
nf_bridge_put(nf_bridge);
nf_bridge = tmp; nf_bridge = tmp;
} }
return nf_bridge; return nf_bridge;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/unaligned/le_byteshift.h> #include <asm/unaligned.h>
#include <net/caif/caif_layer.h> #include <net/caif/caif_layer.h>
#include <net/caif/cfsrvl.h> #include <net/caif/cfsrvl.h>
#include <net/caif/cfpkt.h> #include <net/caif/cfpkt.h>
......
...@@ -451,7 +451,8 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) ...@@ -451,7 +451,8 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
mask |= POLLOUT | POLLWRNORM; mask |= POLLOUT | POLLWRNORM;
} }
} } else
mask |= POLLOUT | POLLWRNORM;
if (tp->urg_data & TCP_URG_VALID) if (tp->urg_data & TCP_URG_VALID)
mask |= POLLPRI; mask |= POLLPRI;
...@@ -2011,11 +2012,8 @@ void tcp_close(struct sock *sk, long timeout) ...@@ -2011,11 +2012,8 @@ void tcp_close(struct sock *sk, long timeout)
} }
} }
if (sk->sk_state != TCP_CLOSE) { if (sk->sk_state != TCP_CLOSE) {
int orphan_count = percpu_counter_read_positive(
sk->sk_prot->orphan_count);
sk_mem_reclaim(sk); sk_mem_reclaim(sk);
if (tcp_too_many_orphans(sk, orphan_count)) { if (tcp_too_many_orphans(sk, 0)) {
if (net_ratelimit()) if (net_ratelimit())
printk(KERN_INFO "TCP: too many of orphaned " printk(KERN_INFO "TCP: too many of orphaned "
"sockets\n"); "sockets\n");
...@@ -3212,7 +3210,7 @@ void __init tcp_init(void) ...@@ -3212,7 +3210,7 @@ void __init tcp_init(void)
{ {
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
unsigned long nr_pages, limit; unsigned long nr_pages, limit;
int order, i, max_share; int i, max_share, cnt;
unsigned long jiffy = jiffies; unsigned long jiffy = jiffies;
BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
...@@ -3261,22 +3259,12 @@ void __init tcp_init(void) ...@@ -3261,22 +3259,12 @@ void __init tcp_init(void)
INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain); INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain);
} }
/* Try to be a bit smarter and adjust defaults depending
* on available memory. cnt = tcp_hashinfo.ehash_mask + 1;
*/
for (order = 0; ((1 << order) << PAGE_SHIFT) < tcp_death_row.sysctl_max_tw_buckets = cnt / 2;
(tcp_hashinfo.bhash_size * sizeof(struct inet_bind_hashbucket)); sysctl_tcp_max_orphans = cnt / 2;
order++) sysctl_max_syn_backlog = max(128, cnt / 256);
;
if (order >= 4) {
tcp_death_row.sysctl_max_tw_buckets = 180000;
sysctl_tcp_max_orphans = 4096 << (order - 4);
sysctl_max_syn_backlog = 1024;
} else if (order < 3) {
tcp_death_row.sysctl_max_tw_buckets >>= (3 - order);
sysctl_tcp_max_orphans >>= (3 - order);
sysctl_max_syn_backlog = 128;
}
/* Set the pressure threshold to be a fraction of global memory that /* Set the pressure threshold to be a fraction of global memory that
* is up to 1/2 at 256 MB, decreasing toward zero with the amount of * is up to 1/2 at 256 MB, decreasing toward zero with the amount of
......
...@@ -196,10 +196,10 @@ void tcp_get_allowed_congestion_control(char *buf, size_t maxlen) ...@@ -196,10 +196,10 @@ void tcp_get_allowed_congestion_control(char *buf, size_t maxlen)
int tcp_set_allowed_congestion_control(char *val) int tcp_set_allowed_congestion_control(char *val)
{ {
struct tcp_congestion_ops *ca; struct tcp_congestion_ops *ca;
char *clone, *name; char *saved_clone, *clone, *name;
int ret = 0; int ret = 0;
clone = kstrdup(val, GFP_USER); saved_clone = clone = kstrdup(val, GFP_USER);
if (!clone) if (!clone)
return -ENOMEM; return -ENOMEM;
...@@ -226,6 +226,7 @@ int tcp_set_allowed_congestion_control(char *val) ...@@ -226,6 +226,7 @@ int tcp_set_allowed_congestion_control(char *val)
} }
out: out:
spin_unlock(&tcp_cong_list_lock); spin_unlock(&tcp_cong_list_lock);
kfree(saved_clone);
return ret; return ret;
} }
......
...@@ -66,18 +66,18 @@ static void tcp_write_err(struct sock *sk) ...@@ -66,18 +66,18 @@ static void tcp_write_err(struct sock *sk)
static int tcp_out_of_resources(struct sock *sk, int do_reset) static int tcp_out_of_resources(struct sock *sk, int do_reset)
{ {
struct tcp_sock *tp = tcp_sk(sk); struct tcp_sock *tp = tcp_sk(sk);
int orphans = percpu_counter_read_positive(&tcp_orphan_count); int shift = 0;
/* If peer does not open window for long time, or did not transmit /* If peer does not open window for long time, or did not transmit
* anything for long time, penalize it. */ * anything for long time, penalize it. */
if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset) if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset)
orphans <<= 1; shift++;
/* If some dubious ICMP arrived, penalize even more. */ /* If some dubious ICMP arrived, penalize even more. */
if (sk->sk_err_soft) if (sk->sk_err_soft)
orphans <<= 1; shift++;
if (tcp_too_many_orphans(sk, orphans)) { if (tcp_too_many_orphans(sk, shift)) {
if (net_ratelimit()) if (net_ratelimit())
printk(KERN_INFO "Out of socket memory\n"); printk(KERN_INFO "Out of socket memory\n");
......
...@@ -132,7 +132,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, ...@@ -132,7 +132,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
printk("\n"); printk("\n");
} }
if (data_len < ETH_HLEN) if (!pskb_may_pull(skb, sizeof(ETH_HLEN)))
goto error; goto error;
secpath_reset(skb); secpath_reset(skb);
......
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