Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Browse files Browse the repository at this point in the history
Pull networking fixes from David Miller:

 1) Out of bounds array access in 802.11 minstrel code, from Adrien
    Schildknecht.

 2) Don't use skb_get() in IGMP/MLD code paths, as this makes
    pskb_may_pull() BUG.  From Linus Luessing.

 3) Fix off by one in ipv4 route dumping code, from Andy Whitcroft.

 4) Fix deadlock in reqsk_queue_unlink(), from Eric Dumazet.

 5) Fix ppp device deregistration wrt.  netns deletion, from Guillaume
    Nault.

 6) Fix deadlock when creating per-cpu ipv6 routes, from Martin KaFai
    Lau.

 7) Fix memory leak in batman-adv code, from Sven Eckelmann.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  batman-adv: Fix memory leak on tt add with invalid vlan
  net: phy: fix semicolon.cocci warnings
  net: qmi_wwan: add HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module
  be2net: avoid vxlan offloading on multichannel configs
  ipv6: Fix a potential deadlock when creating pcpu rt
  ipv6: Add rt6_make_pcpu_route()
  ipv6: Remove un-used argument from ip6_dst_alloc()
  net: phy: workaround for buggy cable detection by LAN8700 after cable plugging
  net: ethernet: micrel: fix an error code
  ppp: fix device unregistration upon netns deletion
  net: phy: fix PHY_RUNNING in phy_state_machine
  Revert "net: limit tcp/udp rmem/wmem to SOCK_{RCV,SND}BUF_MIN"
  inet: fix potential deadlock in reqsk_queue_unlink()
  gianfar: Restore link state settings after MAC reset
  ipv4: off-by-one in continuation handling in /proc/net/route
  net: fix wrong skb_get() usage / crash in IGMP/MLD parsing code
  mac80211: fix invalid read in minstrel_sort_best_tp_rates()
  • Loading branch information
torvalds committed Aug 20, 2015
2 parents 3d3e66b + fd7dec2 commit 28e55d0
Show file tree
Hide file tree
Showing 18 changed files with 212 additions and 146 deletions.
4 changes: 2 additions & 2 deletions drivers/net/ethernet/emulex/benet/be_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5174,7 +5174,7 @@ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
struct device *dev = &adapter->pdev->dev;
int status;

if (lancer_chip(adapter) || BEx_chip(adapter))
if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter))
return;

if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) {
Expand Down Expand Up @@ -5221,7 +5221,7 @@ static void be_del_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
{
struct be_adapter *adapter = netdev_priv(netdev);

if (lancer_chip(adapter) || BEx_chip(adapter))
if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter))
return;

if (adapter->vxlan_port != port)
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/freescale/gianfar.c
Original file line number Diff line number Diff line change
Expand Up @@ -2102,6 +2102,11 @@ int startup_gfar(struct net_device *ndev)
/* Start Rx/Tx DMA and enable the interrupts */
gfar_start(priv);

/* force link state update after mac reset */
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;

phy_start(priv->phydev);

enable_napi(priv);
Expand Down
5 changes: 2 additions & 3 deletions drivers/net/ethernet/micrel/ks8842.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,9 +952,8 @@ static int ks8842_alloc_dma_bufs(struct net_device *netdev)

sg_dma_address(&tx_ctl->sg) = dma_map_single(adapter->dev,
tx_ctl->buf, DMA_BUFFER_SIZE, DMA_TO_DEVICE);
err = dma_mapping_error(adapter->dev,
sg_dma_address(&tx_ctl->sg));
if (err) {
if (dma_mapping_error(adapter->dev, sg_dma_address(&tx_ctl->sg))) {
err = -ENOMEM;
sg_dma_address(&tx_ctl->sg) = 0;
goto err;
}
Expand Down
16 changes: 12 additions & 4 deletions drivers/net/phy/phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,7 @@ void phy_state_machine(struct work_struct *work)
bool needs_aneg = false, do_suspend = false;
enum phy_state old_state;
int err = 0;
int old_link;

mutex_lock(&phydev->lock);

Expand Down Expand Up @@ -896,11 +897,18 @@ void phy_state_machine(struct work_struct *work)
phydev->adjust_link(phydev->attached_dev);
break;
case PHY_RUNNING:
/* Only register a CHANGE if we are
* polling or ignoring interrupts
/* Only register a CHANGE if we are polling or ignoring
* interrupts and link changed since latest checking.
*/
if (!phy_interrupt_is_valid(phydev))
phydev->state = PHY_CHANGELINK;
if (!phy_interrupt_is_valid(phydev)) {
old_link = phydev->link;
err = phy_read_status(phydev);
if (err)
break;

if (old_link != phydev->link)
phydev->state = PHY_CHANGELINK;
}
break;
case PHY_CHANGELINK:
err = phy_read_status(phydev);
Expand Down
31 changes: 19 additions & 12 deletions drivers/net/phy/smsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,18 @@ static int lan911x_config_init(struct phy_device *phydev)
}

/*
* The LAN8710/LAN8720 requires a minimum of 2 link pulses within 64ms of each
* other in order to set the ENERGYON bit and exit EDPD mode. If a link partner
* does send the pulses within this interval, the PHY will remained powered
* down.
*
* This workaround will manually toggle the PHY on/off upon calls to read_status
* in order to generate link test pulses if the link is down. If a link partner
* is present, it will respond to the pulses, which will cause the ENERGYON bit
* to be set and will cause the EDPD mode to be exited.
* The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable
* plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to
* unstable detection of plugging in Ethernet cable.
* This workaround disables Energy Detect Power-Down mode and waiting for
* response on link pulses to detect presence of plugged Ethernet cable.
* The Energy Detect Power-Down mode is enabled again in the end of procedure to
* save approximately 220 mW of power if cable is unplugged.
*/
static int lan87xx_read_status(struct phy_device *phydev)
{
int err = genphy_read_status(phydev);
int i;

if (!phydev->link) {
/* Disable EDPD to wake up PHY */
Expand All @@ -116,8 +115,16 @@ static int lan87xx_read_status(struct phy_device *phydev)
if (rc < 0)
return rc;

/* Sleep 64 ms to allow ~5 link test pulses to be sent */
msleep(64);
/* Wait max 640 ms to detect energy */
for (i = 0; i < 64; i++) {
/* Sleep to allow link test pulses to be sent */
msleep(10);
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
if (rc < 0)
return rc;
if (rc & MII_LAN83C185_ENERGYON)
break;
}

/* Re-enable EDPD */
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
Expand Down Expand Up @@ -191,7 +198,7 @@ static struct phy_driver smsc_phy_driver[] = {

/* basic functions */
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
.read_status = lan87xx_read_status,
.config_init = smsc_phy_config_init,
.soft_reset = smsc_phy_reset,

Expand Down
78 changes: 42 additions & 36 deletions drivers/net/ppp/ppp_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,9 @@ static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound);
static void ppp_ccp_closed(struct ppp *ppp);
static struct compressor *find_compressor(int type);
static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st);
static struct ppp *ppp_create_interface(struct net *net, int unit, int *retp);
static struct ppp *ppp_create_interface(struct net *net, int unit,
struct file *file, int *retp);
static void init_ppp_file(struct ppp_file *pf, int kind);
static void ppp_shutdown_interface(struct ppp *ppp);
static void ppp_destroy_interface(struct ppp *ppp);
static struct ppp *ppp_find_unit(struct ppp_net *pn, int unit);
static struct channel *ppp_find_channel(struct ppp_net *pn, int unit);
Expand Down Expand Up @@ -392,8 +392,10 @@ static int ppp_release(struct inode *unused, struct file *file)
file->private_data = NULL;
if (pf->kind == INTERFACE) {
ppp = PF_TO_PPP(pf);
rtnl_lock();
if (file == ppp->owner)
ppp_shutdown_interface(ppp);
unregister_netdevice(ppp->dev);
rtnl_unlock();
}
if (atomic_dec_and_test(&pf->refcnt)) {
switch (pf->kind) {
Expand Down Expand Up @@ -593,8 +595,10 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
mutex_lock(&ppp_mutex);
if (pf->kind == INTERFACE) {
ppp = PF_TO_PPP(pf);
rtnl_lock();
if (file == ppp->owner)
ppp_shutdown_interface(ppp);
unregister_netdevice(ppp->dev);
rtnl_unlock();
}
if (atomic_long_read(&file->f_count) < 2) {
ppp_release(NULL, file);
Expand Down Expand Up @@ -838,11 +842,10 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
/* Create a new ppp unit */
if (get_user(unit, p))
break;
ppp = ppp_create_interface(net, unit, &err);
ppp = ppp_create_interface(net, unit, file, &err);
if (!ppp)
break;
file->private_data = &ppp->file;
ppp->owner = file;
err = -EFAULT;
if (put_user(ppp->file.index, p))
break;
Expand Down Expand Up @@ -916,6 +919,16 @@ static __net_init int ppp_init_net(struct net *net)
static __net_exit void ppp_exit_net(struct net *net)
{
struct ppp_net *pn = net_generic(net, ppp_net_id);
struct ppp *ppp;
LIST_HEAD(list);
int id;

rtnl_lock();
idr_for_each_entry(&pn->units_idr, ppp, id)
unregister_netdevice_queue(ppp->dev, &list);

unregister_netdevice_many(&list);
rtnl_unlock();

idr_destroy(&pn->units_idr);
}
Expand Down Expand Up @@ -1088,8 +1101,28 @@ static int ppp_dev_init(struct net_device *dev)
return 0;
}

static void ppp_dev_uninit(struct net_device *dev)
{
struct ppp *ppp = netdev_priv(dev);
struct ppp_net *pn = ppp_pernet(ppp->ppp_net);

ppp_lock(ppp);
ppp->closing = 1;
ppp_unlock(ppp);

mutex_lock(&pn->all_ppp_mutex);
unit_put(&pn->units_idr, ppp->file.index);
mutex_unlock(&pn->all_ppp_mutex);

ppp->owner = NULL;

ppp->file.dead = 1;
wake_up_interruptible(&ppp->file.rwait);
}

static const struct net_device_ops ppp_netdev_ops = {
.ndo_init = ppp_dev_init,
.ndo_uninit = ppp_dev_uninit,
.ndo_start_xmit = ppp_start_xmit,
.ndo_do_ioctl = ppp_net_ioctl,
.ndo_get_stats64 = ppp_get_stats64,
Expand Down Expand Up @@ -2667,8 +2700,8 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
* or if there is already a unit with the requested number.
* unit == -1 means allocate a new number.
*/
static struct ppp *
ppp_create_interface(struct net *net, int unit, int *retp)
static struct ppp *ppp_create_interface(struct net *net, int unit,
struct file *file, int *retp)
{
struct ppp *ppp;
struct ppp_net *pn;
Expand All @@ -2688,6 +2721,7 @@ ppp_create_interface(struct net *net, int unit, int *retp)
ppp->mru = PPP_MRU;
init_ppp_file(&ppp->file, INTERFACE);
ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */
ppp->owner = file;
for (i = 0; i < NUM_NP; ++i)
ppp->npmode[i] = NPMODE_PASS;
INIT_LIST_HEAD(&ppp->channels);
Expand Down Expand Up @@ -2775,34 +2809,6 @@ init_ppp_file(struct ppp_file *pf, int kind)
init_waitqueue_head(&pf->rwait);
}

/*
* Take down a ppp interface unit - called when the owning file
* (the one that created the unit) is closed or detached.
*/
static void ppp_shutdown_interface(struct ppp *ppp)
{
struct ppp_net *pn;

pn = ppp_pernet(ppp->ppp_net);
mutex_lock(&pn->all_ppp_mutex);

/* This will call dev_close() for us. */
ppp_lock(ppp);
if (!ppp->closing) {
ppp->closing = 1;
ppp_unlock(ppp);
unregister_netdev(ppp->dev);
unit_put(&pn->units_idr, ppp->file.index);
} else
ppp_unlock(ppp);

ppp->file.dead = 1;
ppp->owner = NULL;
wake_up_interruptible(&ppp->file.rwait);

mutex_unlock(&pn->all_ppp_mutex);
}

/*
* Free the memory used by a ppp unit. This is only called once
* there are no channels connected to the unit and no file structs
Expand Down
1 change: 1 addition & 0 deletions drivers/net/usb/qmi_wwan.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,7 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x413c, 0x81a4, 8)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
{QMI_FIXED_INTF(0x413c, 0x81a8, 8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
{QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
{QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
{QMI_FIXED_INTF(0x03f0, 0x581d, 4)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */

/* 4. Gobi 1000 devices */
Expand Down
5 changes: 4 additions & 1 deletion net/batman-adv/translation-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,8 +595,11 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
/* increase the refcounter of the related vlan */
vlan = batadv_softif_vlan_get(bat_priv, vid);
if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d",
addr, BATADV_PRINT_VID(vid)))
addr, BATADV_PRINT_VID(vid))) {
kfree(tt_local);
tt_local = NULL;
goto out;
}

batadv_dbg(BATADV_DBG_TT, bat_priv,
"Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
Expand Down
4 changes: 2 additions & 2 deletions net/bridge/br_multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -1591,7 +1591,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
break;
}

if (skb_trimmed)
if (skb_trimmed && skb_trimmed != skb)
kfree_skb(skb_trimmed);

return err;
Expand Down Expand Up @@ -1636,7 +1636,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
break;
}

if (skb_trimmed)
if (skb_trimmed && skb_trimmed != skb)
kfree_skb(skb_trimmed);

return err;
Expand Down
37 changes: 18 additions & 19 deletions net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -4022,8 +4022,8 @@ EXPORT_SYMBOL(skb_checksum_setup);
* Otherwise returns the provided skb. Returns NULL in error cases
* (e.g. transport_len exceeds skb length or out-of-memory).
*
* Caller needs to set the skb transport header and release the returned skb.
* Provided skb is consumed.
* Caller needs to set the skb transport header and free any returned skb if it
* differs from the provided skb.
*/
static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb,
unsigned int transport_len)
Expand All @@ -4032,16 +4032,12 @@ static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb,
unsigned int len = skb_transport_offset(skb) + transport_len;
int ret;

if (skb->len < len) {
kfree_skb(skb);
if (skb->len < len)
return NULL;
} else if (skb->len == len) {
else if (skb->len == len)
return skb;
}

skb_chk = skb_clone(skb, GFP_ATOMIC);
kfree_skb(skb);

if (!skb_chk)
return NULL;

Expand All @@ -4066,8 +4062,8 @@ static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb,
* If the skb has data beyond the given transport length, then a
* trimmed & cloned skb is checked and returned.
*
* Caller needs to set the skb transport header and release the returned skb.
* Provided skb is consumed.
* Caller needs to set the skb transport header and free any returned skb if it
* differs from the provided skb.
*/
struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb,
unsigned int transport_len,
Expand All @@ -4079,23 +4075,26 @@ struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb,

skb_chk = skb_checksum_maybe_trim(skb, transport_len);
if (!skb_chk)
return NULL;
goto err;

if (!pskb_may_pull(skb_chk, offset)) {
kfree_skb(skb_chk);
return NULL;
}
if (!pskb_may_pull(skb_chk, offset))
goto err;

__skb_pull(skb_chk, offset);
ret = skb_chkf(skb_chk);
__skb_push(skb_chk, offset);

if (ret) {
kfree_skb(skb_chk);
return NULL;
}
if (ret)
goto err;

return skb_chk;

err:
if (skb_chk && skb_chk != skb)
kfree_skb(skb_chk);

return NULL;

}
EXPORT_SYMBOL(skb_checksum_trimmed);

Expand Down
Loading

0 comments on commit 28e55d0

Please sign in to comment.