4.8.8-stable review
Subsystems (4)
Greg Kroah-Hartman
maintainercover 4.8.8-stable review
This is the start of the stable review cycle for the 4.8.8 release. There are 35 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Tue Nov 15 11:24:10 UTC 2016. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.8.8-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.8.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 4.8.8-rc1
Felipe Balbi <[email protected]>
usb: dwc3: gadget: properly account queued requests
Ivan Vecera <[email protected]>
arch/powerpc: Update parameters for csum_tcpudp_magic & csum_tcpudp_nofold
Willem de Bruijn <[email protected]>
packet: on direct_xmit, limit tso and csum to supported devices
Eli Cooper <[email protected]>
ip6_tunnel: Update skb->protocol to ETH_P_IPV6 in ip6_tnl_xmit()
Marcelo Ricardo Leitner <[email protected]>
sctp: validate chunk len before actually using it
Jamal Hadi Salim <[email protected]>
net sched filters: fix notification of filter delete with proper handle
David Ahern <[email protected]>
net: ipv6: Do not consider link state for nexthop validation
Tobias Brunner <[email protected]>
macsec: Fix header length if SCI is added if explicitly disabled
Stephen Hemminger <[email protected]>
netvsc: fix incorrect receive checksum offloading
Eric Dumazet <[email protected]>
udp: fix IP_CHECKSUM handling
Xin Long <[email protected]>
sctp: fix the panic caused by route update
Jiri Slaby <[email protected]>
net: sctp, forbid negative length
Fabio Estevam <[email protected]>
net: fec: Call swap_buffer() prior to IP header alignment
WANG Cong <[email protected]>
ipv4: use the right lock for ping_group_range
Eric Dumazet <[email protected]>
ipv4: disable BH in set_ping_group_range()
Sabrina Dubroca <[email protected]>
net: add recursion limit to GRO
Ido Schimmel <[email protected]>
net: core: Correctly iterate over lower adjacency list
Jiri Pirko <[email protected]>
rtnetlink: Add rtnexthop offload flag to compare mask
Ido Schimmel <[email protected]>
switchdev: Execute bridge ndos only for bridge ports
Nikolay Aleksandrov <[email protected]>
bridge: multicast: restore perm router ports on multicast enable
Eric Dumazet <[email protected]>
net: pktgen: remove rcu locking in pktgen_change_name()
Brenden Blanco <[email protected]>
net/mlx4_en: fixup xdp tx irq to match rx
Paolo Abeni <[email protected]>
IB/ipoib: move back IB LL address into the hard header
Nicolas Dichtel <[email protected]>
ipv6: correctly add local routes when lo goes up
Vadim Fedorenko <[email protected]>
ip6_tunnel: fix ip6_tnl_lookup
Andrew Lunn <[email protected]>
net: phy: Trigger state machine on state change and not polling.
Eric Dumazet <[email protected]>
ipv6: tcp: restore IP6CB for pktoptions skbs
WANG Cong <[email protected]>
net_sched: reorder pernet ops and act ops registrations
Vlad Tsyrklevich <[email protected]>
drivers/ptp: Fix kernel memory disclosure
Eric Dumazet <[email protected]>
netlink: do not enter direct reclaim from netlink_dump()
Anoob Soman <[email protected]>
packet: call fanout_release, while UNREGISTERING a netdev
Andrew Collins <[email protected]>
net: Add netdev all_adj_list refcnt propagation to fix panic
Shmulik Ladkani <[email protected]>
net/sched: act_vlan: Push skb->data to mac_header prior calling skb_vlan_*() functions
Paolo Abeni <[email protected]>
net: pktgen: fix pkt_size
Gavin Schenk <[email protected]>
net: fec: set mac address unconditionally
-------------
Diffstat:
Makefile | 4 +- arch/powerpc/include/asm/checksum.h | 12 ++-- drivers/infiniband/ulp/ipoib/ipoib.h | 20 +++++-- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 15 ++--- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 12 ++-- drivers/infiniband/ulp/ipoib/ipoib_main.c | 54 ++++++++++------- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 6 +- drivers/net/ethernet/freescale/fec_main.c | 18 +++--- drivers/net/ethernet/mellanox/mlx4/en_cq.c | 10 +++- drivers/net/geneve.c | 2 +- drivers/net/hyperv/netvsc_drv.c | 19 +++--- drivers/net/macsec.c | 26 ++++++--- drivers/net/phy/phy.c | 22 ++++++- drivers/net/vxlan.c | 2 +- drivers/ptp/ptp_chardev.c | 1 + drivers/usb/dwc3/gadget.c | 7 ++- include/linux/netdevice.h | 41 ++++++++++++- include/net/ip.h | 4 +- include/net/ip6_route.h | 1 + include/uapi/linux/rtnetlink.h | 2 +- net/8021q/vlan.c | 2 +- net/bridge/br_multicast.c | 23 +++++--- net/core/dev.c | 80 +++++++++++++++----------- net/core/pktgen.c | 38 ++++++------ net/ethernet/eth.c | 2 +- net/ipv4/af_inet.c | 2 +- net/ipv4/fou.c | 4 +- net/ipv4/gre_offload.c | 2 +- net/ipv4/ip_sockglue.c | 11 ++-- net/ipv4/sysctl_net_ipv4.c | 8 +-- net/ipv4/udp.c | 2 +- net/ipv4/udp_offload.c | 2 +- net/ipv6/addrconf.c | 2 +- net/ipv6/ip6_offload.c | 2 +- net/ipv6/ip6_tunnel.c | 3 + net/ipv6/route.c | 6 +- net/ipv6/tcp_ipv6.c | 20 ++++--- net/ipv6/udp.c | 3 +- net/netlink/af_netlink.c | 7 ++- net/packet/af_packet.c | 10 ++-- net/sched/act_api.c | 19 +++--- net/sched/act_vlan.c | 9 +++ net/sched/cls_api.c | 3 +- net/sctp/output.c | 8 ++- net/sctp/sm_statefuns.c | 12 ++-- net/sctp/socket.c | 5 +- net/switchdev/switchdev.c | 9 +++ 47 files changed, 363 insertions(+), 209 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 2/35 net: pktgen: fix pkt_size
4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Abeni <[email protected]>
[ Upstream commit 63d75463c91a5b5be7c0aca11ceb45ea5a0ae81d ]
The commit 879c7220e828 ("net: pktgen: Observe needed_headroom of the device") increased the 'pkt_overhead' field value by LL_RESERVED_SPACE.
As a side effect the generated packet size, computed as:
/* Eth + IPh + UDPh + mpls */ datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 - pkt_dev->pkt_overhead;
is decreased by the same value.
The above changed slightly the behavior of existing pktgen users, and made the procfs interface somewhat inconsistent. Fix it by restoring the previous pkt_overhead value and using LL_RESERVED_SPACE as extralen in skb allocation.
Also, change pktgen_alloc_skb() to only partially reserve the headroom to allow the caller to prefetch from ll header start.
v1 -> v2:
- fixed some typos in the comments
--- net/core/pktgen.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-)
net/core/pktgen.c +10 -11
@@ -2286,7 +2286,7 @@ out:static inline void set_pkt_overhead (struct pktgen_dev *pkt_dev) { - pkt_dev->pkt_overhead =LL_RESERVED_SPACE (pkt_dev->odev); + pkt_dev->pkt_overhead =0 ; pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof (u32); pkt_dev->pkt_overhead +=VLAN_TAG_SIZE (pkt_dev); pkt_dev->pkt_overhead +=SVLAN_TAG_SIZE (pkt_dev);
@@ -2777,13 +2777,13 @@ static void pktgen_finalize_skb(struct p }static struct sk_buff *pktgen_alloc_skb (struct net_device *dev, -struct pktgen_dev *pkt_dev, -unsigned int extralen) +struct pktgen_dev *pkt_dev) { +unsigned int extralen =LL_RESERVED_SPACE (dev);struct sk_buff *skb =NULL ; -unsigned int size = pkt_dev->cur_pkt_size +64 + extralen + - pkt_dev->pkt_overhead; +unsigned int size; + size = pkt_dev->cur_pkt_size +64 + extralen + pkt_dev->pkt_overhead;if (pkt_dev->flags &F_NODE ) {int node = pkt_dev->node >=0 ? pkt_dev->node :numa_node_id ();
@@ -2796,8 +2796,9 @@ static struct sk_buff *pktgen_alloc_skb( skb =__netdev_alloc_skb (dev, size,GFP_NOWAIT ); } +/* the caller pre-fetches from skb->data and reserves for the mac hdr */ if (likely (skb)) -skb_reserve (skb,LL_RESERVED_SPACE (dev)); +skb_reserve (skb, extralen -16 );return skb; }
@@ -2830,16 +2831,14 @@ static struct sk_buff *fill_packet_ipv4(mod_cur_headers (pkt_dev); queue_map = pkt_dev->cur_queue_map; - datalen = (odev->hard_header_len +16 ) & ~0xf ; - - skb =pktgen_alloc_skb (odev, pkt_dev, datalen); + skb =pktgen_alloc_skb (odev, pkt_dev);if (!skb) {sprintf (pkt_dev->result,"No memory" );return NULL ; }prefetchw (skb->data); -skb_reserve (skb, datalen); +skb_reserve (skb,16 );/* Reserve for ethernet and IP header */ eth = (__u8 *)skb_push (skb,14 );
@@ -2959,7 +2958,7 @@ static struct sk_buff *fill_packet_ipv6(mod_cur_headers (pkt_dev); queue_map = pkt_dev->cur_queue_map; - skb =pktgen_alloc_skb (odev, pkt_dev,16 ); + skb =pktgen_alloc_skb (odev, pkt_dev);if (!skb) {sprintf (pkt_dev->result,"No memory" );return NULL ;
Greg Kroah-Hartman
maintainerPATCH 3/35 net/sched: act_vlan: Push skb->data to mac_header prior calling skb_vlan_*() functions
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shmulik Ladkani <[email protected]>
[ Upstream commit f39acc84aad10710e89835c60d3b6694c43a8dd9 ]
Generic skb_vlan_push/skb_vlan_pop functions don't properly handle the case where the input skb data pointer does not point at the mac header:
- They're doing push/pop, but fail to properly unwind data back to its original location.
For example, in the skb_vlan_push case, any subsequent 'skb_push(skb, skb->mac_len)' calls make the skb->data point 4 bytes BEFORE start of frame, leading to bogus frames that may be transmitted.
- They update rcsum per the added/removed 4 bytes tag. Alas if data is originally after the vlan/eth headers, then these bytes were already pulled out of the csum.
OTOH calling skb_vlan_push/skb_vlan_pop with skb->data at mac_header present no issues.
act_vlan is the only caller to skb_vlan_*() that has skb->data pointing at network header (upon ingress).
Other calles (ovs, bpf) already adjust skb->data at mac_header.
This patch fixes act_vlan to point to the mac_header prior calling skb_vlan_*() functions, as other callers do.
--- net/sched/act_vlan.c | 9 +++++++++ 1 file changed, 9 insertions(+)
net/sched/act_vlan.c +9 -0
@@ -36,6 +36,12 @@ static int tcf_vlan(struct sk_buff *skb,bstats_update (&v->tcf_bstats, skb); action = v->tcf_action; +/* Ensure 'data' points at mac_header prior calling vlan manipulating +* functions. +*/ +if (skb_at_tc_ingress (skb)) +skb_push_rcsum (skb, skb->mac_len); +switch (v->tcfv_action) {case TCA_VLAN_ACT_POP : err =skb_vlan_pop (skb);
@@ -57,6 +63,9 @@ drop: action =TC_ACT_SHOT ; v->tcf_qstats.drops++; unlock: +if (skb_at_tc_ingress (skb)) +skb_pull_rcsum (skb, skb->mac_len); +spin_unlock (&v->tcf_lock);return action; }
Greg Kroah-Hartman
maintainerPATCH 4/35 net: Add netdev all_adj_list refcnt propagation to fix panic
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrew Collins <[email protected]>
[ Upstream commit 93409033ae653f1c9a949202fb537ab095b2092f ]
This is a respin of a patch to fix a relatively easily reproducible kernel panic related to the all_adj_list handling for netdevs in recent kernels.
The following sequence of commands will reproduce the issue:
ip link add link eth0 name eth0.100 type vlan id 100 ip link add link eth0 name eth0.200 type vlan id 200 ip link add name testbr type bridge
ip link set eth0.100 master testbr
ip link set eth0.200 master testbr
ip link add link testbr mac0 type macvlan
ip link delete dev testbr
This creates an upper/lower tree of (excuse the poor ASCII art):
/---eth0.100-eth0
mac0-testbr-
\---eth0.200-eth0When testbr is deleted, the all_adj_lists are walked, and eth0 is deleted twice from the mac0 list. Unfortunately, during setup in __netdev_upper_dev_link, only one reference to eth0 is added, so this results in a panic.
This change adds reference count propagation so things are handled properly.
Matthias Schiffer reported a similar crash in batman-adv:
https://github.com/freifunk-gluon/gluon/issues/680
https://www.open-mesh.org/issues/247
which this patch also seems to resolve.
--- net/core/dev.c | 68 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 31 deletions(-)
net/core/dev.c +37 -31
@@ -5578,6 +5578,7 @@ static inline bool netdev_adjacent_is_nestatic int __netdev_adjacent_dev_insert (struct net_device *dev,struct net_device *adj_dev, +u16 ref_nr,struct list_head *dev_list,void *private,bool master) {
@@ -5587,7 +5588,7 @@ static int __netdev_adjacent_dev_insert( adj =__netdev_find_adj (adj_dev, dev_list);if (adj) { - adj->ref_nr++; + adj->ref_nr += ref_nr;return 0 ; }
@@ -5597,7 +5598,7 @@ static int __netdev_adjacent_dev_insert( adj->dev = adj_dev; adj->master = master; - adj->ref_nr =1 ; + adj->ref_nr = ref_nr; adj->private = private;dev_hold (adj_dev);
@@ -5636,6 +5637,7 @@ free_adj:static void __netdev_adjacent_dev_remove (struct net_device *dev,struct net_device *adj_dev, +u16 ref_nr,struct list_head *dev_list) {struct netdev_adjacent *adj;
@@ -5648,10 +5650,10 @@ static void __netdev_adjacent_dev_removeBUG (); } -if (adj->ref_nr >1 ) { -pr_debug ("%s to %s ref_nr-- = %d\n" , dev->name, adj_dev->name, - adj->ref_nr-1 ); - adj->ref_nr--; +if (adj->ref_nr > ref_nr) { +pr_debug ("%s to %s ref_nr-%d = %d\n" , dev->name, adj_dev->name, + ref_nr, adj->ref_nr-ref_nr); + adj->ref_nr -= ref_nr;return ; }
@@ -5670,21 +5672,22 @@ static void __netdev_adjacent_dev_removestatic int __netdev_adjacent_dev_link_lists (struct net_device *dev,struct net_device *upper_dev, +u16 ref_nr,struct list_head *up_list,struct list_head *down_list,void *private,bool master) {int ret; - ret =__netdev_adjacent_dev_insert (dev, upper_dev, up_list, private, - master); + ret =__netdev_adjacent_dev_insert (dev, upper_dev, ref_nr, up_list, + private, master);if (ret)return ret; - ret =__netdev_adjacent_dev_insert (upper_dev, dev, down_list, private, - false); + ret =__netdev_adjacent_dev_insert (upper_dev, dev, ref_nr, down_list, + private, false);if (ret) { -__netdev_adjacent_dev_remove (dev, upper_dev, up_list); +__netdev_adjacent_dev_remove (dev, upper_dev, ref_nr, up_list);return ret; }
@@ -5692,9 +5695,10 @@ static int __netdev_adjacent_dev_link_li }static int __netdev_adjacent_dev_link (struct net_device *dev, -struct net_device *upper_dev) +struct net_device *upper_dev, +u16 ref_nr) { -return __netdev_adjacent_dev_link_lists (dev, upper_dev, +return __netdev_adjacent_dev_link_lists (dev, upper_dev, ref_nr, &dev->all_adj_list.upper, &upper_dev->all_adj_list.lower,NULL , false);
@@ -5702,17 +5706,19 @@ static int __netdev_adjacent_dev_link(ststatic void __netdev_adjacent_dev_unlink_lists (struct net_device *dev,struct net_device *upper_dev, +u16 ref_nr,struct list_head *up_list,struct list_head *down_list) { -__netdev_adjacent_dev_remove (dev, upper_dev, up_list); -__netdev_adjacent_dev_remove (upper_dev, dev, down_list); +__netdev_adjacent_dev_remove (dev, upper_dev, ref_nr, up_list); +__netdev_adjacent_dev_remove (upper_dev, dev, ref_nr, down_list); }static void __netdev_adjacent_dev_unlink (struct net_device *dev, -struct net_device *upper_dev) +struct net_device *upper_dev, +u16 ref_nr) { -__netdev_adjacent_dev_unlink_lists (dev, upper_dev, +__netdev_adjacent_dev_unlink_lists (dev, upper_dev, ref_nr, &dev->all_adj_list.upper, &upper_dev->all_adj_list.lower); }
@@ -5721,17 +5727,17 @@ static int __netdev_adjacent_dev_link_nestruct net_device *upper_dev, void *private, bool master) { - int ret = __netdev_adjacent_dev_link(dev, upper_dev); + int ret = __netdev_adjacent_dev_link(dev, upper_dev, 1);if (ret)return ret; - ret =__netdev_adjacent_dev_link_lists (dev, upper_dev, + ret =__netdev_adjacent_dev_link_lists (dev, upper_dev,1 , &dev->adj_list.upper, &upper_dev->adj_list.lower, private, master);if (ret) { -__netdev_adjacent_dev_unlink (dev, upper_dev); +__netdev_adjacent_dev_unlink (dev, upper_dev,1 );return ret; }
@@ -5741,8 +5747,8 @@ static int __netdev_adjacent_dev_link_nestatic void __netdev_adjacent_dev_unlink_neighbour (struct net_device *dev,struct net_device *upper_dev) { -__netdev_adjacent_dev_unlink (dev, upper_dev); -__netdev_adjacent_dev_unlink_lists (dev, upper_dev, +__netdev_adjacent_dev_unlink (dev, upper_dev,1 ); +__netdev_adjacent_dev_unlink_lists (dev, upper_dev,1 , &dev->adj_list.upper, &upper_dev->adj_list.lower); }
@@ -5795,7 +5801,7 @@ static int __netdev_upper_dev_link(struclist_for_each_entry (j, &upper_dev->all_adj_list.upper, list) {pr_debug ("Interlinking %s with %s, non-neighbour\n" , i->dev->name, j->dev->name); - ret =__netdev_adjacent_dev_link (i->dev, j->dev); + ret =__netdev_adjacent_dev_link (i->dev, j->dev, i->ref_nr);if (ret) goto rollback_mesh; }
@@ -5805,7 +5811,7 @@ static int __netdev_upper_dev_link(struclist_for_each_entry (i, &upper_dev->all_adj_list.upper, list) {pr_debug ("linking %s's upper device %s with %s\n" , upper_dev->name, i->dev->name, dev->name); - ret =__netdev_adjacent_dev_link (dev, i->dev); + ret =__netdev_adjacent_dev_link (dev, i->dev, i->ref_nr);if (ret) goto rollback_upper_mesh; }
@@ -5814,7 +5820,7 @@ static int __netdev_upper_dev_link(struclist_for_each_entry (i, &dev->all_adj_list.lower, list) {pr_debug ("linking %s's lower device %s with %s\n" , dev->name, i->dev->name, upper_dev->name); - ret =__netdev_adjacent_dev_link (i->dev, upper_dev); + ret =__netdev_adjacent_dev_link (i->dev, upper_dev, i->ref_nr);if (ret) goto rollback_lower_mesh; }
@@ -5832,7 +5838,7 @@ rollback_lower_mesh:list_for_each_entry (i, &dev->all_adj_list.lower, list) {if (i == to_i)break ; -__netdev_adjacent_dev_unlink (i->dev, upper_dev); +__netdev_adjacent_dev_unlink (i->dev, upper_dev, i->ref_nr); } i =NULL ;
@@ -5842,7 +5848,7 @@ rollback_upper_mesh:list_for_each_entry (i, &upper_dev->all_adj_list.upper, list) {if (i == to_i)break ; -__netdev_adjacent_dev_unlink (dev, i->dev); +__netdev_adjacent_dev_unlink (dev, i->dev, i->ref_nr); } i = j =NULL ;
@@ -5854,7 +5860,7 @@ rollback_mesh:list_for_each_entry (j, &upper_dev->all_adj_list.upper, list) {if (i == to_i && j == to_j)break ; -__netdev_adjacent_dev_unlink (i->dev, j->dev); +__netdev_adjacent_dev_unlink (i->dev, j->dev, i->ref_nr); }if (i == to_i)break ;
@@ -5934,16 +5940,16 @@ void netdev_upper_dev_unlink(struct net_*/ list_for_each_entry (i, &dev->all_adj_list.lower, list)list_for_each_entry (j, &upper_dev->all_adj_list.upper, list) -__netdev_adjacent_dev_unlink (i->dev, j->dev); +__netdev_adjacent_dev_unlink (i->dev, j->dev, i->ref_nr);/* remove also the devices itself from lower/upper device * list */ list_for_each_entry (i, &dev->all_adj_list.lower, list) -__netdev_adjacent_dev_unlink (i->dev, upper_dev); +__netdev_adjacent_dev_unlink (i->dev, upper_dev, i->ref_nr);list_for_each_entry (i, &upper_dev->all_adj_list.upper, list) -__netdev_adjacent_dev_unlink (dev, i->dev); +__netdev_adjacent_dev_unlink (dev, i->dev, i->ref_nr);call_netdevice_notifiers_info (NETDEV_CHANGEUPPER , dev, &changeupper_info.info);
Greg Kroah-Hartman
maintainerPATCH 5/35 packet: call fanout_release, while UNREGISTERING a netdev
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anoob Soman <[email protected]>
[ Upstream commit 6664498280cf17a59c3e7cf1a931444c02633ed1 ]
If a socket has FANOUT sockopt set, a new proto_hook is registered as part of fanout_add(). When processing a NETDEV_UNREGISTER event in af_packet, __fanout_unlink is called for all sockets, but prot_hook which was registered as part of fanout_add is not removed. Call fanout_release, on a NETDEV_UNREGISTER, which removes prot_hook and removes fanout from the fanout_list.
This fixes BUG_ON(!list_empty(&dev->ptype_specific)) in netdev_run_todo()
--- net/packet/af_packet.c | 1 + 1 file changed, 1 insertion(+)
net/packet/af_packet.c +1 -0
@@ -3952,6 +3952,7 @@ static int packet_notifier(struct notifi }if (msg ==NETDEV_UNREGISTER ) {packet_cached_dev_reset (po); +fanout_release (sk); po->ifindex =-1 ;if (po->prot_hook.dev)dev_put (po->prot_hook.dev);
Greg Kroah-Hartman
maintainerPATCH 6/35 netlink: do not enter direct reclaim from netlink_dump()
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit d35c99ff77ecb2eb239731b799386f3b3637a31e ]
Since linux-3.15, netlink_dump() can use up to 16384 bytes skb allocations.
Due to struct skb_shared_info ~320 bytes overhead, we end up using order-3 (on x86) page allocations, that might trigger direct reclaim and add stress.
The intent was really to attempt a large allocation but immediately fallback to a smaller one (order-1 on x86) in case of memory stress.
On recent kernels (linux-4.4), we can remove __GFP_DIRECT_RECLAIM to meet the goal. Old kernels would need to remove __GFP_WAIT
While we are at it, since we do an order-3 allocation, allow to use all the allocated bytes instead of 16384 to reduce syscalls during large dumps.
iproute2 already uses 32KB recvmsg() buffer sizes.
Alexei provided an initial patch downsizing to SKB_WITH_OVERHEAD(16384)
--- net/netlink/af_netlink.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
net/netlink/af_netlink.c +4 -3
@@ -1832,7 +1832,7 @@ static int netlink_recvmsg(struct socket/* Record the max length of recvmsg() calls for future allocations */ nlk->max_recvmsg_len =max (nlk->max_recvmsg_len, len); nlk->max_recvmsg_len =min_t (size_t, nlk->max_recvmsg_len, -16384 ); +SKB_WITH_OVERHEAD (32768 )); copied = data_skb->len;if (len < copied) {
@@ -2083,8 +2083,9 @@ static int netlink_dump(struct sock *sk)if (alloc_min_size < nlk->max_recvmsg_len) { alloc_size = nlk->max_recvmsg_len; - skb =alloc_skb (alloc_size,GFP_KERNEL | - __GFP_NOWARN | __GFP_NORETRY); + skb =alloc_skb (alloc_size, + (GFP_KERNEL & ~__GFP_DIRECT_RECLAIM) | + __GFP_NOWARN | __GFP_NORETRY); }if (!skb) { alloc_size = alloc_min_size;
Greg Kroah-Hartman
maintainerPATCH 7/35 drivers/ptp: Fix kernel memory disclosure
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vlad Tsyrklevich <[email protected]>
[ Upstream commit 02a9079c66341836c4914c33c06a73245060df2e ]
The reserved field precise_offset->rsv is not cleared before being copied to user space, leaking kernel stack memory. Clear the struct before it's copied.
--- drivers/ptp/ptp_chardev.c | 1 + 1 file changed, 1 insertion(+)
drivers/ptp/ptp_chardev.c +1 -0
@@ -193,6 +193,7 @@ long ptp_ioctl(struct posix_clock *pc, uif (err)break ; +memset (&precise_offset,0 ,sizeof (precise_offset)); ts =ktime_to_timespec64 (xtstamp.device); precise_offset.device.sec = ts.tv_sec; precise_offset.device.nsec = ts.tv_nsec;
Greg Kroah-Hartman
maintainerPATCH 8/35 net_sched: reorder pernet ops and act ops registrations
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: WANG Cong <[email protected]>
[ Upstream commit ab102b80cef28c20b3ef7794806c3a982c6444fc ]
Krister reported a kernel NULL pointer dereference after tcf_action_init_1() invokes a_o->init(), it is a race condition where one thread calling tcf_register_action() to initialize the netns data after putting act ops in the global list and the other thread searching the list and then calling a_o->init(net, ...).
Fix this by moving the pernet ops registration before making the action ops visible. This is fine because: a) we don't rely on act_base in pernet ops->init(), b) in the worst case we have a fully initialized netns but ops is still not ready so new actions still can't be created.
--- net/sched/act_api.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
net/sched/act_api.c +11 -8
@@ -341,22 +341,25 @@ int tcf_register_action(struct tc_actionif (!act->act || !act->dump || !act->init || !act->walk || !act->lookup)return -EINVAL ; +/* We have to register pernet ops before making the action ops visible, +* otherwise tcf_action_init_1() could get a partially initialized +* netns. +*/ + ret =register_pernet_subsys (ops); +if (ret) +return ret; +write_lock (&act_mod_lock);list_for_each_entry (a, &act_base, head) {if (act->type == a->type || (strcmp (act->kind, a->kind) ==0 )) {write_unlock (&act_mod_lock); +unregister_pernet_subsys (ops);return -EEXIST ; } }list_add_tail (&act->head, &act_base);write_unlock (&act_mod_lock); - ret =register_pernet_subsys (ops); -if (ret) { -tcf_unregister_action (act, ops); -return ret; - } -return 0 ; }EXPORT_SYMBOL (tcf_register_action);
@@ -367,8 +370,6 @@ int tcf_unregister_action(struct tc_actistruct tc_action_ops *a;int err = -ENOENT ; -unregister_pernet_subsys (ops); -write_lock (&act_mod_lock);list_for_each_entry (a, &act_base, head) {if (a == act) {
@@ -378,6 +379,8 @@ int tcf_unregister_action(struct tc_acti } }write_unlock (&act_mod_lock); +if (!err) +unregister_pernet_subsys (ops);return err; }EXPORT_SYMBOL (tcf_unregister_action);
Greg Kroah-Hartman
maintainerPATCH 9/35 ipv6: tcp: restore IP6CB for pktoptions skbs
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 8ce48623f0cf3d632e32448411feddccb693d351 ]
Baozeng Ding reported following KASAN splat :
BUG: KASAN: use-after-free in ip6_datagram_recv_specific_ctl+0x13f1/0x15c0 at addr ffff880029c84ec8 Read of size 1 by task poc/25548 Call Trace: [<ffffffff82cf43c9>] dump_stack+0x12e/0x185 /lib/dump_stack.c:15 [< inline >] print_address_description /mm/kasan/report.c:204 [<ffffffff817ced3b>] kasan_report_error+0x48b/0x4b0 /mm/kasan/report.c:283 [< inline >] kasan_report /mm/kasan/report.c:303 [<ffffffff817ced9e>] __asan_report_load1_noabort+0x3e/0x40 /mm/kasan/report.c:321 [<ffffffff85c71da1>] ip6_datagram_recv_specific_ctl+0x13f1/0x15c0 /net/ipv6/datagram.c:687 [<ffffffff85c734c3>] ip6_datagram_recv_ctl+0x33/0x40 [<ffffffff85c0b07c>] do_ipv6_getsockopt.isra.4+0xaec/0x2150 [<ffffffff85c0c7f6>] ipv6_getsockopt+0x116/0x230 [<ffffffff859b5a12>] tcp_getsockopt+0x82/0xd0 /net/ipv4/tcp.c:3035 [<ffffffff855fb385>] sock_common_getsockopt+0x95/0xd0 /net/core/sock.c:2647 [< inline >] SYSC_getsockopt /net/socket.c:1776 [<ffffffff855f8ba2>] SyS_getsockopt+0x142/0x230 /net/socket.c:1758 [<ffffffff8685cdc5>] entry_SYSCALL_64_fastpath+0x23/0xc6 Memory state around the buggy address: ffff880029c84d80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ffff880029c84e00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
Quoted 1 line
ffff880029c84e80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff880029c84f00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff880029c84f80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
He also provided a syzkaller reproducer.
Issue is that ip6_datagram_recv_specific_ctl() expects to find IP6CB data that was moved at a different place in tcp_v6_rcv()
This patch moves tcp_v6_restore_cb() up and calls it from tcp_v6_do_rcv() when np->pktoptions is set.
--- net/ipv6/tcp_ipv6.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
net/ipv6/tcp_ipv6.c +11 -9
@@ -1193,6 +1193,16 @@ out:return NULL ; } +static void tcp_v6_restore_cb (struct sk_buff *skb) +{ +/* We need to move header back to the beginning if xfrm6_policy_check() +* and tcp_v6_fill_cb() are going to be called again. +* ip6_datagram_recv_specific_ctl() also expects IP6CB to be there. +*/ +memmove (IP6CB (skb), &TCP_SKB_CB (skb)->header.h6, +sizeof (struct inet6_skb_parm )); +} +/* The socket must have it's spinlock held when we get * here, unless it is a TCP_LISTEN socket. *
@@ -1322,6 +1332,7 @@ ipv6_pktoptions: np->flow_label =ip6_flowlabel (ipv6_hdr (opt_skb));if (ipv6_opt_accepted (sk, opt_skb, &TCP_SKB_CB (opt_skb)->header.h6)) {skb_set_owner_r (opt_skb, sk); +tcp_v6_restore_cb (opt_skb); opt_skb =xchg (&np->pktoptions, opt_skb); }else {__kfree_skb (opt_skb);
@@ -1355,15 +1366,6 @@ static void tcp_v6_fill_cb(struct sk_bufTCP_SKB_CB (skb)->sacked =0 ; } -static void tcp_v6_restore_cb (struct sk_buff *skb) -{ -/* We need to move header back to the beginning if xfrm6_policy_check() -* and tcp_v6_fill_cb() are going to be called again. -*/ -memmove (IP6CB (skb), &TCP_SKB_CB (skb)->header.h6, -sizeof (struct inet6_skb_parm )); -} -static int tcp_v6_rcv (struct sk_buff *skb) {const struct tcphdr *th;
Greg Kroah-Hartman
maintainerPATCH 10/35 net: phy: Trigger state machine on state change and not polling.
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrew Lunn <[email protected]>
[ Upstream commit 3c293f4e08b58ad5b78f78d89ca1fd41f87f8729 ]
The phy_start() is used to indicate the PHY is now ready to do its work. The state is changed, normally to PHY_UP which means that both the MAC and the PHY are ready.
If the phy driver is using polling, when the next poll happens, the state machine notices the PHY is now in PHY_UP, and kicks off auto-negotiation, if needed.
If however, the PHY is using interrupts, there is no polling. The phy is stuck in PHY_UP until the next interrupt comes along. And there is no reason for the PHY to interrupt.
Have phy_start() schedule the state machine to run, which both speeds up the polling use case, and makes the interrupt use case actually work.
This problems exists whenever there is a state change which will not cause an interrupt. Trigger the state machine in these cases, e.g. phy_error().
--- drivers/net/phy/phy.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-)
drivers/net/phy/phy.c +20 -2
@@ -608,6 +608,21 @@ void phy_start_machine(struct phy_device }/** +* phy_trigger_machine - trigger the state machine to run +* +* @phydev: the phy_device struct +* +* Description: There has been a change in state which requires that the +* state machine runs. +*/ + +static void phy_trigger_machine (struct phy_device *phydev) +{ +cancel_delayed_work_sync (&phydev->state_queue); +queue_delayed_work (system_power_efficient_wq, &phydev->state_queue,0 ); +} + +/** * phy_stop_machine - stop the PHY state machine tracking * @phydev: target phy_device struct *
@@ -639,6 +654,8 @@ static void phy_error(struct phy_devicemutex_lock (&phydev->lock); phydev->state =PHY_HALTED ;mutex_unlock (&phydev->lock); + +phy_trigger_machine (phydev); }/**
@@ -800,8 +817,7 @@ void phy_change(struct work_struct *work }/* reschedule state queue work to run as soon as possible */ -cancel_delayed_work_sync (&phydev->state_queue); -queue_delayed_work (system_power_efficient_wq, &phydev->state_queue,0 ); +phy_trigger_machine (phydev);return ; ignore:
@@ -890,6 +906,8 @@ void phy_start(struct phy_device *phydev/* if phy was suspended, bring the physical link up again */ if (do_resume)phy_resume (phydev); + +phy_trigger_machine (phydev); }EXPORT_SYMBOL (phy_start);
Greg Kroah-Hartman
maintainerPATCH 11/35 ip6_tunnel: fix ip6_tnl_lookup
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vadim Fedorenko <[email protected]>
[ Upstream commit 68d00f332e0ba7f60f212be74ede290c9f873bc5 ]
The commit ea3dc9601bda ("ip6_tunnel: Add support for wildcard tunnel endpoints.") introduces support for wildcards in tunnels endpoints, but in some rare circumstances ip6_tnl_lookup selects wrong tunnel interface relying only on source or destination address of the packet and not checking presence of wildcard in tunnels endpoints. Later in ip6_tnl_rcv this packets can be dicarded because of difference in ipproto even if fallback device have proper ipproto configuration.
This patch adds checks of wildcard endpoint in tunnel avoiding such behavior
--- net/ipv6/ip6_tunnel.c | 2 ++ 1 file changed, 2 insertions(+)
net/ipv6/ip6_tunnel.c +2 -0
@@ -155,6 +155,7 @@ ip6_tnl_lookup(struct net *net, const st hash =HASH (&any, local);for_each_ip6_tunnel_rcu (ip6n->tnls_r_l[hash]) {if (ipv6_addr_equal (local, &t->parms.laddr) && +ipv6_addr_any (&t->parms.raddr) && (t->dev->flags &IFF_UP ))return t; }
@@ -162,6 +163,7 @@ ip6_tnl_lookup(struct net *net, const st hash =HASH (remote, &any);for_each_ip6_tunnel_rcu (ip6n->tnls_r_l[hash]) {if (ipv6_addr_equal (remote, &t->parms.raddr) && +ipv6_addr_any (&t->parms.laddr) && (t->dev->flags &IFF_UP ))return t; }
Greg Kroah-Hartman
maintainerPATCH 12/35 ipv6: correctly add local routes when lo goes up
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Dichtel <[email protected]>
[ Upstream commit a220445f9f4382c36a53d8ef3e08165fa27f7e2c ]
The goal of the patch is to fix this scenario:
ip link add dummy1 type dummy
ip link set dummy1 up
ip link set lo down ; ip link set lo up
After that sequence, the local route to the link layer address of dummy1 is not there anymore.
When the loopback is set down, all local routes are deleted by addrconf_ifdown()/rt6_ifdown(). At this time, the rt6_info entry still exists, because the corresponding idev has a reference on it. After the rcu grace period, dst_rcu_free() is called, and thus ___dst_free(), which will set obsolete to DST_OBSOLETE_DEAD.
In this case, init_loopback() is called before dst_rcu_free(), thus obsolete is still sets to something <= 0. So, the function doesn't add the route again. To avoid that race, let's check the rt6 refcnt instead.
--- net/ipv6/addrconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/addrconf.c +1 -1
@@ -2995,7 +2995,7 @@ static void init_loopback(struct net_dev* lo device down, release this obsolete dst and * reallocate a new router for ifa. */ -if (sp_ifa->rt->dst.obsolete >0 ) { +if (!atomic_read (&sp_ifa->rt->rt6i_ref)) {ip6_rt_put (sp_ifa->rt); sp_ifa->rt =NULL ; }else {
Greg Kroah-Hartman
maintainerPATCH 13/35 IB/ipoib: move back IB LL address into the hard header
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Abeni <[email protected]>
[ Upstream commit fc791b6335152c5278dc4a4991bcb2d329f806f9 ]
After the commit 9207f9d45b0a ("net: preserve IP control block during GSO segmentation"), the GSO CB and the IPoIB CB conflict. That destroy the IPoIB address information cached there, causing a severe performance regression, as better described here:
http://marc.info/?l=linux-kernel&m=146787279825501&w=2
This change moves the data cached by the IPoIB driver from the skb control lock into the IPoIB hard header, as done before the commit 936d7de3d736 ("IPoIB: Stop lying about hard_header_len and use skb->cb to stash LL addresses").
In order to avoid GRO issue, on packet reception, the IPoIB driver stash into the skb a dummy pseudo header, so that the received packets have actually a hard header matching the declared length. To avoid changing the connected mode maximum mtu, the allocated head buffer size is increased by the pseudo header length.
After this commit, IPoIB performances are back to pre-regression value.
v2 -> v3: rebased
v1 -> v2: avoid changing the max mtu, increasing the head buf size
--- drivers/infiniband/ulp/ipoib/ipoib.h | 20 ++++++--- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 15 +++--- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 12 ++--- drivers/infiniband/ulp/ipoib/ipoib_main.c | 54 +++++++++++++++---------- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 6 +- 5 files changed, 64 insertions(+), 43 deletions(-)
drivers/infiniband/ulp/ipoib/ipoib.h +14 -6
@@ -63,6 +63,8 @@ enum ipoib_flush_level {enum {IPOIB_ENCAP_LEN =4 , +IPOIB_PSEUDO_LEN =20 , +IPOIB_HARD_LEN =IPOIB_ENCAP_LEN +IPOIB_PSEUDO_LEN ,IPOIB_UD_HEAD_SIZE =IB_GRH_BYTES +IPOIB_ENCAP_LEN ,IPOIB_UD_RX_SG =2 ,/* max buffer needed for 4K mtu */
@@ -134,15 +136,21 @@ struct ipoib_header {u16 reserved; }; -struct ipoib_cb { -struct qdisc_skb_cb qdisc_cb; -u8 hwaddr[INFINIBAND_ALEN ]; +struct ipoib_pseudo_header { +u8 hwaddr[INFINIBAND_ALEN ]; }; -static inline struct ipoib_cb *ipoib_skb_cb (const struct sk_buff *skb) +static inline void skb_add_pseudo_hdr (struct sk_buff *skb) { -BUILD_BUG_ON (sizeof (skb->cb) <sizeof (struct ipoib_cb )); -return (struct ipoib_cb *)skb->cb; +char *data =skb_push (skb,IPOIB_PSEUDO_LEN ); + +/* +* only the ipoib header is present now, make room for a dummy +* pseudo header and set skb field accordingly +*/ +memset (data,0 ,IPOIB_PSEUDO_LEN ); +skb_reset_mac_header (skb); +skb_pull (skb,IPOIB_HARD_LEN ); }/* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
drivers/infiniband/ulp/ipoib/ipoib_cm.c +8 -7
@@ -63,6 +63,8 @@ MODULE_PARM_DESC(cm_data_debug_level,#define IPOIB_CM_RX_DELAY (3 * 256 * HZ)#define IPOIB_CM_RX_UPDATE_MASK (0x3) +#define IPOIB_CM_RX_RESERVE (ALIGN(IPOIB_HARD_LEN, 16) - IPOIB_ENCAP_LEN) +static struct ib_qp_attr ipoib_cm_err_attr = { .qp_state =IB_QPS_ERR };
@@ -146,15 +148,15 @@ static struct sk_buff *ipoib_cm_alloc_rxstruct sk_buff *skb;int i; - skb =dev_alloc_skb (IPOIB_CM_HEAD_SIZE +12 ); + skb =dev_alloc_skb (ALIGN (IPOIB_CM_HEAD_SIZE +IPOIB_PSEUDO_LEN ,16 ));if (unlikely (!skb))return NULL ;/* -* IPoIB adds a 4 byte header. So we need 12 more bytes to align the +* IPoIB adds a IPOIB_ENCAP_LEN byte header, this will align the * IP header to a multiple of 16. */ -skb_reserve (skb,12 ); +skb_reserve (skb,IPOIB_CM_RX_RESERVE ); mapping[0 ] =ib_dma_map_single (priv->ca, skb->data,IPOIB_CM_HEAD_SIZE ,DMA_FROM_DEVICE );
@@ -624,9 +626,9 @@ void ipoib_cm_handle_rx_wc(struct net_deif (wc->byte_len <IPOIB_CM_COPYBREAK ) {int dlen = wc->byte_len; - small_skb =dev_alloc_skb (dlen +12 ); + small_skb =dev_alloc_skb (dlen +IPOIB_CM_RX_RESERVE );if (small_skb) { -skb_reserve (small_skb,12 ); +skb_reserve (small_skb,IPOIB_CM_RX_RESERVE );ib_dma_sync_single_for_cpu (priv->ca, rx_ring[wr_id].mapping[0 ], dlen,DMA_FROM_DEVICE );skb_copy_from_linear_data (skb, small_skb->data, dlen);
@@ -663,8 +665,7 @@ void ipoib_cm_handle_rx_wc(struct net_de copied: skb->protocol = ((struct ipoib_header *) skb->data)->proto; -skb_reset_mac_header (skb); -skb_pull (skb,IPOIB_ENCAP_LEN ); +skb_add_pseudo_hdr (skb); ++dev->stats.rx_packets; dev->stats.rx_bytes += skb->len;
drivers/infiniband/ulp/ipoib/ipoib_ib.c +5 -7
@@ -128,16 +128,15 @@ static struct sk_buff *ipoib_alloc_rx_sk buf_size =IPOIB_UD_BUF_SIZE (priv->max_ib_mtu); - skb =dev_alloc_skb (buf_size +IPOIB_ENCAP_LEN ); + skb =dev_alloc_skb (buf_size +IPOIB_HARD_LEN );if (unlikely (!skb))return NULL ;/* -* IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte -* header. So we need 4 more bytes to get to 48 and align the -* IP header to a multiple of 16. +* the IP header will be at IPOIP_HARD_LEN + IB_GRH_BYTES, that is +* 64 bytes aligned */ -skb_reserve (skb,4 ); +skb_reserve (skb,sizeof (struct ipoib_pseudo_header )); mapping = priv->rx_ring[id].mapping; mapping[0] = ib_dma_map_single(priv->ca, skb->data, buf_size,
@@ -253,8 +252,7 @@ static void ipoib_ib_handle_rx_wc(structskb_pull (skb,IB_GRH_BYTES ); skb->protocol = ((struct ipoib_header *) skb->data)->proto; -skb_reset_mac_header (skb); -skb_pull (skb,IPOIB_ENCAP_LEN ); +skb_add_pseudo_hdr (skb); ++dev->stats.rx_packets; dev->stats.rx_bytes += skb->len;
drivers/infiniband/ulp/ipoib/ipoib_main.c +33 -21
155 lines not on this page · raw message
drivers/infiniband/ulp/ipoib/ipoib_multicast.c +4 -2
@@ -796,9 +796,11 @@ void ipoib_mcast_send(struct net_device__ipoib_mcast_add (dev, mcast);list_add_tail (&mcast->list, &priv->multicast_list); } -if (skb_queue_len (&mcast->pkt_queue) <IPOIB_MAX_MCAST_QUEUE ) +if (skb_queue_len (&mcast->pkt_queue) <IPOIB_MAX_MCAST_QUEUE ) { +/* put pseudoheader back on for next time */ +skb_push (skb,sizeof (struct ipoib_pseudo_header ));skb_queue_tail (&mcast->pkt_queue, skb); -else { + }else { ++dev->stats.tx_dropped;dev_kfree_skb_any (skb); }
Greg Kroah-Hartman
maintainerPATCH 14/35 net/mlx4_en: fixup xdp tx irq to match rx
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brenden Blanco <[email protected]>
[ Upstream commit 958b3d396d7f80755e2c2e6a8f873a669f38de10 ]
In cases where the number of tx rings is not a multiple of the number of rx rings, the tx completion event will be handled on a different core from the transmit and population of the ring. Races on the ring will lead to a double-free of the page, and possibly other corruption.
The rings are initialized by default with a valid multiple of rings, based on the number of cpus, therefore an invalid configuration requires ethtool to change the ring layout. For instance 'ethtool -L eth0 rx 9 tx 8' will cause packets received on rx0, and XDP_TX'd to tx48, to be completed on cpu3 (48 % 9 == 3).
Resolve this discrepancy by shifting the irq for the xdp tx queues to start again from 0, modulo rx_ring_num.
--- drivers/net/ethernet/mellanox/mlx4/en_cq.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/net/ethernet/mellanox/mlx4/en_cq.c +8 -0
@@ -127,7 +127,15 @@ int mlx4_en_activate_cq(struct mlx4_en_p/* For TX we use the same irq per ring we assigned for the RX */ struct mlx4_en_cq *rx_cq; +int xdp_index; +/* The xdp tx irq must align with the rx ring that forwards to +* it, so reindex these from 0. This should only happen when +* tx_ring_num is not a multiple of rx_ring_num. +*/ + xdp_index = (priv->xdp_ring_num - priv->tx_ring_num) + cq_idx; +if (xdp_index >=0 ) + cq_idx = xdp_index; cq_idx = cq_idx % priv->rx_ring_num; rx_cq = priv->rx_cq[cq_idx]; cq->vector = rx_cq->vector;
Greg Kroah-Hartman
maintainerPATCH 15/35 net: pktgen: remove rcu locking in pktgen_change_name()
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 9a0b1e8ba4061778897b544afc898de2163382f7 ]
After Jesper commit back in linux-3.18, we trigger a lockdep splat in proc_create_data() while allocating memory from pktgen_change_name().
This patch converts t->if_lock to a mutex, since it is now only used from control path, and adds proper locking to pktgen_change_name()
1) pktgen_thread_lock to protect the outer loop (iterating threads)
2) t->if_lock to protect the inner loop (iterating devices)
Note that before Jesper patch, pktgen_change_name() was lacking proper protection, but lockdep was not able to detect the problem.
--- net/core/pktgen.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
net/core/pktgen.c +10 -7
@@ -216,8 +216,8 @@#define M_QUEUE_XMIT 2/* Inject packet into qdisc */ /* If lock -- protects updating of if_list */ -#define if_lock (t) spin_lock(&(t->if_lock)); -#define if_unlock (t) spin_unlock(&(t->if_lock)); +#define if_lock (t) mutex_lock(&(t->if_lock)); +#define if_unlock (t) mutex_unlock(&(t->if_lock));/* Used to help with determining the pkts on receive */ #define PKTGEN_MAGIC 0xbe9be955
@@ -423,7 +423,7 @@ struct pktgen_net { };struct pktgen_thread { -spinlock_t if_lock;/* for list of devices */ +struct mutex if_lock;/* for list of devices */ struct list_head if_list;/* All device here */ struct list_head th_list;struct task_struct *tsk;
@@ -2010,11 +2010,13 @@ static void pktgen_change_name(const str {struct pktgen_thread *t; +mutex_lock (&pktgen_thread_lock); +list_for_each_entry (t, &pn->pktgen_threads, th_list) {struct pktgen_dev *pkt_dev; -rcu_read_lock (); -list_for_each_entry_rcu (pkt_dev, &t->if_list, list) { +if_lock (t); +list_for_each_entry (pkt_dev, &t->if_list, list) {if (pkt_dev->odev != dev)continue ;
@@ -2029,8 +2031,9 @@ static void pktgen_change_name(const str dev->name);break ; } -rcu_read_unlock (); +if_unlock (t); } +mutex_unlock (&pktgen_thread_lock); } static int pktgen_device_event(struct notifier_block *unused,
@@ -3762,7 +3765,7 @@ static int __net_init pktgen_create_threreturn -ENOMEM ; } -spin_lock_init (&t->if_lock); +mutex_init (&t->if_lock); t->cpu = cpu;INIT_LIST_HEAD (&t->if_list);
Greg Kroah-Hartman
maintainerPATCH 16/35 bridge: multicast: restore perm router ports on multicast enable
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit 7cb3f9214dfa443c1ccc2be637dcc6344cc203f0 ]
Satish reported a problem with the perm multicast router ports not getting reenabled after some series of events, in particular if it happens that the multicast snooping has been disabled and the port goes to disabled state then it will be deleted from the router port list, but if it moves into non-disabled state it will not be re-added because the mcast snooping is still disabled, and enabling snooping later does nothing.
Here are the steps to reproduce, setup br0 with snooping enabled and eth1 added as a perm router (multicast_router = 2):
1. $ echo 0 > /sys/class/net/br0/bridge/multicast_snooping
2. $ ip l set eth1 down
^ This step deletes the interface from the router list
3. $ ip l set eth1 up
^ This step does not add it again because mcast snooping is disabled
4. $ echo 1 > /sys/class/net/br0/bridge/multicast_snooping
5. $ bridge -d -s mdb show
<empty>
At this point we have mcast enabled and eth1 as a perm router (value = 2) but it is not in the router list which is incorrect.
After this change:
1. $ echo 0 > /sys/class/net/br0/bridge/multicast_snooping
2. $ ip l set eth1 down
^ This step deletes the interface from the router list
3. $ ip l set eth1 up
^ This step does not add it again because mcast snooping is disabled
4. $ echo 1 > /sys/class/net/br0/bridge/multicast_snooping
5. $ bridge -d -s mdb show
router ports on br0: eth1
Note: we can directly do br_multicast_enable_port for all because the querier timer already has checks for the port state and will simply expire if it's in blocking/disabled. See the comment added by commit 9aa66382163e7 ("bridge: multicast: add a comment to br_port_state_selection about blocking state")
--- net/bridge/br_multicast.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
net/bridge/br_multicast.c +14 -9
@@ -972,13 +972,12 @@ static void br_multicast_enable(struct bmod_timer (&query->timer, jiffies); } -void br_multicast_enable_port (struct net_bridge_port *port) +static void __br_multicast_enable_port (struct net_bridge_port *port) {struct net_bridge *br = port->br; -spin_lock (&br->multicast_lock);if (br->multicast_disabled || !netif_running (br->dev)) - goto out; +return ;br_multicast_enable (&port->ip4_own_query);#if IS_ENABLED (CONFIG_IPV6 )
@@ -987,8 +986,14 @@ void br_multicast_enable_port(struct netif (port->multicast_router ==MDB_RTR_TYPE_PERM &&hlist_unhashed (&port->rlist))br_multicast_add_router (br, port); +} -out: +void br_multicast_enable_port (struct net_bridge_port *port) +{ +struct net_bridge *br = port->br; + +spin_lock (&br->multicast_lock); +__br_multicast_enable_port (port);spin_unlock (&br->multicast_lock); }
@@ -1994,8 +1999,9 @@ static void br_multicast_start_querier(sint br_multicast_toggle (struct net_bridge *br,unsigned long val) { -int err =0 ;struct net_bridge_mdb_htable *mdb; +struct net_bridge_port *port; +int err =0 ;spin_lock_bh (&br->multicast_lock);if (br->multicast_disabled == !val)
@@ -2023,10 +2029,9 @@ rollback: goto rollback; } -br_multicast_start_querier (br, &br->ip4_own_query); -#if IS_ENABLED (CONFIG_IPV6 ) -br_multicast_start_querier (br, &br->ip6_own_query); -#endif +br_multicast_open (br); +list_for_each_entry (port, &br->port_list, list) +__br_multicast_enable_port (port); unlock:spin_unlock_bh (&br->multicast_lock);
Greg Kroah-Hartman
maintainerPATCH 17/35 switchdev: Execute bridge ndos only for bridge ports
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit 97c242902c209e7d46e365335db5202634484dcb ]
We recently got the following warning after setting up a vlan device on top of an offloaded bridge and executing 'bridge link':
WARNING: CPU: 0 PID: 18566 at drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c:81 mlxsw_sp_port_orig_get.part.9+0x55/0x70 [mlxsw_spectrum] [...] CPU: 0 PID: 18566 Comm: bridge Not tainted 4.8.0-rc7 #1 Hardware name: Mellanox Technologies Ltd. Mellanox switch/Mellanox switch, BIOS 4.6.5 05/21/2015 0000000000000286 00000000e64ab94f ffff880406e6f8f0 ffffffff8135eaa3 0000000000000000 0000000000000000 ffff880406e6f930 ffffffff8108c43b 0000005106e6f988 ffff8803df398840 ffff880403c60108 ffff880406e6f990 Call Trace: [<ffffffff8135eaa3>] dump_stack+0x63/0x90 [<ffffffff8108c43b>] __warn+0xcb/0xf0 [<ffffffff8108c56d>] warn_slowpath_null+0x1d/0x20 [<ffffffffa01420d5>] mlxsw_sp_port_orig_get.part.9+0x55/0x70 [mlxsw_spectrum] [<ffffffffa0142195>] mlxsw_sp_port_attr_get+0xa5/0xb0 [mlxsw_spectrum] [<ffffffff816f151f>] switchdev_port_attr_get+0x4f/0x140 [<ffffffff816f15d0>] switchdev_port_attr_get+0x100/0x140 [<ffffffff816f15d0>] switchdev_port_attr_get+0x100/0x140 [<ffffffff816f1d6b>] switchdev_port_bridge_getlink+0x5b/0xc0 [<ffffffff816f2680>] ? switchdev_port_fdb_dump+0x90/0x90 [<ffffffff815f5427>] rtnl_bridge_getlink+0xe7/0x190 [<ffffffff8161a1b2>] netlink_dump+0x122/0x290 [<ffffffff8161b0df>] __netlink_dump_start+0x15f/0x190 [<ffffffff815f5340>] ? rtnl_bridge_dellink+0x230/0x230 [<ffffffff815fab46>] rtnetlink_rcv_msg+0x1a6/0x220 [<ffffffff81208118>] ? __kmalloc_node_track_caller+0x208/0x2c0 [<ffffffff815f5340>] ? rtnl_bridge_dellink+0x230/0x230 [<ffffffff815fa9a0>] ? rtnl_newlink+0x890/0x890 [<ffffffff8161cf54>] netlink_rcv_skb+0xa4/0xc0 [<ffffffff815f56f8>] rtnetlink_rcv+0x28/0x30 [<ffffffff8161c92c>] netlink_unicast+0x18c/0x240 [<ffffffff8161ccdb>] netlink_sendmsg+0x2fb/0x3a0 [<ffffffff815c5a48>] sock_sendmsg+0x38/0x50 [<ffffffff815c6031>] SYSC_sendto+0x101/0x190 [<ffffffff815c7111>] ? __sys_recvmsg+0x51/0x90 [<ffffffff815c6b6e>] SyS_sendto+0xe/0x10 [<ffffffff817017f2>] entry_SYSCALL_64_fastpath+0x1a/0xa4
The problem is that the 8021q module propagates the call to ndo_bridge_getlink() via switchdev ops, but the switch driver doesn't recognize the netdev, as it's not offloaded.
While we can ignore calls being made to non-bridge ports inside the driver, a better fix would be to push this check up to the switchdev layer.
Note that these ndos can be called for non-bridged netdev, but this only happens in certain PF drivers which don't call the corresponding switchdev functions anyway.
--- net/switchdev/switchdev.c | 9 +++++++++ 1 file changed, 9 insertions(+)
net/switchdev/switchdev.c +9 -0
@@ -774,6 +774,9 @@ int switchdev_port_bridge_getlink(structu32 mask =BR_LEARNING |BR_LEARNING_SYNC |BR_FLOOD ;int err; +if (!netif_is_bridge_port (dev)) +return -EOPNOTSUPP ; + err =switchdev_port_attr_get (dev, &attr);if (err && err != -EOPNOTSUPP )return err;
@@ -929,6 +932,9 @@ int switchdev_port_bridge_setlink(structstruct nlattr *afspec;int err =0 ; +if (!netif_is_bridge_port (dev)) +return -EOPNOTSUPP ; + protinfo =nlmsg_find_attr (nlh,sizeof (struct ifinfomsg ),IFLA_PROTINFO );if (protinfo) {
@@ -962,6 +968,9 @@ int switchdev_port_bridge_dellink(struct {struct nlattr *afspec; +if (!netif_is_bridge_port (dev)) +return -EOPNOTSUPP ; + afspec =nlmsg_find_attr (nlh,sizeof (struct ifinfomsg ),IFLA_AF_SPEC );if (afspec)
Greg Kroah-Hartman
maintainerPATCH 18/35 rtnetlink: Add rtnexthop offload flag to compare mask
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Pirko <[email protected]>
[ Upstream commit 85dda4e5b0ee1f5b4e8cc93d39e475006bc61ccd ]
The offload flag is a status flag and should not be used by FIB semantics for comparison.
--- include/uapi/linux/rtnetlink.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/uapi/linux/rtnetlink.h +1 -1
@@ -350,7 +350,7 @@ struct rtnexthop {#define RTNH_F_OFFLOAD 8/* offloaded route */ #define RTNH_F_LINKDOWN 16/* carrier-down on nexthop */ -#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN) +#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN | RTNH_F_OFFLOAD)/* Macros to handle hexthops */
Greg Kroah-Hartman
maintainerPATCH 19/35 net: core: Correctly iterate over lower adjacency list
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit e4961b0768852d9eb7383e1a5df178eacb714656 ]
Tamir reported the following trace when processing ARP requests received via a vlan device on top of a VLAN-aware bridge:
NMI watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [swapper/1:0]
[...]
CPU: 1 PID: 0 Comm: swapper/1 Tainted: G W 4.8.0-rc7 #1 Hardware name: Mellanox Technologies Ltd. "MSN2100-CB2F"/"SA001017", BIOS 5.6.5 06/07/2016 task: ffff88017edfea40 task.stack: ffff88017ee10000 RIP: 0010:[<ffffffff815dcc73>] [<ffffffff815dcc73>] netdev_all_lower_get_next_rcu+0x33/0x60 [...] Call Trace: <IRQ> [<ffffffffa015de0a>] mlxsw_sp_port_lower_dev_hold+0x5a/0xa0 [mlxsw_spectrum] [<ffffffffa016f1b0>] mlxsw_sp_router_netevent_event+0x80/0x150 [mlxsw_spectrum] [<ffffffff810ad07a>] notifier_call_chain+0x4a/0x70 [<ffffffff810ad13a>] atomic_notifier_call_chain+0x1a/0x20 [<ffffffff815ee77b>] call_netevent_notifiers+0x1b/0x20 [<ffffffff815f2eb6>] neigh_update+0x306/0x740 [<ffffffff815f38ce>] neigh_event_ns+0x4e/0xb0 [<ffffffff8165ea3f>] arp_process+0x66f/0x700 [<ffffffff8170214c>] ? common_interrupt+0x8c/0x8c [<ffffffff8165ec29>] arp_rcv+0x139/0x1d0 [<ffffffff816e505a>] ? vlan_do_receive+0xda/0x320 [<ffffffff815e3794>] __netif_receive_skb_core+0x524/0xab0 [<ffffffff815e6830>] ? dev_queue_xmit+0x10/0x20 [<ffffffffa06d612d>] ? br_forward_finish+0x3d/0xc0 [bridge] [<ffffffffa06e5796>] ? br_handle_vlan+0xf6/0x1b0 [bridge] [<ffffffff815e3d38>] __netif_receive_skb+0x18/0x60 [<ffffffff815e3dc0>] netif_receive_skb_internal+0x40/0xb0 [<ffffffff815e3e4c>] netif_receive_skb+0x1c/0x70 [<ffffffffa06d7856>] br_pass_frame_up+0xc6/0x160 [bridge] [<ffffffffa06d63d7>] ? deliver_clone+0x37/0x50 [bridge] [<ffffffffa06d656c>] ? br_flood+0xcc/0x160 [bridge] [<ffffffffa06d7b14>] br_handle_frame_finish+0x224/0x4f0 [bridge] [<ffffffffa06d7f94>] br_handle_frame+0x174/0x300 [bridge] [<ffffffff815e3599>] __netif_receive_skb_core+0x329/0xab0 [<ffffffff81374815>] ? find_next_bit+0x15/0x20 [<ffffffff8135e802>] ? cpumask_next_and+0x32/0x50 [<ffffffff810c9968>] ? load_balance+0x178/0x9b0 [<ffffffff815e3d38>] __netif_receive_skb+0x18/0x60 [<ffffffff815e3dc0>] netif_receive_skb_internal+0x40/0xb0 [<ffffffff815e3e4c>] netif_receive_skb+0x1c/0x70 [<ffffffffa01544a1>] mlxsw_sp_rx_listener_func+0x61/0xb0 [mlxsw_spectrum] [<ffffffffa005c9f7>] mlxsw_core_skb_receive+0x187/0x200 [mlxsw_core] [<ffffffffa007332a>] mlxsw_pci_cq_tasklet+0x63a/0x9b0 [mlxsw_pci] [<ffffffff81091986>] tasklet_action+0xf6/0x110 [<ffffffff81704556>] __do_softirq+0xf6/0x280 [<ffffffff8109213f>] irq_exit+0xdf/0xf0 [<ffffffff817042b4>] do_IRQ+0x54/0xd0 [<ffffffff8170214c>] common_interrupt+0x8c/0x8c
The problem is that netdev_all_lower_get_next_rcu() never advances the iterator, thereby causing the loop over the lower adjacency list to run forever.
Fix this by advancing the iterator and avoid the infinite loop.
--- include/linux/netdevice.h | 2 +- net/core/dev.c | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-)
include/linux/netdevice.h +1 -1
@@ -3862,7 +3862,7 @@ struct net_device *netdev_all_lower_get_ ldev = netdev_all_lower_get_next(dev, &(iter)))#define netdev_for_each_all_lower_dev_rcu (dev, ldev, iter) \ - for (iter = (dev)->all_adj_list.lower.next, \ + for (iter = &(dev)->all_adj_list.lower, \ ldev = netdev_all_lower_get_next_rcu(dev, &(iter)); \ ldev; \ ldev = netdev_all_lower_get_next_rcu(dev, &(iter)))
net/core/dev.c +7 -3
@@ -5500,10 +5500,14 @@ struct net_device *netdev_all_lower_get_ {struct netdev_adjacent *lower; - lower =list_first_or_null_rcu (&dev->all_adj_list.lower, - struct netdev_adjacent, list); + lower = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); -return lower ? lower->dev :NULL ; +if (&lower->list == &dev->all_adj_list.lower) +return NULL ; + + *iter = &lower->list; + +return lower->dev; }EXPORT_SYMBOL (netdev_all_lower_get_next_rcu);
Greg Kroah-Hartman
maintainerPATCH 21/35 ipv4: disable BH in set_ping_group_range()
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit a681574c99be23e4d20b769bf0e543239c364af5 ]
In commit 4ee3bd4a8c746 ("ipv4: disable BH when changing ip local port range") Cong added BH protection in set_local_port_range() but missed that same fix was needed in set_ping_group_range()
--- net/ipv4/sysctl_net_ipv4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/ipv4/sysctl_net_ipv4.c +2 -2
@@ -109,10 +109,10 @@ static void set_ping_group_range(structkgid_t *data = table->data;struct net *net = container_of(table->data, struct net, ipv4.ping_group_range.range); -write_seqlock (&net->ipv4.ip_local_ports.lock); +write_seqlock_bh (&net->ipv4.ip_local_ports.lock); data[0 ] = low; data[1 ] = high; -write_sequnlock (&net->ipv4.ip_local_ports.lock); +write_sequnlock_bh (&net->ipv4.ip_local_ports.lock); }/* Validate changes from /proc interface. */
Greg Kroah-Hartman
maintainerPATCH 22/35 ipv4: use the right lock for ping_group_range
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: WANG Cong <[email protected]>
[ Upstream commit 396a30cce15d084b2b1a395aa6d515c3d559c674 ]
This reverts commit a681574c99be23e4d20b769bf0e543239c364af5 ("ipv4: disable BH in set_ping_group_range()") because we never read ping_group_range in BH context (unlike local_port_range).
Then, since we already have a lock for ping_group_range, those using ip_local_ports.lock for ping_group_range are clearly typos.
We might consider to share a same lock for both ping_group_range and local_port_range w.r.t. space saving, but that should be for net-next.
--- net/ipv4/sysctl_net_ipv4.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/ipv4/sysctl_net_ipv4.c +4 -4
@@ -96,11 +96,11 @@ static void inet_get_ping_group_range_ta container_of(table->data, struct net, ipv4.ping_group_range.range);unsigned int seq;do { - seq =read_seqbegin (&net->ipv4.ip_local_ports.lock); + seq =read_seqbegin (&net->ipv4.ping_group_range.lock); *low = data[0 ]; *high = data[1 ]; - }while (read_seqretry (&net->ipv4.ip_local_ports.lock, seq)); + }while (read_seqretry (&net->ipv4.ping_group_range.lock, seq)); }/* Update system visible IP port range */
@@ -109,10 +109,10 @@ static void set_ping_group_range(structkgid_t *data = table->data;struct net *net = container_of(table->data, struct net, ipv4.ping_group_range.range); -write_seqlock_bh (&net->ipv4.ip_local_ports.lock); +write_seqlock (&net->ipv4.ping_group_range.lock); data[0 ] = low; data[1 ] = high; -write_sequnlock_bh (&net->ipv4.ip_local_ports.lock); +write_sequnlock (&net->ipv4.ping_group_range.lock); }/* Validate changes from /proc interface. */
Greg Kroah-Hartman
maintainerPATCH 23/35 net: fec: Call swap_buffer() prior to IP header alignment
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fabio Estevam <[email protected]>
[ Upstream commit 235bde1ed3f0fff0f68f367ec8807b89ea151258 ]
Commit 3ac72b7b63d5 ("net: fec: align IP header in hardware") breaks networking on mx28.
There is an erratum on mx28 (ENGR121613 - ENET big endian mode not compatible with ARM little endian) that requires an additional byte-swap operation to workaround this problem.
So call swap_buffer() prior to performing the IP header alignment to restore network functionality on mx28.
--- drivers/net/ethernet/freescale/fec_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +3 -3
@@ -1430,14 +1430,14 @@ fec_enet_rx_queue(struct net_device *ndeskb_put (skb, pkt_len -4 ); data = skb->data; +if (!is_copybreak && need_swap) +swap_buffer (data, pkt_len); +#if !defined(CONFIG_M5272 )if (fep->quirks &FEC_QUIRK_HAS_RACC ) data =skb_pull_inline (skb,2 );#endif -if (!is_copybreak && need_swap) -swap_buffer (data, pkt_len); -/* Extract the enhanced buffer descriptor */ ebdp =NULL ;if (fep->bufdesc_ex)
Greg Kroah-Hartman
maintainerPATCH 24/35 net: sctp, forbid negative length
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Slaby <[email protected]>
[ Upstream commit a4b8e71b05c27bae6bad3bdecddbc6b68a3ad8cf ]
Most of getsockopt handlers in net/sctp/socket.c check len against sizeof some structure like:
if (len < sizeof(int))
return -EINVAL;
On the first look, the check seems to be correct. But since len is int and sizeof returns size_t, int gets promoted to unsigned size_t too. So the test returns false for negative lengths. Yes, (-1 < sizeof(long)) is false.
Fix this in sctp by explicitly checking len < 0 before any getsockopt handler is called.
Note that sctp_getsockopt_events already handled the negative case. Since we added the < 0 check elsewhere, this one can be removed.
If not checked, this is the result:
UBSAN: Undefined behaviour in ../mm/page_alloc.c:2722:19 shift exponent 52 is too large for 32-bit type 'int' CPU: 1 PID: 24535 Comm: syz-executor Not tainted 4.8.1-0-syzkaller #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.1-0-gb3ef39f-prebuilt.qemu-project.org 04/01/2014 0000000000000000 ffff88006d99f2a8 ffffffffb2f7bdea 0000000041b58ab3 ffffffffb4363c14 ffffffffb2f7bcde ffff88006d99f2d0 ffff88006d99f270 0000000000000000 0000000000000000 0000000000000034 ffffffffb5096422 Call Trace: [<ffffffffb3051498>] ? __ubsan_handle_shift_out_of_bounds+0x29c/0x300
...
[<ffffffffb273f0e4>] ? kmalloc_order+0x24/0x90 [<ffffffffb27416a4>] ? kmalloc_order_trace+0x24/0x220 [<ffffffffb2819a30>] ? __kmalloc+0x330/0x540 [<ffffffffc18c25f4>] ? sctp_getsockopt_local_addrs+0x174/0xca0 [sctp] [<ffffffffc18d2bcd>] ? sctp_getsockopt+0x10d/0x1b0 [sctp] [<ffffffffb37c1219>] ? sock_common_getsockopt+0xb9/0x150 [<ffffffffb37be2f5>] ? SyS_getsockopt+0x1a5/0x270
--- net/sctp/socket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/sctp/socket.c +4 -1
@@ -4683,7 +4683,7 @@ static int sctp_getsockopt_disable_fragmstatic int sctp_getsockopt_events (struct sock *sk,int len,char __user *optval,int __user *optlen) { -if (len <=0 ) +if (len =0 )return -EINVAL ;if (len >sizeof (struct sctp_event_subscribe )) len =sizeof (struct sctp_event_subscribe );
@@ -6426,6 +6426,9 @@ static int sctp_getsockopt(struct sock *if (get_user (len, optlen))return -EFAULT ; +if (len <0 ) +return -EINVAL ; +lock_sock (sk);switch (optname) {
Greg Kroah-Hartman
maintainerPATCH 25/35 sctp: fix the panic caused by route update
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xin Long <[email protected]>
[ Upstream commit ecc515d7238f2cffac839069d56dc271141defa0 ]
Commit 7303a1475008 ("sctp: identify chunks that need to be fragmented at IP level") made the chunk be fragmented at IP level in the next round if it's size exceed PMTU.
But there still is another case, PMTU can be updated if transport's dst expires and transport's pmtu_pending is set in sctp_packet_transmit. If the new PMTU is less than the chunk, the same issue with that commit can be triggered.
So we should drop this packet and let it retransmit in another round where it would be fragmented at IP level.
This patch is to fix it by checking the chunk size after PMTU may be updated and dropping this packet if it's size exceed PMTU.
--- net/sctp/output.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
net/sctp/output.c +7 -1
@@ -417,6 +417,7 @@ int sctp_packet_transmit(struct sctp_pac__u8 has_data =0 ;int gso =0 ;int pktcount =0 ; +int auth_len =0 ;struct dst_entry *dst;unsigned char *auth =NULL ;/* pointer to auth in skb data */
@@ -505,7 +506,12 @@ int sctp_packet_transmit(struct sctp_paclist_for_each_entry (chunk, &packet->chunk_list, list) {int padded =WORD_ROUND (chunk->skb->len); -if (pkt_size + padded > tp->pathmtu) +if (chunk == packet->auth) + auth_len = padded; +else if (auth_len + padded + packet->overhead > + tp->pathmtu) + goto nomem; +else if (pkt_size + padded > tp->pathmtu)break ; pkt_size += padded; }
Greg Kroah-Hartman
maintainerPATCH 26/35 udp: fix IP_CHECKSUM handling
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 10df8e6152c6c400a563a673e9956320bfce1871 ]
First bug was added in commit ad6f939ab193 ("ip: Add offset parameter to ip_cmsg_recv") : Tom missed that ipv4 udp messages could be received on AF_INET6 socket. ip_cmsg_recv(msg, skb) should have been replaced by ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr));
Then commit e6afc8ace6dd ("udp: remove headers from UDP packets before queueing") forgot to adjust the offsets now UDP headers are pulled before skb are put in receive queue.
--- include/net/ip.h | 4 ++-- net/ipv4/ip_sockglue.c | 11 ++++++----- net/ipv4/udp.c | 2 +- net/ipv6/udp.c | 3 ++- 4 files changed, 11 insertions(+), 9 deletions(-)
include/net/ip.h +2 -2
@@ -549,7 +549,7 @@ int ip_options_rcv_srr(struct sk_buff *s*/ void ipv4_pktinfo_prepare (const struct sock *sk,struct sk_buff *skb); -void ip_cmsg_recv_offset (struct msghdr *msg,struct sk_buff *skb,int offset); +void ip_cmsg_recv_offset (struct msghdr *msg,struct sk_buff *skb,int tlen,int offset);int ip_cmsg_send (struct sock *sk,struct msghdr *msg,struct ipcm_cookie *ipc,bool allow_ipv6); int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
@@ -571,7 +571,7 @@ void ip_local_error(struct sock *sk, intstatic inline void ip_cmsg_recv (struct msghdr *msg,struct sk_buff *skb) { -ip_cmsg_recv_offset (msg, skb,0 ); +ip_cmsg_recv_offset (msg, skb,0 ,0 ); }bool icmp_global_allow (void );
net/ipv4/ip_sockglue.c +6 -5
@@ -98,7 +98,7 @@ static void ip_cmsg_recv_retopts(struct }static void ip_cmsg_recv_checksum (struct msghdr *msg,struct sk_buff *skb, -int offset) +int tlen,int offset) {__wsum csum = skb->csum;
@@ -106,8 +106,9 @@ static void ip_cmsg_recv_checksum(structreturn ;if (offset !=0 ) - csum =csum_sub (csum,csum_partial (skb_transport_header (skb), - offset,0 )); + csum =csum_sub (csum, +csum_partial (skb_transport_header (skb) + tlen, + offset,0 ));put_cmsg (msg,SOL_IP ,IP_CHECKSUM ,sizeof (__wsum), &csum); }
@@ -153,7 +154,7 @@ static void ip_cmsg_recv_dstaddr(struct }void ip_cmsg_recv_offset (struct msghdr *msg,struct sk_buff *skb, -int offset) +int tlen,int offset) {struct inet_sock *inet =inet_sk (skb->sk);unsigned int flags = inet->cmsg_flags;
@@ -216,7 +217,7 @@ void ip_cmsg_recv_offset(struct msghdr * }if (flags &IP_CMSG_CHECKSUM ) -ip_cmsg_recv_checksum (msg, skb, offset); +ip_cmsg_recv_checksum (msg, skb, tlen, offset); }EXPORT_SYMBOL (ip_cmsg_recv_offset);
net/ipv4/udp.c +1 -1
@@ -1327,7 +1327,7 @@ try_again: *addr_len =sizeof (*sin); }if (inet->cmsg_flags) -ip_cmsg_recv_offset (msg, skb,sizeof (struct udphdr ) + off); +ip_cmsg_recv_offset (msg, skb,sizeof (struct udphdr ), off); err = copied;if (flags &MSG_TRUNC )
net/ipv6/udp.c +2 -1
@@ -427,7 +427,8 @@ try_again:if (is_udp4) {if (inet->cmsg_flags) -ip_cmsg_recv (msg, skb); +ip_cmsg_recv_offset (msg, skb, +sizeof (struct udphdr ), off); }else {if (np->rxopt.all)ip6_datagram_recv_specific_ctl (sk, msg, skb);
Greg Kroah-Hartman
maintainerPATCH 27/35 netvsc: fix incorrect receive checksum offloading
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephen Hemminger <[email protected]>
[ Upstream commit e52fed7177f74382f742c27de2cc5314790aebb6 ]
The Hyper-V netvsc driver was looking at the incorrect status bits in the checksum info. It was setting the receive checksum unnecessary flag based on the IP header checksum being correct. The checksum flag is skb is about TCP and UDP checksum status. Because of this bug, any packet received with bad TCP checksum would be passed up the stack and to the application causing data corruption. The problem is reproducible via netcat and netem.
This had a side effect of not doing receive checksum offload on IPv6. The driver was also also always doing checksum offload independent of the checksum setting done via ethtool.
--- drivers/net/hyperv/netvsc_drv.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
drivers/net/hyperv/netvsc_drv.c +11 -8
@@ -624,15 +624,18 @@ static struct sk_buff *netvsc_alloc_recv packet->total_data_buflen); skb->protocol =eth_type_trans (skb, net); -if (csum_info) { -/* We only look at the IP checksum here. -* Should we be dropping the packet if checksum -* failed? How do we deal with other checksums - TCP/UDP? -*/ -if (csum_info->receive.ip_checksum_succeeded) + +/* skb is already created with CHECKSUM_NONE */ +skb_checksum_none_assert (skb); + +/* +* In Linux, the IP checksum is always checked. +* Do L4 checksum offload if enabled and present. +*/ +if (csum_info && (net->features &NETIF_F_RXCSUM )) { +if (csum_info->receive.tcp_checksum_succeeded || + csum_info->receive.udp_checksum_succeeded) skb->ip_summed =CHECKSUM_UNNECESSARY ; -else - skb->ip_summed =CHECKSUM_NONE ; }if (vlan_tci &VLAN_TAG_PRESENT )
Greg Kroah-Hartman
maintainerPATCH 28/35 macsec: Fix header length if SCI is added if explicitly disabled
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tobias Brunner <[email protected]>
[ Upstream commit e0f841f5cbf2a195c63f3441f3d8ef1cd2bdeeed ]
Even if sending SCIs is explicitly disabled, the code that creates the Security Tag might still decide to add it (e.g. if multiple RX SCs are defined on the MACsec interface).
But because the header length so far only depended on the configuration option the SCI overwrote the original frame's contents (EtherType and e.g. the beginning of the IP header) and if encrypted did not visibly end up in the packet, while the SC flag in the TCI field of the Security Tag was still set, resulting in invalid MACsec frames.
--- drivers/net/macsec.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-)
drivers/net/macsec.c +18 -8
@@ -397,6 +397,14 @@ static struct macsec_cb *macsec_skb_cb(s#define DEFAULT_ENCRYPT false#define DEFAULT_ENCODING_SA 0 +static bool send_sci (const struct macsec_secy *secy) +{ +const struct macsec_tx_sc *tx_sc = &secy->tx_sc; + +return tx_sc->send_sci || + (secy->n_rx_sc >1 && !tx_sc->end_station && !tx_sc->scb); +} +static sci_t make_sci (u8 *addr,__be16 port) {sci_t sci;
@@ -437,15 +445,15 @@ static unsigned int macsec_extra_len(boo/* Fill SecTAG according to IEEE 802.1AE-2006 10.5.3 */ static void macsec_fill_sectag (struct macsec_eth_header *h, -const struct macsec_secy *secy,u32 pn) +const struct macsec_secy *secy,u32 pn, +bool sci_present) {const struct macsec_tx_sc *tx_sc = &secy->tx_sc; -memset (&h->tci_an,0 ,macsec_sectag_len (tx_sc->send_sci)); +memset (&h->tci_an,0 ,macsec_sectag_len (sci_present)); h->eth.h_proto =htons (ETH_P_MACSEC ); -if (tx_sc->send_sci || - (secy->n_rx_sc >1 && !tx_sc->end_station && !tx_sc->scb)) { +if (sci_present) { h->tci_an |=MACSEC_TCI_SC ;memcpy (&h->secure_channel_id, &secy->sci,sizeof (h->secure_channel_id));
@@ -650,6 +658,7 @@ static struct sk_buff *macsec_encrypt(ststruct macsec_tx_sc *tx_sc;struct macsec_tx_sa *tx_sa;struct macsec_dev *macsec =macsec_priv (dev); +bool sci_present;u32 pn; secy = &macsec->secy;
@@ -687,7 +696,8 @@ static struct sk_buff *macsec_encrypt(st unprotected_len = skb->len; eth =eth_hdr (skb); - hh = (struct macsec_eth_header *)skb_push (skb,macsec_extra_len (tx_sc->send_sci)); + sci_present =send_sci (secy); + hh = (struct macsec_eth_header *)skb_push (skb,macsec_extra_len (sci_present));memmove (hh, eth,2 *ETH_ALEN ); pn =tx_sa_update_pn (tx_sa, secy);
@@ -696,7 +706,7 @@ static struct sk_buff *macsec_encrypt(stkfree_skb (skb);return ERR_PTR (-ENOLINK ); } -macsec_fill_sectag (hh, secy, pn); +macsec_fill_sectag (hh, secy, pn, sci_present);macsec_set_shortlen (hh, unprotected_len -2 *ETH_ALEN );skb_put (skb, secy->icv_len);
@@ -726,10 +736,10 @@ static struct sk_buff *macsec_encrypt(stskb_to_sgvec (skb, sg,0 , skb->len);if (tx_sc->encrypt) { -int len = skb->len -macsec_hdr_len (tx_sc->send_sci) - +int len = skb->len -macsec_hdr_len (sci_present) - secy->icv_len;aead_request_set_crypt (req, sg, sg, len, iv); -aead_request_set_ad (req,macsec_hdr_len (tx_sc->send_sci)); +aead_request_set_ad (req,macsec_hdr_len (sci_present)); }else {aead_request_set_crypt (req, sg, sg,0 , iv);aead_request_set_ad (req, skb->len - secy->icv_len);
Greg Kroah-Hartman
maintainerPATCH 29/35 net: ipv6: Do not consider link state for nexthop validation
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Ahern <[email protected]>
[ Upstream commit d5d32e4b76687f4df9ad3ba8d3702b7347f51fa6 ]
Similar to IPv4, do not consider link state when validating next hops.
Currently, if the link is down default routes can fail to insert:
$ ip -6 ro add vrf blue default via 2100:2::64 dev eth2 RTNETLINK answers: No route to host
With this patch the command succeeds.
--- include/net/ip6_route.h | 1 + net/ipv6/route.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-)
include/net/ip6_route.h +1 -0
@@ -32,6 +32,7 @@ struct route_info {#define RT6_LOOKUP_F_SRCPREF_TMP 0x00000008#define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010#define RT6_LOOKUP_F_SRCPREF_COA 0x00000020 +#define RT6_LOOKUP_F_IGNORE_LINKSTATE 0x00000040/* We do not (yet ?) support IPv6 jumbograms (RFC 2675) * Unlike IPv4, hdr->seg_len doesn't include the IPv6 header
net/ipv6/route.c +4 -2
@@ -656,7 +656,8 @@ static struct rt6_info *find_match(strucstruct net_device *dev = rt->dst.dev;if (dev && !netif_carrier_ok (dev) && - idev->cnf.ignore_routes_with_linkdown) + idev->cnf.ignore_routes_with_linkdown && + !(strict &RT6_LOOKUP_F_IGNORE_LINKSTATE )) goto out;if (rt6_check_expired (rt))
@@ -1050,6 +1051,7 @@ struct rt6_info *ip6_pol_route(struct neint strict =0 ; strict |= flags &RT6_LOOKUP_F_IFACE ; + strict |= flags &RT6_LOOKUP_F_IGNORE_LINKSTATE ;if (net->ipv6.devconf_all->forwarding ==0 ) strict |=RT6_LOOKUP_F_REACHABLE ;
@@ -1783,7 +1785,7 @@ static struct rt6_info *ip6_nh_lookup_ta };struct fib6_table *table;struct rt6_info *rt; -int flags =RT6_LOOKUP_F_IFACE ; +int flags =RT6_LOOKUP_F_IFACE |RT6_LOOKUP_F_IGNORE_LINKSTATE ; table =fib6_get_table (net, cfg->fc_table);if (!table)
Greg Kroah-Hartman
maintainerPATCH 30/35 net sched filters: fix notification of filter delete with proper handle
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 9ee7837449b3d6f0fcf9132c6b5e5aaa58cc67d4 ]
Daniel says:
While trying out [1][2], I noticed that tc monitor doesn't show the correct handle on delete:
$ tc monitor qdisc clsact ffff: dev eno1 parent ffff:fff1 filter dev eno1 ingress protocol all pref 49152 bpf handle 0x2a [...] deleted filter dev eno1 ingress protocol all pref 49152 bpf handle 0xf3be0c80
some context to explain the above:
The user identity of any tc filter is represented by a 32-bit identifier encoded in tcm->tcm_handle. Example 0x2a in the bpf filter above. A user wishing to delete, get or even modify a specific filter uses this handle to reference it.
Every classifier is free to provide its own semantics for the 32 bit handle.
Example: classifiers like u32 use schemes like 800:1:801 to describe the semantics of their filters represented as hash table, bucket and node ids etc.
Classifiers also have internal per-filter representation which is different from this externally visible identity. Most classifiers set this internal representation to be a pointer address (which allows fast retrieval of said filters in their implementations). This internal representation is referenced with the "fh" variable in the kernel control code.
When a user successfuly deletes a specific filter, by specifying the correct tcm->tcm_handle, an event is generated to user space which indicates which specific filter was deleted.
Before this patch, the "fh" value was sent to user space as the identity. As an example what is shown in the sample bpf filter delete event above is 0xf3be0c80. This is infact a 32-bit truncation of 0xffff8807f3be0c80 which happens to be a 64-bit memory address of the internal filter representation (address of the corresponding filter's struct cls_bpf_prog);
After this patch the appropriate user identifiable handle as encoded in the originating request tcm->tcm_handle is generated in the event. One of the cardinal rules of netlink rules is to be able to take an event (such as a delete in this case) and reflect it back to the kernel and successfully delete the filter. This patch achieves that.
Note, this issue has existed since the original TC action infrastructure code patch back in 2004 as found in:
https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/
[1] http://patchwork.ozlabs.org/patch/682828/
[2] http://patchwork.ozlabs.org/patch/682829/
--- net/sched/cls_api.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/sched/cls_api.c +2 -1
@@ -344,7 +344,8 @@ replay:if (err ==0 ) {struct tcf_proto *next =rtnl_dereference (tp->next); -tfilter_notify (net, skb, n, tp, fh,RTM_DELTFILTER ); +tfilter_notify (net, skb, n, tp, + t->tcm_handle,RTM_DELTFILTER );if (tcf_destroy (tp, false))RCU_INIT_POINTER (*back, next); }
Greg Kroah-Hartman
maintainerPATCH 31/35 sctp: validate chunk len before actually using it
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marcelo Ricardo Leitner <[email protected]>
[ Upstream commit bf911e985d6bbaa328c20c3e05f4eb03de11fdd6 ]
Andrey Konovalov reported that KASAN detected that SCTP was using a slab beyond the boundaries. It was caused because when handling out of the blue packets in function sctp_sf_ootb() it was checking the chunk len only after already processing the first chunk, validating only for the 2nd and subsequent ones.
The fix is to just move the check upwards so it's also validated for the 1st chunk.
--- net/sctp/sm_statefuns.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
net/sctp/sm_statefuns.c +6 -6
@@ -3422,6 +3422,12 @@ sctp_disposition_t sctp_sf_ootb(struct nreturn sctp_sf_violation_chunklen (net, ep, asoc, type, arg, commands); +/* Report violation if chunk len overflows */ + ch_end = ((__u8 *)ch) +WORD_ROUND (ntohs (ch->length)); +if (ch_end >skb_tail_pointer (skb)) +return sctp_sf_violation_chunklen (net, ep, asoc, type, arg, + commands); +/* Now that we know we at least have a chunk header, * do things that are type appropriate. */
@@ -3453,12 +3459,6 @@ sctp_disposition_t sctp_sf_ootb(struct n } } -/* Report violation if chunk len overflows */ - ch_end = ((__u8 *)ch) +WORD_ROUND (ntohs (ch->length)); -if (ch_end >skb_tail_pointer (skb)) -return sctp_sf_violation_chunklen (net, ep, asoc, type, arg, - commands); - ch = (sctp_chunkhdr_t *) ch_end; }while (ch_end <skb_tail_pointer (skb));
Greg Kroah-Hartman
maintainerPATCH 32/35 ip6_tunnel: Update skb->protocol to ETH_P_IPV6 in ip6_tnl_xmit()
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eli Cooper <[email protected]>
[ Upstream commit ae148b085876fa771d9ef2c05f85d4b4bf09ce0d ]
This patch updates skb->protocol to ETH_P_IPV6 in ip6_tnl_xmit() when an IPv6 header is installed to a socket buffer.
This is not a cosmetic change. Without updating this value, GSO packets transmitted through an ipip6 tunnel have the protocol of ETH_P_IP and skb_mac_gso_segment() will attempt to call gso_segment() for IPv4, which results in the packets being dropped.
--- net/ipv6/ip6_tunnel.c | 1 + 1 file changed, 1 insertion(+)
net/ipv6/ip6_tunnel.c +1 -0
@@ -1134,6 +1134,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, stif (err)return err; + skb->protocol =htons (ETH_P_IPV6 );skb_push (skb,sizeof (struct ipv6hdr ));skb_reset_network_header (skb); ipv6h =ipv6_hdr (skb);
Greg Kroah-Hartman
maintainerPATCH 33/35 packet: on direct_xmit, limit tso and csum to supported devices
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit 104ba78c98808ae837d1f63aae58c183db5505df ]
When transmitting on a packet socket with PACKET_VNET_HDR and PACKET_QDISC_BYPASS, validate device support for features requested in vnet_hdr.
Drop TSO packets sent to devices that do not support TSO or have the feature disabled. Note that the latter currently do process those packets correctly, regardless of not advertising the feature.
Because of SKB_GSO_DODGY, it is not sufficient to test device features with netif_needs_gso. Full validate_xmit_skb is needed.
Switch to software checksum for non-TSO packets that request checksum offload if that device feature is unsupported or disabled. Note that similar to the TSO case, device drivers may perform checksum offload correctly even when not advertising it.
When switching to software checksum, packets hit skb_checksum_help, which has two BUG_ON checksum not in linear segment. Packet sockets always allocate at least up to csum_start + csum_off + 2 as linear.
Tested by running github.com/wdebruij/kerneltools/psock_txring_vnet.c
ethtool -K eth0 tso off tx on
psock_txring_vnet -d $dst -s $src -i eth0 -l 2000 -n 1 -q -v psock_txring_vnet -d $dst -s $src -i eth0 -l 2000 -n 1 -q -v -N
ethtool -K eth0 tx off
psock_txring_vnet -d $dst -s $src -i eth0 -l 1000 -n 1 -q -v -G psock_txring_vnet -d $dst -s $src -i eth0 -l 1000 -n 1 -q -v -G -N
v2:
- add EXPORT_SYMBOL_GPL(validate_xmit_skb_list)
--- net/core/dev.c | 1 + net/packet/af_packet.c | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-)
net/core/dev.c +1 -0
@@ -3035,6 +3035,7 @@ struct sk_buff *validate_xmit_skb_list(s }return head; } +EXPORT_SYMBOL_GPL (validate_xmit_skb_list);static void qdisc_pkt_len_init (struct sk_buff *skb) {
net/packet/af_packet.c +4 -5
@@ -250,7 +250,7 @@ static void __fanout_link(struct sock *sstatic int packet_direct_xmit (struct sk_buff *skb) {struct net_device *dev = skb->dev; -netdev_features_t features; +struct sk_buff *orig_skb = skb;struct netdev_queue *txq;int ret =NETDEV_TX_BUSY ;
@@ -258,9 +258,8 @@ static int packet_direct_xmit(struct sk_ !netif_carrier_ok(dev))) goto drop; - features =netif_skb_features (skb); -if (skb_needs_linearize (skb, features) && -__skb_linearize (skb)) + skb =validate_xmit_skb_list (skb, dev); +if (skb != orig_skb) goto drop; txq =skb_get_tx_queue (dev, skb);
@@ -280,7 +279,7 @@ static int packet_direct_xmit(struct sk_return ret; drop:atomic_long_inc (&dev->tx_dropped); -kfree_skb (skb); +kfree_skb_list (skb);return NET_XMIT_DROP ; }
Greg Kroah-Hartman
maintainerPATCH 34/35 arch/powerpc: Update parameters for csum_tcpudp_magic & csum_tcpudp_nofold
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivan Vecera <[email protected]>
[ Upstream commit f9d4286b9516b02e795214412d36885f572b57ad ]
Commit 01cfbad "ipv4: Update parameters for csum_tcpudp_magic to their original types" changed parameters for csum_tcpudp_magic and csum_tcpudp_nofold for many platforms but not for PowerPC.
--- arch/powerpc/include/asm/checksum.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
arch/powerpc/include/asm/checksum.h +4 -8
@@ -53,10 +53,8 @@ static inline __sum16 csum_fold(__wsum sreturn (__force __sum16)(~((__force u32 )sum + tmp) >>16 ); } -static inline __wsum csum_tcpudp_nofold (__be32 saddr,__be32 daddr, -unsigned short len, -unsigned short proto, -__wsum sum) +static inline __wsum csum_tcpudp_nofold (__be32 saddr,__be32 daddr,__u32 len, +__u8 proto,__wsum sum) {#ifdef __powerpc64__unsigned long s = (__force u32 )sum;
@@ -83,10 +81,8 @@ static inline __wsum csum_tcpudp_nofold(* computes the checksum of the TCP/UDP pseudo-header * returns a 16-bit checksum, already complemented */ -static inline __sum16 csum_tcpudp_magic (__be32 saddr,__be32 daddr, -unsigned short len, -unsigned short proto, -__wsum sum) +static inline __sum16 csum_tcpudp_magic (__be32 saddr,__be32 daddr,__u32 len, +__u8 proto,__wsum sum) {return csum_fold (csum_tcpudp_nofold (saddr, daddr, len, proto, sum)); }
Greg Kroah-Hartman
maintainerPATCH 35/35 usb: dwc3: gadget: properly account queued requests
In reply to Greg Kroah-Hartman4.8-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felipe Balbi <[email protected]>
commit a9c3ca5fae6bf73770f0576eaf57d5f1305ef4b3 upstream.
Some requests could be accounted for multiple times. Let's fix that so each and every requests is accounted for only once.
--- drivers/usb/dwc3/gadget.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/usb/dwc3/gadget.c +4 -3
@@ -789,6 +789,7 @@ static void dwc3_prepare_one_trb(struct req->trb = trb; req->trb_dma =dwc3_trb_dma_offset (dep, trb); req->first_trb_index = dep->trb_enqueue; + dep->queued_requests++; }dwc3_ep_inc_enq (dep);
@@ -841,8 +842,6 @@ static void dwc3_prepare_one_trb(struct trb->ctrl |=DWC3_TRB_CTRL_HWO ; - dep->queued_requests++; -trace_dwc3_prepare_trb (dep, trb); }
@@ -1963,7 +1962,9 @@ static int __dwc3_cleanup_done_trbs(struunsigned int s_pkt =0 ;unsigned int trb_status; - dep->queued_requests--; +if (req->trb == trb) + dep->queued_requests--; +trace_dwc3_complete_trb (dep, trb);/*
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.8.8 release. There are 35 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Tue Nov 15 11:24:10 UTC 2016. Anything received after that time might be too late.
Build results:
total: 149 pass: 149 fail: 0 Qemu test results: total: 114 pass: 114 fail: 0
Details are available at http://kerneltests.org/builders.
Guenter
Greg Kroah-Hartman
maintainerQuoted 11 lines · Guenter Roeck
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.8.8 release. There are 35 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Tue Nov 15 11:24:10 UTC 2016. Anything received after that time might be too late.
Quoted 6 lines
Build results:
total: 149 pass: 149 fail: 0 Qemu test results: total: 114 pass: 114 fail: 0Details are available at http://kerneltests.org/builders.
Thanks for testing both trees and letting me know.
greg k-h
A message that is not in the archive (sent off-list or not yet received): [email protected]
Greg Kroah-Hartman
maintainerQuoted 1 line · kernelci.org bot
stable-rc boot: 146 boots: 0 failed, 144 passed with 2 offline (v4.8.7-36-g06d2f2c881c0)
Nice! Thanks for testing.
greg k-h
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.8.8 release. There are 35 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Tue Nov 15 11:24:10 UTC 2016. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.8.8-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.8.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Signature · 5 lines
Shuah Khan Sr. Linux Kernel Developer Open Source Innovation Group Samsung Research America(Silicon Valley) [email protected]
Greg Kroah-Hartman
maintainerQuoted 15 lines · Shuah Khan
Quoted 14 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.8.8 release. There are 35 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Tue Nov 15 11:24:10 UTC 2016. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.8.8-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.8.y
and the diffstat can be found below.
Quoted 6 lines
Quoted 4 lines
thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
Thanks for testing both of these and letting me know.
greg k-h