Skip to content

Commit c579bc7

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking changes from David Miller: "1) icmp6_dst_alloc() returns NULL instead of ERR_PTR() leading to crashes, particularly during shutdown. Reported by Dave Jones and fixed by Eric Dumazet. 2) hyperv and wimax/i2400m return NETDEV_TX_BUSY when they have already freed the SKB, which causes crashes as to the caller this means requeue the packet. Fixes from Eric Dumazet. 3) usbnet driver doesn't allocate the right amount of headroom on fresh RX SKBs, fix from Eric Dumazet. 4) Fix regression in ip6_mc_find_dev_rcu(), as an RCU lookup it abolutely should not take a reference to 'dev', this leads to leaks. Fix from RonQing Li. 5) Fix netfilter ctnetlink race between delete and timeout expiration. From Pablo Neira Ayuso. 6) Revert SFQ change which causes regressions, specifically queueing to tail can lead to unavoidable flow starvation. From Eric Dumazet. 7) Fix a memory leak and a crash on corrupt firmware files in bnx2x, from Michal Schmidt." * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: netfilter: ctnetlink: fix race between delete and timeout expiration ipv6: Don't dev_hold(dev) in ip6_mc_find_dev_rcu. wimax/i2400m: fix erroneous NETDEV_TX_BUSY use net/hyperv: fix erroneous NETDEV_TX_BUSY use net/usbnet: reserve headroom on rx skbs bnx2x: fix memory leak in bnx2x_init_firmware() bnx2x: fix a crash on corrupt firmware file sch_sfq: revert dont put new flow at the end of flows ipv6: fix icmp6_dst_alloc()
2 parents 96ee049 + a16a164 commit c579bc7

File tree

8 files changed

+57
-64
lines changed

8 files changed

+57
-64
lines changed

drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10824,38 +10824,36 @@ do { \
1082410824

1082510825
int bnx2x_init_firmware(struct bnx2x *bp)
1082610826
{
10827+
const char *fw_file_name;
1082710828
struct bnx2x_fw_file_hdr *fw_hdr;
1082810829
int rc;
1082910830

10831+
if (bp->firmware)
10832+
return 0;
1083010833

10831-
if (!bp->firmware) {
10832-
const char *fw_file_name;
10833-
10834-
if (CHIP_IS_E1(bp))
10835-
fw_file_name = FW_FILE_NAME_E1;
10836-
else if (CHIP_IS_E1H(bp))
10837-
fw_file_name = FW_FILE_NAME_E1H;
10838-
else if (!CHIP_IS_E1x(bp))
10839-
fw_file_name = FW_FILE_NAME_E2;
10840-
else {
10841-
BNX2X_ERR("Unsupported chip revision\n");
10842-
return -EINVAL;
10843-
}
10844-
BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
10834+
if (CHIP_IS_E1(bp))
10835+
fw_file_name = FW_FILE_NAME_E1;
10836+
else if (CHIP_IS_E1H(bp))
10837+
fw_file_name = FW_FILE_NAME_E1H;
10838+
else if (!CHIP_IS_E1x(bp))
10839+
fw_file_name = FW_FILE_NAME_E2;
10840+
else {
10841+
BNX2X_ERR("Unsupported chip revision\n");
10842+
return -EINVAL;
10843+
}
10844+
BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
1084510845

10846-
rc = request_firmware(&bp->firmware, fw_file_name,
10847-
&bp->pdev->dev);
10848-
if (rc) {
10849-
BNX2X_ERR("Can't load firmware file %s\n",
10850-
fw_file_name);
10851-
goto request_firmware_exit;
10852-
}
10846+
rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev);
10847+
if (rc) {
10848+
BNX2X_ERR("Can't load firmware file %s\n",
10849+
fw_file_name);
10850+
goto request_firmware_exit;
10851+
}
1085310852

10854-
rc = bnx2x_check_firmware(bp);
10855-
if (rc) {
10856-
BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
10857-
goto request_firmware_exit;
10858-
}
10853+
rc = bnx2x_check_firmware(bp);
10854+
if (rc) {
10855+
BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
10856+
goto request_firmware_exit;
1085910857
}
1086010858

1086110859
fw_hdr = (struct bnx2x_fw_file_hdr *)bp->firmware->data;
@@ -10901,6 +10899,7 @@ int bnx2x_init_firmware(struct bnx2x *bp)
1090110899
kfree(bp->init_data);
1090210900
request_firmware_exit:
1090310901
release_firmware(bp->firmware);
10902+
bp->firmware = NULL;
1090410903

1090510904
return rc;
1090610905
}

drivers/net/hyperv/netvsc_drv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
166166

167167
dev_kfree_skb(skb);
168168
net->stats.tx_dropped++;
169-
return NETDEV_TX_BUSY;
169+
return NETDEV_TX_OK;
170170
}
171171

172172
packet->extension = (void *)(unsigned long)packet +
@@ -226,7 +226,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
226226
dev_kfree_skb_any(skb);
227227
}
228228

229-
return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK;
229+
return NETDEV_TX_OK;
230230
}
231231

232232
/*

drivers/net/usb/usbnet.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,13 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
328328
unsigned long lockflags;
329329
size_t size = dev->rx_urb_size;
330330

331-
if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
331+
skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);
332+
if (!skb) {
332333
netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
333334
usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
334335
usb_free_urb (urb);
335336
return -ENOMEM;
336337
}
337-
skb_reserve (skb, NET_IP_ALIGN);
338338

339339
entry = (struct skb_data *) skb->cb;
340340
entry->urb = urb;

drivers/net/wimax/i2400m/netdev.c

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -367,38 +367,28 @@ netdev_tx_t i2400m_hard_start_xmit(struct sk_buff *skb,
367367
{
368368
struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
369369
struct device *dev = i2400m_dev(i2400m);
370-
int result;
370+
int result = -1;
371371

372372
d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev);
373-
if (skb_header_cloned(skb)) {
374-
/*
375-
* Make tcpdump/wireshark happy -- if they are
376-
* running, the skb is cloned and we will overwrite
377-
* the mac fields in i2400m_tx_prep_header. Expand
378-
* seems to fix this...
379-
*/
380-
result = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
381-
if (result) {
382-
result = NETDEV_TX_BUSY;
383-
goto error_expand;
384-
}
385-
}
373+
374+
if (skb_header_cloned(skb) &&
375+
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
376+
goto drop;
386377

387378
if (i2400m->state == I2400M_SS_IDLE)
388379
result = i2400m_net_wake_tx(i2400m, net_dev, skb);
389380
else
390381
result = i2400m_net_tx(i2400m, net_dev, skb);
391-
if (result < 0)
382+
if (result < 0) {
383+
drop:
392384
net_dev->stats.tx_dropped++;
393-
else {
385+
} else {
394386
net_dev->stats.tx_packets++;
395387
net_dev->stats.tx_bytes += skb->len;
396388
}
397-
result = NETDEV_TX_OK;
398-
error_expand:
399-
kfree_skb(skb);
389+
dev_kfree_skb(skb);
400390
d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result);
401-
return result;
391+
return NETDEV_TX_OK;
402392
}
403393

404394

net/ipv6/mcast.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net,
257257

258258
if (rt) {
259259
dev = rt->dst.dev;
260-
dev_hold(dev);
261260
dst_release(&rt->dst);
262261
}
263262
} else

net/ipv6/route.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
10771077
struct net *net = dev_net(dev);
10781078

10791079
if (unlikely(!idev))
1080-
return NULL;
1080+
return ERR_PTR(-ENODEV);
10811081

10821082
rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0);
10831083
if (unlikely(!rt)) {

net/netfilter/nf_conntrack_netlink.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -943,20 +943,21 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
943943
}
944944
}
945945

946-
if (nf_conntrack_event_report(IPCT_DESTROY, ct,
947-
NETLINK_CB(skb).pid,
948-
nlmsg_report(nlh)) < 0) {
946+
if (del_timer(&ct->timeout)) {
947+
if (nf_conntrack_event_report(IPCT_DESTROY, ct,
948+
NETLINK_CB(skb).pid,
949+
nlmsg_report(nlh)) < 0) {
950+
nf_ct_delete_from_lists(ct);
951+
/* we failed to report the event, try later */
952+
nf_ct_insert_dying_list(ct);
953+
nf_ct_put(ct);
954+
return 0;
955+
}
956+
/* death_by_timeout would report the event again */
957+
set_bit(IPS_DYING_BIT, &ct->status);
949958
nf_ct_delete_from_lists(ct);
950-
/* we failed to report the event, try later */
951-
nf_ct_insert_dying_list(ct);
952959
nf_ct_put(ct);
953-
return 0;
954960
}
955-
956-
/* death_by_timeout would report the event again */
957-
set_bit(IPS_DYING_BIT, &ct->status);
958-
959-
nf_ct_kill(ct);
960961
nf_ct_put(ct);
961962

962963
return 0;

net/sched/sch_sfq.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,11 +469,15 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
469469
if (slot->qlen == 1) { /* The flow is new */
470470
if (q->tail == NULL) { /* It is the first flow */
471471
slot->next = x;
472-
q->tail = slot;
473472
} else {
474473
slot->next = q->tail->next;
475474
q->tail->next = x;
476475
}
476+
/* We put this flow at the end of our flow list.
477+
* This might sound unfair for a new flow to wait after old ones,
478+
* but we could endup servicing new flows only, and freeze old ones.
479+
*/
480+
q->tail = slot;
477481
/* We could use a bigger initial quantum for new flows */
478482
slot->allot = q->scaled_quantum;
479483
}

0 commit comments

Comments
 (0)