3.10.70-stable review
Greg Kroah-Hartman
maintainercover 3.10.70-stable review
This is the start of the stable review cycle for the 3.10.70 release. There are 16 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 Fri Feb 27 02:07:52 UTC 2015. 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/v3.0/stable-review/patch-3.10.70-rc1.gz
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 3.10.70-rc1
Alex Elder <[email protected]>
rbd: drop an unsafe assertion
Austin Lund <[email protected]>
media/rc: Send sync space information on the lirc device
Saran Maruti Ramanara <[email protected]>
net: sctp: fix passing wrong parameter header to param_type2af in sctp_process_param
Florian Westphal <[email protected]>
ppp: deflate: never return len larger than output buffer
Eric Dumazet <[email protected]>
ipv4: tcp: get rid of ugly unicast_sock
Eric Dumazet <[email protected]>
tcp: ipv4: initialize unicast_sock sk_pacing_rate
Roopa Prabhu <[email protected]>
bridge: dont send notification when skb->len == 0 in rtnl_bridge_notify
Hannes Frederic Sowa <[email protected]>
ipv6: replacing a rt6_info needs to purge possible propagated rt6_infos too
[email protected] <[email protected]>
ping: Fix race in free in receive path
Herbert Xu <[email protected]>
udp_diag: Fix socket skipping within chain
Hannes Frederic Sowa <[email protected]>
ipv4: try to cache dst_entries which would cause a redirect
Daniel Borkmann <[email protected]>
net: sctp: fix slab corruption from use after free on INIT collisions
Eric Dumazet <[email protected]>
netxen: fix netxen_nic_poll() logic
Hagen Paul Pfeifer <[email protected]>
ipv6: stop sending PTB packets for MTU < 1280
Eric Dumazet <[email protected]>
net: rps: fix cpu unplug
Willem de Bruijn <[email protected]>
ip: zero sockaddr returned on error queue
-------------
Diffstat:
Makefile | 4 +- drivers/block/rbd.c | 1 - drivers/media/rc/ir-lirc-codec.c | 12 ++++-- .../net/ethernet/qlogic/netxen/netxen_nic_main.c | 5 ++- drivers/net/ppp/ppp_deflate.c | 2 +- include/net/ip.h | 13 ++++--- include/net/netns/ipv4.h | 1 + net/core/dev.c | 20 +++++++--- net/core/rtnetlink.c | 6 ++- net/ipv4/ip_forward.c | 3 +- net/ipv4/ip_output.c | 29 ++------------ net/ipv4/ip_sockglue.c | 8 +--- net/ipv4/ping.c | 5 ++- net/ipv4/route.c | 9 +++-- net/ipv4/tcp_ipv4.c | 37 +++++++++++++++--- net/ipv4/udp_diag.c | 4 +- net/ipv6/datagram.c | 10 ++--- net/ipv6/ip6_fib.c | 45 +++++++++++++--------- net/ipv6/route.c | 7 +--- net/sctp/associola.c | 1 - net/sctp/sm_make_chunk.c | 2 +- 21 files changed, 127 insertions(+), 97 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/16 ip: zero sockaddr returned on error queue
3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit f812116b174e59a350acc8e4856213a166a91222 ]
The sockaddr is returned in IP(V6)_RECVERR as part of errhdr. That structure is defined and allocated on the stack as
struct {
struct sock_extended_err ee;
struct sockaddr_in(6) offender;
} errhdr;The second part is only initialized for certain SO_EE_ORIGIN values. Always initialize it completely.
An MTU exceeded error on a SOCK_RAW/IPPROTO_RAW is one example that would return uninitialized bytes.
----
Also verified that there is no padding between errhdr.ee and errhdr.offender that could leak additional kernel data.
--- net/ipv4/ip_sockglue.c | 8 ++------ net/ipv6/datagram.c | 10 +++------- 2 files changed, 5 insertions(+), 13 deletions(-)
net/ipv4/ip_sockglue.c +2 -6
@@ -410,15 +410,11 @@ int ip_recv_error(struct sock *sk, strucmemcpy (&errhdr.ee, &serr->ee,sizeof (struct sock_extended_err )); sin = &errhdr.offender; - sin->sin_family =AF_UNSPEC ; +memset (sin,0 ,sizeof (*sin));if (serr->ee.ee_origin ==SO_EE_ORIGIN_ICMP ) { -struct inet_sock *inet =inet_sk (sk); - sin->sin_family =AF_INET ; sin->sin_addr.s_addr =ip_hdr (skb)->saddr; - sin->sin_port =0 ; -memset (&sin->sin_zero,0 ,sizeof (sin->sin_zero)); -if (inet->cmsg_flags) +if (inet_sk (sk)->cmsg_flags)ip_cmsg_recv (msg, skb); }
net/ipv6/datagram.c +3 -7
@@ -374,11 +374,10 @@ int ipv6_recv_error(struct sock *sk, strmemcpy (&errhdr.ee, &serr->ee,sizeof (struct sock_extended_err )); sin = &errhdr.offender; - sin->sin6_family =AF_UNSPEC ; +memset (sin,0 ,sizeof (*sin)); +if (serr->ee.ee_origin !=SO_EE_ORIGIN_LOCAL ) { sin->sin6_family =AF_INET6 ; - sin->sin6_flowinfo =0 ; - sin->sin6_port =0 ;if (skb->protocol ==htons (ETH_P_IPV6 )) { sin->sin6_addr =ipv6_hdr (skb)->saddr;if (np->rxopt.all)
@@ -387,12 +386,9 @@ int ipv6_recv_error(struct sock *sk, stripv6_iface_scope_id (&sin->sin6_addr,IP6CB (skb)->iif); }else { -struct inet_sock *inet =inet_sk (sk); -ipv6_addr_set_v4mapped (ip_hdr (skb)->saddr, &sin->sin6_addr); - sin->sin6_scope_id =0 ; -if (inet->cmsg_flags) +if (inet_sk (sk)->cmsg_flags)ip_cmsg_recv (msg, skb); } }
Greg Kroah-Hartman
maintainerPATCH 2/16 net: rps: fix cpu unplug
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit ac64da0b83d82abe62f78b3d0e21cca31aea24fa ]
softnet_data.input_pkt_queue is protected by a spinlock that we must hold when transferring packets from victim queue to an active one. This is because other cpus could still be trying to enqueue packets into victim queue.
A second problem is that when we transfert the NAPI poll_list from victim to current cpu, we absolutely need to special case the percpu backlog, because we do not want to add complex locking to protect process_queue : Only owner cpu is allowed to manipulate it, unless cpu is offline.
Based on initial patch from Prasad Sodagudi & Subash Abhinov Kasiviswanathan.
This version is better because we do not slow down packet processing, only make migration safer.
--- net/core/dev.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
net/core/dev.c +15 -5
@@ -6015,10 +6015,20 @@ static int dev_cpu_callback(struct notif oldsd->output_queue =NULL ; oldsd->output_queue_tailp = &oldsd->output_queue; } -/* Append NAPI poll list from offline CPU. */ -if (!list_empty (&oldsd->poll_list)) { -list_splice_init (&oldsd->poll_list, &sd->poll_list); -raise_softirq_irqoff (NET_RX_SOFTIRQ ); +/* Append NAPI poll list from offline CPU, with one exception : +* process_backlog() must be called by cpu owning percpu backlog. +* We properly handle process_queue & input_pkt_queue later. +*/ +while (!list_empty (&oldsd->poll_list)) { +struct napi_struct *napi =list_first_entry (&oldsd->poll_list, + struct napi_struct, + poll_list); + +list_del_init (&napi->poll_list); +if (napi->poll == process_backlog) + napi->state =0 ; +else +____napi_schedule (sd, napi); }raise_softirq_irqoff (NET_TX_SOFTIRQ );
@@ -6029,7 +6039,7 @@ static int dev_cpu_callback(struct notifnetif_rx (skb);input_queue_head_incr (oldsd); } -while ((skb =__skb_dequeue (&oldsd->input_pkt_queue))) { +while ((skb =skb_dequeue (&oldsd->input_pkt_queue))) {netif_rx (skb);input_queue_head_incr (oldsd); }
Greg Kroah-Hartman
maintainerPATCH 3/16 ipv6: stop sending PTB packets for MTU < 1280
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hagen Paul Pfeifer <[email protected]>
[ Upstream commit 9d289715eb5c252ae15bd547cb252ca547a3c4f2 ]
Reduce the attack vector and stop generating IPv6 Fragment Header for paths with an MTU smaller than the minimum required IPv6 MTU size (1280 byte) - called atomic fragments.
See IETF I-D "Deprecating the Generation of IPv6 Atomic Fragments" [1] for more information and how this "feature" can be misused.
[1] https://tools.ietf.org/html/draft-ietf-6man-deprecate-atomfrag-generation-00
--- net/ipv6/route.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
net/ipv6/route.c +2 -5
@@ -1141,12 +1141,9 @@ static void ip6_rt_update_pmtu(struct dsstruct net *net =dev_net (dst->dev); rt6->rt6i_flags |=RTF_MODIFIED ; -if (mtu <IPV6_MIN_MTU ) { -u32 features =dst_metric (dst,RTAX_FEATURES ); +if (mtu <IPV6_MIN_MTU ) mtu =IPV6_MIN_MTU ; - features |=RTAX_FEATURE_ALLFRAG ; -dst_metric_set (dst,RTAX_FEATURES , features); - } +dst_metric_set (dst,RTAX_MTU , mtu);rt6_update_expires (rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); }
Greg Kroah-Hartman
maintainerPATCH 4/16 netxen: fix netxen_nic_poll() logic
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 6088beef3f7517717bd21d90b379714dd0837079 ]
NAPI poll logic now enforces that a poller returns exactly the budget when it wants to be called again.
If a driver limits TX completion, it has to return budget as well when the limit is hit, not the number of received packets.
--- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +4 -1
@@ -2315,7 +2315,10 @@ static int netxen_nic_poll(struct napi_s work_done =netxen_process_rcv_ring (sds_ring, budget); -if ((work_done < budget) && tx_complete) { +if (!tx_complete) + work_done = budget; + +if (work_done < budget) {napi_complete (&sds_ring->napi);if (test_bit (__NX_DEV_UP, &adapter->state))netxen_nic_enable_int (sds_ring);
Greg Kroah-Hartman
maintainerPATCH 5/16 net: sctp: fix slab corruption from use after free on INIT collisions
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 600ddd6825543962fb807884169e57b580dba208 ]
When hitting an INIT collision case during the 4WHS with AUTH enabled, as already described in detail in commit 1be9a950c646 ("net: sctp: inherit auth_capable on INIT collisions"), it can happen that we occasionally still remotely trigger the following panic on server side which seems to have been uncovered after the fix from commit 1be9a950c646 ...
[ 533.876389] BUG: unable to handle kernel paging request at 00000000ffffffff [ 533.913657] IP: [<ffffffff811ac385>] __kmalloc+0x95/0x230 [ 533.940559] PGD 5030f2067 PUD 0 [ 533.957104] Oops: 0000 [#1] SMP [ 533.974283] Modules linked in: sctp mlx4_en [...] [ 534.939704] Call Trace: [ 534.951833] [<ffffffff81294e30>] ? crypto_init_shash_ops+0x60/0xf0 [ 534.984213] [<ffffffff81294e30>] crypto_init_shash_ops+0x60/0xf0 [ 535.015025] [<ffffffff8128c8ed>] __crypto_alloc_tfm+0x6d/0x170 [ 535.045661] [<ffffffff8128d12c>] crypto_alloc_base+0x4c/0xb0 [ 535.074593] [<ffffffff8160bd42>] ? _raw_spin_lock_bh+0x12/0x50 [ 535.105239] [<ffffffffa0418c11>] sctp_inet_listen+0x161/0x1e0 [sctp] [ 535.138606] [<ffffffff814e43bd>] SyS_listen+0x9d/0xb0 [ 535.166848] [<ffffffff816149a9>] system_call_fastpath+0x16/0x1b
... or depending on the the application, for example this one:
[ 1370.026490] BUG: unable to handle kernel paging request at 00000000ffffffff [ 1370.026506] IP: [<ffffffff811ab455>] kmem_cache_alloc+0x75/0x1d0 [ 1370.054568] PGD 633c94067 PUD 0 [ 1370.070446] Oops: 0000 [#1] SMP [ 1370.085010] Modules linked in: sctp kvm_amd kvm [...] [ 1370.963431] Call Trace: [ 1370.974632] [<ffffffff8120f7cf>] ? SyS_epoll_ctl+0x53f/0x960 [ 1371.000863] [<ffffffff8120f7cf>] SyS_epoll_ctl+0x53f/0x960 [ 1371.027154] [<ffffffff812100d3>] ? anon_inode_getfile+0xd3/0x170 [ 1371.054679] [<ffffffff811e3d67>] ? __alloc_fd+0xa7/0x130 [ 1371.080183] [<ffffffff816149a9>] system_call_fastpath+0x16/0x1b
With slab debugging enabled, we can see that the poison has been overwritten:
[ 669.826368] BUG kmalloc-128 (Tainted: G W ): Poison overwritten [ 669.826385] INFO: 0xffff880228b32e50-0xffff880228b32e50. First byte 0x6a instead of 0x6b [ 669.826414] INFO: Allocated in sctp_auth_create_key+0x23/0x50 [sctp] age=3 cpu=0 pid=18494 [ 669.826424] __slab_alloc+0x4bf/0x566 [ 669.826433] __kmalloc+0x280/0x310 [ 669.826453] sctp_auth_create_key+0x23/0x50 [sctp] [ 669.826471] sctp_auth_asoc_create_secret+0xcb/0x1e0 [sctp] [ 669.826488] sctp_auth_asoc_init_active_key+0x68/0xa0 [sctp] [ 669.826505] sctp_do_sm+0x29d/0x17c0 [sctp] [...] [ 669.826629] INFO: Freed in kzfree+0x31/0x40 age=1 cpu=0 pid=18494 [ 669.826635] __slab_free+0x39/0x2a8 [ 669.826643] kfree+0x1d6/0x230 [ 669.826650] kzfree+0x31/0x40 [ 669.826666] sctp_auth_key_put+0x19/0x20 [sctp] [ 669.826681] sctp_assoc_update+0x1ee/0x2d0 [sctp] [ 669.826695] sctp_do_sm+0x674/0x17c0 [sctp]
Since this only triggers in some collision-cases with AUTH, the problem at heart is that sctp_auth_key_put() on asoc->asoc_shared_key is called twice when having refcnt 1, once directly in sctp_assoc_update() and yet again from within sctp_auth_asoc_init_active_key() via sctp_assoc_update() on the already kzfree'd memory, which is also consistent with the observation of the poison decrease from 0x6b to 0x6a (note: the overwrite is detected at a later point in time when poison is checked on new allocation).
Reference counting of auth keys revisited:
Shared keys for AUTH chunks are being stored in endpoints and associations in endpoint_shared_keys list. On endpoint creation, a null key is being added; on association creation, all endpoint shared keys are being cached and thus cloned over to the association. struct sctp_shared_key only holds a pointer to the actual key bytes, that is, struct sctp_auth_bytes which keeps track of users internally through refcounting. Naturally, on assoc or enpoint destruction, sctp_shared_key are being destroyed directly and the reference on sctp_auth_bytes dropped.
User space can add keys to either list via setsockopt(2) through struct sctp_authkey and by passing that to sctp_auth_set_key() which replaces or adds a new auth key. There, sctp_auth_create_key() creates a new sctp_auth_bytes with refcount 1 and in case of replacement drops the reference on the old sctp_auth_bytes. A key can be set active from user space through setsockopt() on the id via sctp_auth_set_active_key(), which iterates through either endpoint_shared_keys and in case of an assoc, invokes (one of various places) sctp_auth_asoc_init_active_key().
sctp_auth_asoc_init_active_key() computes the actual secret from local's and peer's random, hmac and shared key parameters and returns a new key directly as sctp_auth_bytes, that is asoc->asoc_shared_key, plus drops the reference if there was a previous one. The secret, which where we eventually double drop the ref comes from sctp_auth_asoc_set_secret() with intitial refcount of 1, which also stays unchanged eventually in sctp_assoc_update(). This key is later being used for crypto layer to set the key for the hash in crypto_hash_setkey() from sctp_auth_calculate_hmac().
To close the loop: asoc->asoc_shared_key is freshly allocated secret material and independant of the sctp_shared_key management keeping track of only shared keys in endpoints and assocs. Hence, also commit 4184b2a79a76 ("net: sctp: fix memory leak in auth key management") is independant of this bug here since it concerns a different layer (though same structures being used eventually). asoc->asoc_shared_key is reference dropped correctly on assoc destruction in sctp_association_free() and when active keys are being replaced in sctp_auth_asoc_init_active_key(), it always has a refcount of 1. Hence, it's freed prematurely in sctp_assoc_update(). Simple fix is to remove that sctp_auth_key_put() from there which fixes these panics.
--- net/sctp/associola.c | 1 - 1 file changed, 1 deletion(-)
net/sctp/associola.c +0 -1
@@ -1297,7 +1297,6 @@ void sctp_assoc_update(struct sctp_assoc asoc->peer.peer_hmacs = new->peer.peer_hmacs; new->peer.peer_hmacs =NULL ; -sctp_auth_key_put (asoc->asoc_shared_key);sctp_auth_asoc_init_active_key (asoc,GFP_ATOMIC ); }
Greg Kroah-Hartman
maintainerPATCH 6/16 ipv4: try to cache dst_entries which would cause a redirect
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Frederic Sowa <[email protected]>
[ Upstream commit df4d92549f23e1c037e83323aff58a21b3de7fe0 ]
Not caching dst_entries which cause redirects could be exploited by hosts on the same subnet, causing a severe DoS attack. This effect aggravated since commit f88649721268999 ("ipv4: fix dst race in sk_dst_get()").
Lookups causing redirects will be allocated with DST_NOCACHE set which will force dst_release to free them via RCU. Unfortunately waiting for RCU grace period just takes too long, we can end up with >1M dst_entries waiting to be released and the system will run OOM. rcuos threads cannot catch up under high softirq load.
Attaching the flag to emit a redirect later on to the specific skb allows us to cache those dst_entries thus reducing the pressure on allocation and deallocation.
This issue was discovered by Marcelo Leitner.
--- include/net/ip.h | 11 ++++++----- net/ipv4/ip_forward.c | 3 ++- net/ipv4/route.c | 9 +++++---- 3 files changed, 13 insertions(+), 10 deletions(-)
include/net/ip.h +6 -5
@@ -37,11 +37,12 @@ struct inet_skb_parm {struct ip_options opt;/* Compiled IP options */ unsigned char flags; -#define IPSKB_FORWARDED 1 -#define IPSKB_XFRM_TUNNEL_SIZE 2 -#define IPSKB_XFRM_TRANSFORMED 4 -#define IPSKB_FRAG_COMPLETE 8 -#define IPSKB_REROUTED 16 +#define IPSKB_FORWARDED BIT(0) +#define IPSKB_XFRM_TUNNEL_SIZE BIT(1) +#define IPSKB_XFRM_TRANSFORMED BIT(2) +#define IPSKB_FRAG_COMPLETE BIT(3) +#define IPSKB_REROUTED BIT(4) +#define IPSKB_DOREDIRECT BIT(5)u16 frag_max_size; };
net/ipv4/ip_forward.c +2 -1
@@ -175,7 +175,8 @@ int ip_forward(struct sk_buff *skb)* We now generate an ICMP HOST REDIRECT giving the route * we calculated. */ -if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path (skb)) +if (IPCB (skb)->flags &IPSKB_DOREDIRECT && !opt->srr && + !skb_sec_path (skb))ip_rt_send_redirect (skb); skb->priority =rt_tos2priority (iph->tos);
net/ipv4/route.c +5 -4
@@ -1514,11 +1514,10 @@ static int __mkroute_input(struct sk_buf do_cache = res->fi && !itag;if (out_dev == in_dev && err &&IN_DEV_TX_REDIRECTS (out_dev) && + skb->protocol ==htons (ETH_P_IP ) && (IN_DEV_SHARED_MEDIA (out_dev) || -inet_addr_onlink (out_dev, saddr,FIB_RES_GW (*res)))) { - flags |=RTCF_DOREDIRECT ; - do_cache = false; - } +inet_addr_onlink (out_dev, saddr,FIB_RES_GW (*res)))) +IPCB (skb)->flags |=IPSKB_DOREDIRECT ;if (skb->protocol !=htons (ETH_P_IP )) {/* Not IP (i.e. ARP). Do not create route, if it is
@@ -2255,6 +2254,8 @@ static int rt_fill_info(struct net *net, r->rtm_flags = (rt->rt_flags & ~0xFFFF ) |RTM_F_CLONED ;if (rt->rt_flags &RTCF_NOTIFY ) r->rtm_flags |=RTM_F_NOTIFY ; +if (IPCB (skb)->flags &IPSKB_DOREDIRECT ) + r->rtm_flags |=RTCF_DOREDIRECT ;if (nla_put_be32 (skb,RTA_DST , dst)) goto nla_put_failure;
Greg Kroah-Hartman
maintainerPATCH 7/16 udp_diag: Fix socket skipping within chain
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu <[email protected]>
[ Upstream commit 86f3cddbc3037882414c7308973530167906b7e9 ]
While working on rhashtable walking I noticed that the UDP diag dumping code is buggy. In particular, the socket skipping within a chain never happens, even though we record the number of sockets that should be skipped.
As this code was supposedly copied from TCP, this patch does what TCP does and resets num before we walk a chain.
--- net/ipv4/udp_diag.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/ipv4/udp_diag.c +3 -1
@@ -99,11 +99,13 @@ static void udp_dump(struct udp_table *t s_slot = cb->args[0 ]; num = s_num = cb->args[1 ]; -for (slot = s_slot; slot <= table->mask; num = s_num =0 , slot++) { +for (slot = s_slot; slot <= table->mask; s_num =0 , slot++) {struct sock *sk;struct hlist_nulls_node *node;struct udp_hslot *hslot = &table->hash[slot]; + num =0 ; +if (hlist_nulls_empty (&hslot->head))continue ;
Greg Kroah-Hartman
maintainerPATCH 8/16 ping: Fix race in free in receive path
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: "[email protected]" <[email protected]>
[ Upstream commit fc752f1f43c1c038a2c6ae58cc739ebb5953ccb0 ]
An exception is seen in ICMP ping receive path where the skb destructor sock_rfree() tries to access a freed socket. This happens because ping_rcv() releases socket reference with sock_put() and this internally frees up the socket. Later icmp_rcv() will try to free the skb and as part of this, skb destructor is called and which leads to a kernel panic as the socket is freed already in ping_rcv().
-->|exception
-007|sk_mem_uncharge -007|sock_rfree -008|skb_release_head_state -009|skb_release_all -009|__kfree_skb -010|kfree_skb -011|icmp_rcv -012|ip_local_deliver_finish
Fix this incorrect free by cloning this skb and processing this cloned skb instead.
This patch was suggested by Eric Dumazet
--- net/ipv4/ping.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/ipv4/ping.c +4 -1
@@ -720,8 +720,11 @@ void ping_rcv(struct sk_buff *skb) sk =ping_v4_lookup (net, saddr, daddr,ntohs (icmph->un.echo.id), skb->dev->ifindex);if (sk !=NULL ) { +struct sk_buff *skb2 =skb_clone (skb,GFP_ATOMIC ); +pr_debug ("rcv on socket %p\n" , sk); -ping_queue_rcv_skb (sk,skb_get (skb)); +if (skb2) +ping_queue_rcv_skb (sk, skb2);sock_put (sk);return ; }
Greg Kroah-Hartman
maintainerPATCH 9/16 ipv6: replacing a rt6_info needs to purge possible propagated rt6_infos too
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Frederic Sowa <[email protected]>
[ Upstream commit 6e9e16e6143b725662e47026a1d0f270721cdd24 ]
Lubomir Rintel reported that during replacing a route the interface reference counter isn't correctly decremented.
To quote bug <https://bugzilla.kernel.org/show_bug.cgi?id=91941>:
| [root@rhel7-5 lkundrak]# sh -x lal | + ip link add dev0 type dummy | + ip link set dev0 up | + ip link add dev1 type dummy | + ip link set dev1 up | + ip addr add 2001:db8:8086::2/64 dev dev0 | + ip route add 2001:db8:8086::/48 dev dev0 proto static metric 20 | + ip route add 2001:db8:8088::/48 dev dev1 proto static metric 10 | + ip route replace 2001:db8:8086::/48 dev dev1 proto static metric 20 | + ip link del dev0 type dummy | Message from syslogd@rhel7-5 at Jan 23 10:54:41 ... | kernel:unregister_netdevice: waiting for dev0 to become free. Usage count = 2 | | Message from syslogd@rhel7-5 at Jan 23 10:54:51 ... | kernel:unregister_netdevice: waiting for dev0 to become free. Usage count = 2
During replacement of a rt6_info we must walk all parent nodes and check if the to be replaced rt6_info got propagated. If so, replace it with an alive one.
--- net/ipv6/ip6_fib.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-)
net/ipv6/ip6_fib.c +26 -19
@@ -638,6 +638,29 @@ static inline bool rt6_qualify_for_ecmp(RTF_GATEWAY ; } +static void fib6_purge_rt (struct rt6_info *rt,struct fib6_node *fn, +struct net *net) +{ +if (atomic_read (&rt->rt6i_ref) !=1 ) { +/* This route is used as dummy address holder in some split +* nodes. It is not leaked, but it still holds other resources, +* which must be released in time. So, scan ascendant nodes +* and replace dummy references to this route with references +* to still alive ones. +*/ +while (fn) { +if (!(fn->fn_flags &RTN_RTINFO ) && fn->leaf == rt) { + fn->leaf =fib6_find_prefix (net, fn); +atomic_inc (&fn->leaf->rt6i_ref); +rt6_release (rt); + } + fn = fn->parent; + } +/* No more references are possible at this point. */ +BUG_ON (atomic_read (&rt->rt6i_ref) !=1 ); + } +} +/* * Insert routing information in a node. */
@@ -775,11 +798,12 @@ add: rt->dst.rt6_next = iter->dst.rt6_next;atomic_inc (&rt->rt6i_ref);inet6_rt_notify (RTM_NEWROUTE , rt, info); -rt6_release (iter);if (!(fn->fn_flags &RTN_RTINFO )) { info->nl_net->ipv6.rt6_stats->fib_route_nodes++; fn->fn_flags |=RTN_RTINFO ; } +fib6_purge_rt (iter, fn, info->nl_net); +rt6_release (iter); }return 0 ;
@@ -1284,24 +1308,7 @@ static void fib6_del_route(struct fib6_n fn =fib6_repair_tree (net, fn); } -if (atomic_read (&rt->rt6i_ref) !=1 ) { -/* This route is used as dummy address holder in some split -* nodes. It is not leaked, but it still holds other resources, -* which must be released in time. So, scan ascendant nodes -* and replace dummy references to this route with references -* to still alive ones. -*/ -while (fn) { -if (!(fn->fn_flags &RTN_RTINFO ) && fn->leaf == rt) { - fn->leaf =fib6_find_prefix (net, fn); -atomic_inc (&fn->leaf->rt6i_ref); -rt6_release (rt); - } - fn = fn->parent; - } -/* No more references are possible at this point. */ -BUG_ON (atomic_read (&rt->rt6i_ref) !=1 ); - } +fib6_purge_rt (rt, fn, net);inet6_rt_notify (RTM_DELROUTE , rt, info);rt6_release (rt);
Greg Kroah-Hartman
maintainerPATCH 10/16 bridge: dont send notification when skb->len == 0 in rtnl_bridge_notify
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Roopa Prabhu <[email protected]>
[ Upstream commit 59ccaaaa49b5b096cdc1f16706a9f931416b2332 ]
Reported in: https://bugzilla.kernel.org/show_bug.cgi?id=92081
This patch avoids calling rtnl_notify if the device ndo_bridge_getlink handler does not return any bytes in the skb.
Alternately, the skb->len check can be moved inside rtnl_notify.
For the bridge vlan case described in 92081, there is also a fix needed in bridge driver to generate a proper notification. Will fix that in subsequent patch.
v2: rebase patch on net tree
--- net/core/rtnetlink.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/core/rtnetlink.c +5 -1
@@ -2477,12 +2477,16 @@ static int rtnl_bridge_notify(struct net goto errout; } +if (!skb->len) + goto errout; +rtnl_notify (skb, net,0 ,RTNLGRP_LINK ,NULL ,GFP_ATOMIC );return 0 ; errout:WARN_ON (err == -EMSGSIZE );kfree_skb (skb); -rtnl_set_sk_err (net,RTNLGRP_LINK , err); +if (err) +rtnl_set_sk_err (net,RTNLGRP_LINK , err);return err; }
Greg Kroah-Hartman
maintainerPATCH 11/16 tcp: ipv4: initialize unicast_sock sk_pacing_rate
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 811230cd853d62f09ed0addd0ce9a1b9b0e13fb5 ]
When I added sk_pacing_rate field, I forgot to initialize its value in the per cpu unicast_sock used in ip_send_unicast_reply()
This means that for sch_fq users, RST packets, or ACK packets sent on behalf of TIME_WAIT sockets might be sent to slowly or even dropped once we reach the per flow limit.
--- net/ipv4/ip_output.c | 1 + 1 file changed, 1 insertion(+)
net/ipv4/ip_output.c +1 -0
@@ -1465,6 +1465,7 @@ static DEFINE_PER_CPU(struct inet_sock, .sk_wmem_alloc = ATOMIC_INIT(1), .sk_allocation = GFP_ATOMIC, .sk_flags = (1UL << SOCK_USE_WRITE_QUEUE), + .sk_pacing_rate = ~0U, }, .pmtudisc = IP_PMTUDISC_WANT, .uc_ttl = -1,
Greg Kroah-Hartman
maintainerPATCH 12/16 ipv4: tcp: get rid of ugly unicast_sock
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit bdbbb8527b6f6a358dbcb70dac247034d665b8e4 ]
In commit be9f4a44e7d41 ("ipv4: tcp: remove per net tcp_sock") I tried to address contention on a socket lock, but the solution I chose was horrible :
commit 3a7c384ffd57e ("ipv4: tcp: unicast_sock should not land outside of TCP stack") addressed a selinux regression.
commit 0980e56e506b ("ipv4: tcp: set unicast_sock uc_ttl to -1") took care of another regression.
commit b5ec8eeac46 ("ipv4: fix ip_send_skb()") fixed another regression.
commit 811230cd85 ("tcp: ipv4: initialize unicast_sock sk_pacing_rate") was another shot in the dark.
Really, just use a proper socket per cpu, and remove the skb_orphan() call, to re-enable flow control.
This solves a serious problem with FQ packet scheduler when used in hostile environments, as we do not want to allocate a flow structure for every RST packet sent in response to a spoofed packet.
--- include/net/ip.h | 2 +- include/net/netns/ipv4.h | 1 + net/ipv4/ip_output.c | 30 +++--------------------------- net/ipv4/tcp_ipv4.c | 37 ++++++++++++++++++++++++++++++++----- 4 files changed, 37 insertions(+), 33 deletions(-)
include/net/ip.h +1 -1
@@ -163,7 +163,7 @@ static inline __u8 ip_reply_arg_flowi_flreturn (arg->flags &IP_REPLY_ARG_NOSRCCHECK ) ?FLOWI_FLAG_ANYSRC :0 ; } -void ip_send_unicast_reply (struct net *net,struct sk_buff *skb,__be32 daddr, +void ip_send_unicast_reply (struct sock *sk,struct sk_buff *skb,__be32 daddr,__be32 saddr,const struct ip_reply_arg *arg,unsigned int len);
include/net/netns/ipv4.h +1 -0
@@ -43,6 +43,7 @@ struct netns_ipv4 {struct inet_peer_base *peers;struct tcpm_hash_bucket *tcp_metrics_hash;unsigned int tcp_metrics_hash_log; +struct sock *__percpu *tcp_sk;struct netns_frags frags;#ifdef CONFIG_NETFILTER struct xt_table *iptable_filter;
net/ipv4/ip_output.c +3 -27
@@ -1454,24 +1454,8 @@ static int ip_reply_glue_bits(void *dptr/* * Generic function to send a packet as reply to another packet. * Used to send some TCP resets/acks so far. -* -* Use a fake percpu inet socket to avoid false sharing and contention. */ -static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = { - .sk = { - .__sk_common = { - .skc_refcnt =ATOMIC_INIT (1 ), - }, - .sk_wmem_alloc =ATOMIC_INIT (1 ), - .sk_allocation =GFP_ATOMIC , - .sk_flags = (1UL <<SOCK_USE_WRITE_QUEUE ), - .sk_pacing_rate = ~0U , - }, - .pmtudisc =IP_PMTUDISC_WANT , - .uc_ttl =-1 , -}; - -void ip_send_unicast_reply (struct net *net,struct sk_buff *skb,__be32 daddr, +void ip_send_unicast_reply (struct sock *sk,struct sk_buff *skb,__be32 daddr,__be32 saddr,const struct ip_reply_arg *arg,unsigned int len) {
@@ -1479,9 +1463,8 @@ void ip_send_unicast_reply(struct net *nstruct ipcm_cookie ipc;struct flowi4 fl4;struct rtable *rt =skb_rtable (skb); +struct net *net =sock_net (sk);struct sk_buff *nskb; -struct sock *sk; -struct inet_sock *inet;int err;if (ip_options_echo (&replyopts.opt.opt, skb))
@@ -1509,15 +1492,11 @@ void ip_send_unicast_reply(struct net *nif (IS_ERR (rt))return ; - inet = &get_cpu_var (unicast_sock); +inet_sk (sk)->tos = arg->tos; - inet->tos = arg->tos; - sk = &inet->sk; sk->sk_priority = skb->priority; sk->sk_protocol =ip_hdr (skb)->protocol; sk->sk_bound_dev_if = arg->bound_dev_if; -sock_net_set (sk, net); -__skb_queue_head_init (&sk->sk_write_queue); sk->sk_sndbuf = sysctl_wmem_default; err =ip_append_data (sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, len,0 , &ipc, &rt,MSG_DONTWAIT );
@@ -1533,13 +1512,10 @@ void ip_send_unicast_reply(struct net *n arg->csumoffset) = csum_fold(csum_add(nskb->csum, arg->csum)); nskb->ip_summed =CHECKSUM_NONE ; -skb_orphan (nskb);skb_set_queue_mapping (nskb,skb_get_queue_mapping (skb));ip_push_pending_frames (sk, &fl4); } out: -put_cpu_var (unicast_sock); -ip_rt_put (rt); }
net/ipv4/tcp_ipv4.c +32 -5
@@ -707,7 +707,8 @@ static void tcp_v4_send_reset(struct soc net =dev_net (skb_dst (skb)->dev); arg.tos =ip_hdr (skb)->tos; -ip_send_unicast_reply (net, skb,ip_hdr (skb)->saddr, +ip_send_unicast_reply (*this_cpu_ptr (net->ipv4.tcp_sk), + skb,ip_hdr (skb)->saddr,ip_hdr (skb)->daddr, &arg, arg.iov[0 ].iov_len);TCP_INC_STATS_BH (net,TCP_MIB_OUTSEGS );
@@ -790,7 +791,8 @@ static void tcp_v4_send_ack(struct sk_buif (oif) arg.bound_dev_if = oif; arg.tos = tos; -ip_send_unicast_reply (net, skb,ip_hdr (skb)->saddr, +ip_send_unicast_reply (*this_cpu_ptr (net->ipv4.tcp_sk), + skb,ip_hdr (skb)->saddr,ip_hdr (skb)->daddr, &arg, arg.iov[0 ].iov_len);TCP_INC_STATS_BH (net,TCP_MIB_OUTSEGS );
@@ -2898,14 +2900,39 @@ struct proto tcp_prot = { };EXPORT_SYMBOL (tcp_prot); +static void __net_exit tcp_sk_exit(struct net *net) +{ +int cpu; + +for_each_possible_cpu (cpu) +inet_ctl_sock_destroy (*per_cpu_ptr (net->ipv4.tcp_sk, cpu)); +free_percpu (net->ipv4.tcp_sk); +} +static int __net_init tcp_sk_init (struct net *net) { +int res, cpu; + + net->ipv4.tcp_sk = alloc_percpu(struct sock *); +if (!net->ipv4.tcp_sk) +return -ENOMEM ; + +for_each_possible_cpu (cpu) { +struct sock *sk; + + res =inet_ctl_sock_create (&sk,PF_INET ,SOCK_RAW , +IPPROTO_TCP , net); +if (res) + goto fail; + *per_cpu_ptr (net->ipv4.tcp_sk, cpu) = sk; + } net->ipv4.sysctl_tcp_ecn =2 ;return 0 ; -} -static void __net_exit tcp_sk_exit(struct net *net) -{ +fail: +tcp_sk_exit (net); + +return res; } static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list)
Greg Kroah-Hartman
maintainerPATCH 13/16 ppp: deflate: never return len larger than output buffer
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit e2a4800e75780ccf4e6c2487f82b688ba736eb18 ]
When we've run out of space in the output buffer to store more data, we will call zlib_deflate with a NULL output buffer until we've consumed remaining input.
When this happens, olen contains the size the output buffer would have consumed iff we'd have had enough room.
This can later cause skb_over_panic when ppp_generic skb_put()s the returned length.
--- drivers/net/ppp/ppp_deflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ppp/ppp_deflate.c +1 -1
@@ -246,7 +246,7 @@ static int z_compress(void *arg, unsigne/* * See if we managed to reduce the size of the packet. */ -if (olen < isize) { +if (olen < isize && olen <= osize) { state->stats.comp_bytes += olen; state->stats.comp_packets++; }else {
Greg Kroah-Hartman
maintainerPATCH 14/16 net: sctp: fix passing wrong parameter header to param_type2af in sctp_process_param
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Saran Maruti Ramanara <[email protected]>
[ Upstream commit cfbf654efc6d78dc9812e030673b86f235bf677d ]
When making use of RFC5061, section 4.2.4. for setting the primary IP address, we're passing a wrong parameter header to param_type2af(), resulting always in NULL being returned.
At this point, param.p points to a sctp_addip_param struct, containing a sctp_paramhdr (type = 0xc004, length = var), and crr_id as a correlation id. Followed by that, as also presented in RFC5061 section 4.2.4., comes the actual sctp_addr_param, which also contains a sctp_paramhdr, but this time with the correct type SCTP_PARAM_IPV{4,6}_ADDRESS that param_type2af() can make use of. Since we already hold a pointer to addr_param from previous line, just reuse it for param_type2af().
--- net/sctp/sm_make_chunk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sctp/sm_make_chunk.c +1 -1
@@ -2595,7 +2595,7 @@ do_addr_param: addr_param = param.v +sizeof (sctp_addip_param_t); - af =sctp_get_af_specific (param_type2af (param.p->type)); + af =sctp_get_af_specific (param_type2af (addr_param->p.type));if (af ==NULL )break ;
Greg Kroah-Hartman
maintainerPATCH 15/16 media/rc: Send sync space information on the lirc device
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Austin Lund <[email protected]>
commit a8f29e89f2b54fbf2c52be341f149bc195b63a8b upstream.
Userspace expects to see a long space before the first pulse is sent on the lirc device. Currently, if a long time has passed and a new packet is started, the lirc codec just returns and doesn't send anything. This makes lircd ignore many perfectly valid signals unless they are sent in quick sucession. When a reset event is delivered, we cannot know anything about the duration of the space. But it should be safe to assume it has been a long time and we just set the duration to maximum.
--- drivers/media/rc/ir-lirc-codec.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
drivers/media/rc/ir-lirc-codec.c +9 -3
@@ -42,11 +42,17 @@ static int ir_lirc_decode(struct rc_devreturn -EINVAL ;/* Packet start */ -if (ev.reset) -return 0 ; +if (ev.reset) { +/* Userspace expects a long space event before the start of +* the signal to use as a sync. This may be done with repeat +* packets and normal samples. But if a reset has been sent +* then we assume that a long time has passed, so we send a +* space with the maximum time value. */ + sample =LIRC_SPACE (LIRC_VALUE_MASK ); +IR_dprintk (2 ,"delivering reset sync space to lirc_dev\n" );/* Carrier reports */ -if (ev.carrier_report) { + }else if (ev.carrier_report) { sample =LIRC_FREQUENCY (ev.carrier);IR_dprintk (2 ,"carrier report (freq: %d)\n" , sample);
Greg Kroah-Hartman
maintainerPATCH 16/16 rbd: drop an unsafe assertion
In reply to Greg Kroah-Hartman3.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
commit 638c323c4d1f8eaf25224946e21ce8818f1bcee1 upstream.
Olivier Bonvalet reported having repeated crashes due to a failed assertion he was hitting in rbd_img_obj_callback():
Assertion failure in rbd_img_obj_callback() at line 2165:
rbd_assert(which >= img_request->next_completion);
With a lot of help from Olivier with reproducing the problem we were able to determine the object and image requests had already been completed (and often freed) at the point the assertion failed.
There was a great deal of discussion on the ceph-devel mailing list about this. The problem only arose when there were two (or more) object requests in an image request, and the problem was always seen when the second request was being completed.
The problem is due to a race in the window between setting the "done" flag on an object request and checking the image request's next completion value. When the first object request completes, it checks to see if its successor request is marked "done", and if so, that request is also completed. In the process, the image request's next_completion value is updated to reflect that both the first and second requests are completed. By the time the second request is able to check the next_completion value, it has been set to a value *greater* than its own "which" value, which caused an assertion to fail.
Fix this problem by skipping over any completion processing unless the completing object request is the next one expected. Test only for inequality (not >=), and eliminate the bad assertion.
--- drivers/block/rbd.c | 1 - 1 file changed, 1 deletion(-)
drivers/block/rbd.c +0 -1
@@ -2149,7 +2149,6 @@ static void rbd_img_obj_callback(structrbd_assert (img_request->obj_request_count >0 );rbd_assert (which !=BAD_WHICH );rbd_assert (which < img_request->obj_request_count); -rbd_assert (which >= img_request->next_completion);spin_lock_irq (&img_request->completion_lock);if (which != img_request->next_completion)
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 3.10.70 release. There are 16 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 Fri Feb 27 02:07:52 UTC 2015. Anything received after that time might be too late.
Build results:
total: 123 pass: 123 fail: 0 Qemu tests: total: 27 pass: 27 fail: 0
Details are available at http://server.roeck-us.net:8010/builders.
Guenter
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 3.10.70 release. There are 16 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 Fri Feb 27 02:07:52 UTC 2015. Anything received after that time might be too late.
Quoted 8 lines
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v3.0/stable-review/patch-3.10.70-rc1.gzand the diffstat can be found below.
thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
-- Shuah
Signature · 5 lines
Shuah Khan Sr. Linux Kernel Developer Open Source Innovation Group Samsung Research America (Silicon Valley) [email protected] | (970) 217-8978