4.4.50-stable review
Subsystems (2)
Greg Kroah-Hartman
maintainercover 4.4.50-stable review
This is the start of the stable review cycle for the 4.4.50 release. There are 20 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 Sat Feb 18 17:52:49 UTC 2017. 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.4.50-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.4.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 4.4.50-rc1
Pau Espin Pedrol <[email protected]>
tcp: fix mark propagation with fwmark_reflect enabled
Eric Dumazet <[email protected]>
l2tp: do not use udp_ioctl()
WANG Cong <[email protected]>
ping: fix a null pointer dereference
Willem de Bruijn <[email protected]>
packet: round up linear to header len
Willem de Bruijn <[email protected]>
net: introduce device min_header_len
WANG Cong <[email protected]>
sit: fix a double free on error path
Marcelo Ricardo Leitner <[email protected]>
sctp: avoid BUG_ON on sctp_wait_for_sndbuf
Benjamin Poirier <[email protected]>
mlx4: Invoke softirqs after napi_reschedule
Willem de Bruijn <[email protected]>
macvtap: read vnet_hdr_size once
Willem de Bruijn <[email protected]>
tun: read vnet_hdr_sz once
Eric Dumazet <[email protected]>
tcp: avoid infinite loop in tcp_splice_read()
Eric Dumazet <[email protected]>
ipv6: tcp: add a missing tcp_v6_restore_cb()
Eric Dumazet <[email protected]>
ip6_gre: fix ip6gre_err() invalid reads
Eric Dumazet <[email protected]>
netlabel: out of bound access in cipso_v4_validate()
Eric Dumazet <[email protected]>
ipv4: keep skb->dst around in presence of IP options
Eric Dumazet <[email protected]>
net: use a work queue to defer net_disable_timestamp() work
Eric Dumazet <[email protected]>
tcp: fix 0 divide in __tcp_select_window()
Dan Carpenter <[email protected]>
ipv6: pointer math error in ip6_tnl_parse_tlv_enc_lim()
Eric Dumazet <[email protected]>
ipv6: fix ip6_tnl_parse_tlv_enc_lim()
Eric Dumazet <[email protected]>
can: Fix kernel panic at security_sock_rcv_skb
-------------
Diffstat:
Makefile | 4 +-- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 5 +++- drivers/net/loopback.c | 1 + drivers/net/macvtap.c | 4 +-- drivers/net/tun.c | 10 +++++--- include/linux/can/core.h | 7 +++-- include/linux/netdevice.h | 4 +++ include/net/cipso_ipv4.h | 4 +++ net/can/af_can.c | 12 +++++++-- net/can/af_can.h | 3 ++- net/can/bcm.c | 4 +-- net/can/gw.c | 2 +- net/can/raw.c | 4 +-- net/core/dev.c | 31 ++++++++++------------ net/ethernet/eth.c | 1 + net/ipv4/cipso_ipv4.c | 4 +++ net/ipv4/ip_output.c | 1 + net/ipv4/ip_sockglue.c | 9 ++++++- net/ipv4/ping.c | 2 ++ net/ipv4/tcp.c | 6 +++++ net/ipv4/tcp_output.c | 6 +++-- net/ipv6/ip6_gre.c | 41 ++++++++++++++++-------------- net/ipv6/ip6_tunnel.c | 34 ++++++++++++++++--------- net/ipv6/sit.c | 1 + net/ipv6/tcp_ipv6.c | 25 ++++++++++-------- net/l2tp/l2tp_core.h | 1 + net/l2tp/l2tp_ip.c | 27 +++++++++++++++++++- net/l2tp/l2tp_ip6.c | 2 +- net/packet/af_packet.c | 7 ++--- net/sctp/socket.c | 3 ++- 30 files changed, 175 insertions(+), 90 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/20 can: Fix kernel panic at security_sock_rcv_skb
4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit f1712c73714088a7252d276a57126d56c7d37e64 ]
Zhang Yanmin reported crashes [1] and provided a patch adding a synchronize_rcu() call in can_rx_unregister()
The main problem seems that the sockets themselves are not RCU protected.
If CAN uses RCU for delivery, then sockets should be freed only after one RCU grace period.
Recent kernels could use sock_set_flag(sk, SOCK_RCU_FREE), but let's ease stable backports with the following fix instead.
[1]
BUG: unable to handle kernel NULL pointer dereference at (null) IP: [<ffffffff81495e25>] selinux_socket_sock_rcv_skb+0x65/0x2a0 Call Trace: <IRQ> [<ffffffff81485d8c>] security_sock_rcv_skb+0x4c/0x60 [<ffffffff81d55771>] sk_filter+0x41/0x210 [<ffffffff81d12913>] sock_queue_rcv_skb+0x53/0x3a0 [<ffffffff81f0a2b3>] raw_rcv+0x2a3/0x3c0 [<ffffffff81f06eab>] can_rcv_filter+0x12b/0x370 [<ffffffff81f07af9>] can_receive+0xd9/0x120 [<ffffffff81f07beb>] can_rcv+0xab/0x100 [<ffffffff81d362ac>] __netif_receive_skb_core+0xd8c/0x11f0 [<ffffffff81d36734>] __netif_receive_skb+0x24/0xb0 [<ffffffff81d37f67>] process_backlog+0x127/0x280 [<ffffffff81d36f7b>] net_rx_action+0x33b/0x4f0 [<ffffffff810c88d4>] __do_softirq+0x184/0x440 [<ffffffff81f9e86c>] do_softirq_own_stack+0x1c/0x30 <EOI> [<ffffffff810c76fb>] do_softirq.part.18+0x3b/0x40 [<ffffffff810c8bed>] do_softirq+0x1d/0x20 [<ffffffff81d30085>] netif_rx_ni+0xe5/0x110 [<ffffffff8199cc87>] slcan_receive_buf+0x507/0x520 [<ffffffff8167ef7c>] flush_to_ldisc+0x21c/0x230 [<ffffffff810e3baf>] process_one_work+0x24f/0x670 [<ffffffff810e44ed>] worker_thread+0x9d/0x6f0 [<ffffffff810e4450>] ? rescuer_thread+0x480/0x480 [<ffffffff810ebafc>] kthread+0x12c/0x150 [<ffffffff81f9ccef>] ret_from_fork+0x3f/0x70
--- include/linux/can/core.h | 7 +++---- net/can/af_can.c | 12 ++++++++++-- net/can/af_can.h | 3 ++- net/can/bcm.c | 4 ++-- net/can/gw.c | 2 +- net/can/raw.c | 4 ++-- 6 files changed, 20 insertions(+), 12 deletions(-)
include/linux/can/core.h +3 -4
@@ -45,10 +45,9 @@ struct can_proto {extern int can_proto_register (const struct can_proto *cp);extern void can_proto_unregister (const struct can_proto *cp); -extern int can_rx_register (struct net_device *dev,canid_t can_id, -canid_t mask, -void (*func)(struct sk_buff *,void *), -void *data,char *ident); +int can_rx_register (struct net_device *dev,canid_t can_id,canid_t mask, +void (*func)(struct sk_buff *,void *), +void *data,char *ident,struct sock *sk); extern void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
net/can/af_can.c +10 -2
@@ -445,6 +445,7 @@ static struct hlist_head *find_rcv_list(* @func: callback function on filter match * @data: returned parameter for callback function * @ident: string for calling module identification +* @sk: socket pointer (might be NULL) * * Description: * Invokes the callback function with the received sk_buff and the given
@@ -468,7 +469,7 @@ static struct hlist_head *find_rcv_list(*/ int can_rx_register (struct net_device *dev,canid_t can_id,canid_t mask,void (*func)(struct sk_buff *,void *),void *data, -char *ident) +char *ident,struct sock *sk) {struct receiver *r;struct hlist_head *rl;
@@ -496,6 +497,7 @@ int can_rx_register(struct net_device *d r->func = func; r->data = data; r->ident = ident; + r->sk = sk;hlist_add_head_rcu (&r->list, rl); d->entries++;
@@ -520,8 +522,11 @@ EXPORT_SYMBOL(can_rx_register);static void can_rx_delete_receiver (struct rcu_head *rp) { struct receiver *r = container_of(rp, struct receiver, rcu); +struct sock *sk = r->sk;kmem_cache_free (rcv_cache, r); +if (sk) +sock_put (sk); }/**
@@ -596,8 +601,11 @@ void can_rx_unregister(struct net_devicespin_unlock (&can_rcvlists_lock);/* schedule the receiver item for deletion */ -if (r) +if (r) { +if (r->sk) +sock_hold (r->sk);call_rcu (&r->rcu, can_rx_delete_receiver); + } }EXPORT_SYMBOL (can_rx_unregister);
net/can/af_can.h +2 -1
@@ -50,13 +50,14 @@struct receiver {struct hlist_node list; -struct rcu_head rcu;canid_t can_id;canid_t mask;unsigned long matches;void (*func)(struct sk_buff *,void *);void *data;char *ident; +struct sock *sk; +struct rcu_head rcu; };#define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
net/can/bcm.c +2 -2
@@ -1179,7 +1179,7 @@ static int bcm_rx_setup(struct bcm_msg_h err =can_rx_register (dev, op->can_id,REGMASK (op->can_id), bcm_rx_handler, op, -"bcm" ); +"bcm" , sk); op->rx_reg_dev = dev;dev_put (dev);
@@ -1188,7 +1188,7 @@ static int bcm_rx_setup(struct bcm_msg_h }else err =can_rx_register (NULL , op->can_id,REGMASK (op->can_id), - bcm_rx_handler, op,"bcm" ); + bcm_rx_handler, op,"bcm" , sk);if (err) {/* this bcm rx op is broken -> remove it */ list_del (&op->list);
net/can/gw.c +1 -1
@@ -442,7 +442,7 @@ static inline int cgw_register_filter(st {return can_rx_register (gwj->src.dev, gwj->ccgw.filter.can_id, gwj->ccgw.filter.can_mask, can_can_gw_rcv, - gwj,"gw" ); + gwj,"gw" ,NULL ); }static inline void cgw_unregister_filter (struct cgw_job *gwj)
net/can/raw.c +2 -2
@@ -190,7 +190,7 @@ static int raw_enable_filters(struct netfor (i =0 ; i < count; i++) { err =can_rx_register (dev, filter[i].can_id, filter[i].can_mask, - raw_rcv, sk,"raw" ); + raw_rcv, sk,"raw" , sk);if (err) {/* clean up successfully registered filters */ while (--i >=0 )
@@ -211,7 +211,7 @@ static int raw_enable_errfilter(struct nif (err_mask) err =can_rx_register (dev,0 , err_mask |CAN_ERR_FLAG , - raw_rcv, sk,"raw" ); + raw_rcv, sk,"raw" , sk);return err; }
Greg Kroah-Hartman
maintainerPATCH 2/20 ipv6: fix ip6_tnl_parse_tlv_enc_lim()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit fbfa743a9d2a0ffa24251764f10afc13eb21e739 ]
This function suffers from multiple issues.
First one is that pskb_may_pull() may reallocate skb->head, so the 'raw' pointer needs either to be reloaded or not used at all.
Second issue is that NEXTHDR_DEST handling does not validate that the options are present in skb->data, so we might read garbage or access non existent memory.
With help from Willem de Bruijn.
--- net/ipv6/ip6_tunnel.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-)
net/ipv6/ip6_tunnel.c +22 -12
@@ -479,18 +479,19 @@ ip6_tnl_dev_uninit(struct net_device *de__u16 ip6_tnl_parse_tlv_enc_lim (struct sk_buff *skb,__u8 *raw) { -const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw; -__u8 nexthdr = ipv6h->nexthdr; -__u16 off =sizeof (*ipv6h); +const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw; +unsigned int nhoff = raw - skb->data; +unsigned int off = nhoff +sizeof (*ipv6h); +u8 next, nexthdr = ipv6h->nexthdr;while (ipv6_ext_hdr (nexthdr) && nexthdr !=NEXTHDR_NONE ) { -__u16 optlen =0 ;struct ipv6_opt_hdr *hdr; -if (raw + off +sizeof (*hdr) > skb->data && - !pskb_may_pull (skb, raw - skb->data + off +sizeof (*hdr))) +u16 optlen; + +if (!pskb_may_pull (skb, off +sizeof (*hdr)))break ; - hdr = (struct ipv6_opt_hdr *) (raw + off); + hdr = (struct ipv6_opt_hdr *)(skb->data + off);if (nexthdr ==NEXTHDR_FRAGMENT ) {struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;if (frag_hdr->frag_off)
@@ -501,20 +502,29 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct s }else { optlen =ipv6_optlen (hdr); } +/* cache hdr->nexthdr, since pskb_may_pull() might +* invalidate hdr +*/ + next = hdr->nexthdr;if (nexthdr ==NEXTHDR_DEST ) { -__u16 i = off +2 ; +u16 i =2 ; + +/* Remember : hdr is no longer valid at this point. */ +if (!pskb_may_pull (skb, off + optlen)) +break ; +while (1 ) {struct ipv6_tlv_tnl_enc_lim *tel;/* No more room for encapsulation limit */ -if (i +sizeof (*tel) > off + optlen) +if (i +sizeof (*tel) > optlen)break ; - tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i]; + tel = (struct ipv6_tlv_tnl_enc_lim *) skb->data + off + i;/* return index of option if found and valid */ if (tel->type ==IPV6_TLV_TNL_ENCAP_LIMIT && tel->length ==1 ) -return i; +return i + off - nhoff;/* else jump to next option */ if (tel->type) i += tel->length +2 ;
@@ -522,7 +532,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct s i++; } } - nexthdr = hdr->nexthdr; + nexthdr = next; off += optlen; }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 3/20 ipv6: pointer math error in ip6_tnl_parse_tlv_enc_lim()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 63117f09c768be05a0bf465911297dc76394f686 ]
Casting is a high precedence operation but "off" and "i" are in terms of bytes so we need to have some parenthesis here.
--- net/ipv6/ip6_tunnel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/ip6_tunnel.c +1 -1
@@ -520,7 +520,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sif (i +sizeof (*tel) > optlen)break ; - tel = (struct ipv6_tlv_tnl_enc_lim *) skb->data + off + i; + tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i);/* return index of option if found and valid */ if (tel->type ==IPV6_TLV_TNL_ENCAP_LIMIT && tel->length ==1 )
Greg Kroah-Hartman
maintainerPATCH 4/20 tcp: fix 0 divide in __tcp_select_window()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 06425c308b92eaf60767bc71d359f4cbc7a561f8 ]
syszkaller fuzzer was able to trigger a divide by zero, when TCP window scaling is not enabled.
SO_RCVBUF can be used not only to increase sk_rcvbuf, also to decrease it below current receive buffers utilization.
If mss is negative or 0, just return a zero TCP window.
--- net/ipv4/tcp_output.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/ipv4/tcp_output.c +4 -2
@@ -2383,9 +2383,11 @@ u32 __tcp_select_window(struct sock *sk)int full_space =min_t (int, tp->window_clamp, allowed_space);int window; -if (mss > full_space) +if (unlikely (mss > full_space)) { mss = full_space; - +if (mss <=0 ) +return 0 ; + }if (free_space < (full_space >>1 )) { icsk->icsk_ack.quick =0 ;
Greg Kroah-Hartman
maintainerPATCH 5/20 net: use a work queue to defer net_disable_timestamp() work
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 5fa8bbda38c668e56b0c6cdecced2eac2fe36dec ]
Dmitry reported a warning [1] showing that we were calling net_disable_timestamp() -> static_key_slow_dec() from a non process context.
Grabbing a mutex while holding a spinlock or rcu_read_lock() is not allowed.
As Cong suggested, we now use a work queue.
It is possible netstamp_clear() exits while netstamp_needed_deferred is not zero, but it is probably not worth trying to do better than that.
netstamp_needed_deferred atomic tracks the exact number of deferred decrements.
[1]
[ INFO: suspicious RCU usage. ]
4.10.0-rc5+ #192 Not tainted
-------------------------------./include/linux/rcupdate.h:561 Illegal context switch in RCU read-side critical section!
other info that might help us debug this:
rcu_scheduler_active = 2, debug_locks = 0
2 locks held by syz-executor14/23111:
#0: (sk_lock-AF_INET6){+.+.+.}, at: [<ffffffff83a35c35>] lock_sockinclude/net/sock.h:1454 [inline]
#0: (sk_lock-AF_INET6){+.+.+.}, at: [<ffffffff83a35c35>]
rawv6_sendmsg+0x1e65/0x3ec0 net/ipv6/raw.c:919
#1: (rcu_read_lock){......}, at: [<ffffffff83ae2678>] nf_hook
include/linux/netfilter.h:201 [inline]
#1: (rcu_read_lock){......}, at: [<ffffffff83ae2678>]
__ip6_local_out+0x258/0x840 net/ipv6/output_core.c:160
stack backtrace:
CPU: 2 PID: 23111 Comm: syz-executor14 Not tainted 4.10.0-rc5+ #192
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs
01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:15 [inline]
dump_stack+0x2ee/0x3ef lib/dump_stack.c:51
lockdep_rcu_suspicious+0x139/0x180 kernel/locking/lockdep.c:4452
rcu_preempt_sleep_check include/linux/rcupdate.h:560 [inline]
___might_sleep+0x560/0x650 kernel/sched/core.c:7748
__might_sleep+0x95/0x1a0 kernel/sched/core.c:7739
mutex_lock_nested+0x24f/0x1730 kernel/locking/mutex.c:752
atomic_dec_and_mutex_lock+0x119/0x160 kernel/locking/mutex.c:1060
__static_key_slow_dec+0x7a/0x1e0 kernel/jump_label.c:149
static_key_slow_dec+0x51/0x90 kernel/jump_label.c:174
net_disable_timestamp+0x3b/0x50 net/core/dev.c:1728
sock_disable_timestamp+0x98/0xc0 net/core/sock.c:403
__sk_destruct+0x27d/0x6b0 net/core/sock.c:1441
sk_destruct+0x47/0x80 net/core/sock.c:1460
__sk_free+0x57/0x230 net/core/sock.c:1468
sock_wfree+0xae/0x120 net/core/sock.c:1645
skb_release_head_state+0xfc/0x200 net/core/skbuff.c:655
skb_release_all+0x15/0x60 net/core/skbuff.c:668
__kfree_skb+0x15/0x20 net/core/skbuff.c:684
kfree_skb+0x16e/0x4c0 net/core/skbuff.c:705
inet_frag_destroy+0x121/0x290 net/ipv4/inet_fragment.c:304
inet_frag_put include/net/inet_frag.h:133 [inline]
nf_ct_frag6_gather+0x1106/0x3840
net/ipv6/netfilter/nf_conntrack_reasm.c:617
ipv6_defrag+0x1be/0x2b0 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c:68
nf_hook_entry_hookfn include/linux/netfilter.h:102 [inline]
nf_hook_slow+0xc3/0x290 net/netfilter/core.c:310
nf_hook include/linux/netfilter.h:212 [inline]
__ip6_local_out+0x489/0x840 net/ipv6/output_core.c:160
ip6_local_out+0x2d/0x170 net/ipv6/output_core.c:170
ip6_send_skb+0xa1/0x340 net/ipv6/ip6_output.c:1722
ip6_push_pending_frames+0xb3/0xe0 net/ipv6/ip6_output.c:1742
rawv6_push_pending_frames net/ipv6/raw.c:613 [inline]
rawv6_sendmsg+0x2d1a/0x3ec0 net/ipv6/raw.c:927
inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:744
sock_sendmsg_nosec net/socket.c:635 [inline]
sock_sendmsg+0xca/0x110 net/socket.c:645
sock_write_iter+0x326/0x600 net/socket.c:848
do_iter_readv_writev+0x2e3/0x5b0 fs/read_write.c:695
do_readv_writev+0x42c/0x9b0 fs/read_write.c:872
vfs_writev+0x87/0xc0 fs/read_write.c:911
do_writev+0x110/0x2c0 fs/read_write.c:944
SYSC_writev fs/read_write.c:1017 [inline]
SyS_writev+0x27/0x30 fs/read_write.c:1014
entry_SYSCALL_64_fastpath+0x1f/0xc2
RIP: 0033:0x445559
RSP: 002b:00007f6f46fceb58 EFLAGS: 00000292 ORIG_RAX: 0000000000000014
RAX: ffffffffffffffda RBX: 0000000000000005 RCX: 0000000000445559
RDX: 0000000000000001 RSI: 0000000020f1eff0 RDI: 0000000000000005
RBP: 00000000006e19c0 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000292 R12: 0000000000700000
R13: 0000000020f59000 R14: 0000000000000015 R15: 0000000000020400
BUG: sleeping function called from invalid context at
kernel/locking/mutex.c:752
in_atomic(): 1, irqs_disabled(): 0, pid: 23111, name: syz-executor14
INFO: lockdep is turned off.
CPU: 2 PID: 23111 Comm: syz-executor14 Not tainted 4.10.0-rc5+ #192
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs
01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:15 [inline]
dump_stack+0x2ee/0x3ef lib/dump_stack.c:51
___might_sleep+0x47e/0x650 kernel/sched/core.c:7780
__might_sleep+0x95/0x1a0 kernel/sched/core.c:7739
mutex_lock_nested+0x24f/0x1730 kernel/locking/mutex.c:752
atomic_dec_and_mutex_lock+0x119/0x160 kernel/locking/mutex.c:1060
__static_key_slow_dec+0x7a/0x1e0 kernel/jump_label.c:149
static_key_slow_dec+0x51/0x90 kernel/jump_label.c:174
net_disable_timestamp+0x3b/0x50 net/core/dev.c:1728
sock_disable_timestamp+0x98/0xc0 net/core/sock.c:403
__sk_destruct+0x27d/0x6b0 net/core/sock.c:1441
sk_destruct+0x47/0x80 net/core/sock.c:1460
__sk_free+0x57/0x230 net/core/sock.c:1468
sock_wfree+0xae/0x120 net/core/sock.c:1645
skb_release_head_state+0xfc/0x200 net/core/skbuff.c:655
skb_release_all+0x15/0x60 net/core/skbuff.c:668
__kfree_skb+0x15/0x20 net/core/skbuff.c:684
kfree_skb+0x16e/0x4c0 net/core/skbuff.c:705
inet_frag_destroy+0x121/0x290 net/ipv4/inet_fragment.c:304
inet_frag_put include/net/inet_frag.h:133 [inline]
nf_ct_frag6_gather+0x1106/0x3840
net/ipv6/netfilter/nf_conntrack_reasm.c:617
ipv6_defrag+0x1be/0x2b0 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c:68
nf_hook_entry_hookfn include/linux/netfilter.h:102 [inline]
nf_hook_slow+0xc3/0x290 net/netfilter/core.c:310
nf_hook include/linux/netfilter.h:212 [inline]
__ip6_local_out+0x489/0x840 net/ipv6/output_core.c:160
ip6_local_out+0x2d/0x170 net/ipv6/output_core.c:170
ip6_send_skb+0xa1/0x340 net/ipv6/ip6_output.c:1722
ip6_push_pending_frames+0xb3/0xe0 net/ipv6/ip6_output.c:1742
rawv6_push_pending_frames net/ipv6/raw.c:613 [inline]
rawv6_sendmsg+0x2d1a/0x3ec0 net/ipv6/raw.c:927
inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:744
sock_sendmsg_nosec net/socket.c:635 [inline]
sock_sendmsg+0xca/0x110 net/socket.c:645
sock_write_iter+0x326/0x600 net/socket.c:848
do_iter_readv_writev+0x2e3/0x5b0 fs/read_write.c:695
do_readv_writev+0x42c/0x9b0 fs/read_write.c:872
vfs_writev+0x87/0xc0 fs/read_write.c:911
do_writev+0x110/0x2c0 fs/read_write.c:944
SYSC_writev fs/read_write.c:1017 [inline]
SyS_writev+0x27/0x30 fs/read_write.c:1014
entry_SYSCALL_64_fastpath+0x1f/0xc2
RIP: 0033:0x445559--- net/core/dev.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-)
net/core/dev.c +13 -18
@@ -1676,24 +1676,19 @@ EXPORT_SYMBOL_GPL(net_dec_ingress_queue)static struct static_key netstamp_needed__read_mostly ;#ifdef HAVE_JUMP_LABEL -/* We are not allowed to call static_key_slow_dec() from irq context -* If net_disable_timestamp() is called from irq context, defer the -* static_key_slow_dec() calls. -*/ static atomic_t netstamp_needed_deferred; -#endif - -void net_enable_timestamp (void ) +static void netstamp_clear (struct work_struct *work) { -#ifdef HAVE_JUMP_LABEL int deferred =atomic_xchg (&netstamp_needed_deferred,0 ); -if (deferred) { -while (--deferred) -static_key_slow_dec (&netstamp_needed); -return ; - } +while (deferred--) +static_key_slow_dec (&netstamp_needed); +} +static DECLARE_WORK(netstamp_work, netstamp_clear);#endif + +void net_enable_timestamp (void ) +{static_key_slow_inc (&netstamp_needed); }EXPORT_SYMBOL (net_enable_timestamp);
@@ -1701,12 +1696,12 @@ EXPORT_SYMBOL(net_enable_timestamp);void net_disable_timestamp (void ) {#ifdef HAVE_JUMP_LABEL -if (in_interrupt ()) { -atomic_inc (&netstamp_needed_deferred); -return ; - } -#endif +/* net_disable_timestamp() can be called from non process context */ +atomic_inc (&netstamp_needed_deferred); +schedule_work (&netstamp_work); +#else static_key_slow_dec (&netstamp_needed); +#endif }EXPORT_SYMBOL (net_disable_timestamp);
Greg Kroah-Hartman
maintainerPATCH 6/20 ipv4: keep skb->dst around in presence of IP options
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 34b2cef20f19c87999fff3da4071e66937db9644 ]
Andrey Konovalov got crashes in __ip_options_echo() when a NULL skb->dst is accessed.
ipv4_pktinfo_prepare() should not drop the dst if (evil) IP options are present.
We could refine the test to the presence of ts_needtime or srr, but IP options are not often used, so let's be conservative.
Thanks to syzkaller team for finding this bug.
--- net/ipv4/ip_sockglue.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
net/ipv4/ip_sockglue.c +8 -1
@@ -1192,7 +1192,14 @@ void ipv4_pktinfo_prepare(const struct s pktinfo->ipi_ifindex =0 ; pktinfo->ipi_spec_dst.s_addr =0 ; } -skb_dst_drop (skb); +/* We need to keep the dst for __ip_options_echo() +* We could restrict the test to opt.ts_needtime || opt.srr, +* but the following is good enough as IP options are not often used. +*/ +if (unlikely (IPCB (skb)->opt.optlen)) +skb_dst_force (skb); +else +skb_dst_drop (skb); } int ip_setsockopt(struct sock *sk, int level,
Greg Kroah-Hartman
maintainerPATCH 7/20 netlabel: out of bound access in cipso_v4_validate()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit d71b7896886345c53ef1d84bda2bc758554f5d61 ]
syzkaller found another out of bound access in ip_options_compile(), or more exactly in cipso_v4_validate()
--- include/net/cipso_ipv4.h | 4 ++++ net/ipv4/cipso_ipv4.c | 4 ++++ 2 files changed, 8 insertions(+)
include/net/cipso_ipv4.h +4 -0
@@ -309,6 +309,10 @@ static inline int cipso_v4_validate(cons }for (opt_iter =6 ; opt_iter < opt_len;) { +if (opt_iter +1 == opt_len) { + err_offset = opt_iter; + goto out; + } tag_len = opt[opt_iter +1 ];if ((tag_len ==0 ) || (tag_len > (opt_len - opt_iter))) { err_offset = opt_iter +1 ;
net/ipv4/cipso_ipv4.c +4 -0
@@ -1657,6 +1657,10 @@ int cipso_v4_validate(const struct sk_bu goto validate_return_locked; } +if (opt_iter +1 == opt_len) { + err_offset = opt_iter; + goto validate_return_locked; + } tag_len = tag[1 ];if (tag_len > (opt_len - opt_iter)) { err_offset = opt_iter +1 ;
Greg Kroah-Hartman
maintainerPATCH 8/20 ip6_gre: fix ip6gre_err() invalid reads
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 7892032cfe67f4bde6fc2ee967e45a8fbaf33756 ]
Andrey Konovalov reported out of bound accesses in ip6gre_err()
If GRE flags contains GRE_KEY, the following expression *(((__be32 *)p) + (grehlen / 4) - 1)
accesses data ~40 bytes after the expected point, since grehlen includes the size of IPv6 headers.
Let's use a "struct gre_base_hdr *greh" pointer to make this code more readable.
p[1] becomes greh->protocol.
grhlen is the GRE header length.
--- net/ipv6/ip6_gre.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-)
net/ipv6/ip6_gre.c +22 -19
@@ -55,6 +55,7 @@#include <net/ip6_fib.h> #include <net/ip6_route.h> #include <net/ip6_tunnel.h> +#include <net/gre.h> static bool log_ecn_error = true;
@@ -367,35 +368,37 @@ static void ip6gre_tunnel_uninit(structstatic void ip6gre_err (struct sk_buff *skb,struct inet6_skb_parm *opt, -u8 type,u8 code,int offset,__be32 info) +u8 type,u8 code,int offset,__be32 info) { -const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data; -__be16 *p = (__be16 *)(skb->data + offset); -int grehlen = offset +4 ; +const struct gre_base_hdr *greh; +const struct ipv6hdr *ipv6h; +int grehlen =sizeof (*greh);struct ip6_tnl *t; +int key_off =0 ;__be16 flags; +__be32 key; - flags = p[0 ]; -if (flags&(GRE_CSUM |GRE_KEY |GRE_SEQ |GRE_ROUTING |GRE_VERSION )) { -if (flags&(GRE_VERSION |GRE_ROUTING )) -return ; -if (flags&GRE_KEY ) { - grehlen +=4 ; -if (flags&GRE_CSUM ) - grehlen +=4 ; - } +if (!pskb_may_pull (skb, offset + grehlen)) +return ; + greh = (const struct gre_base_hdr *)(skb->data + offset); + flags = greh->flags; +if (flags & (GRE_VERSION |GRE_ROUTING )) +return ; +if (flags &GRE_CSUM ) + grehlen +=4 ; +if (flags &GRE_KEY ) { + key_off = grehlen + offset; + grehlen +=4 ; } -/* If only 8 bytes returned, keyed message will be dropped here */ -if (!pskb_may_pull (skb, grehlen)) +if (!pskb_may_pull (skb, offset + grehlen))return ; ipv6h = (const struct ipv6hdr *)skb->data; - p = (__be16 *)(skb->data + offset); + greh = (const struct gre_base_hdr *)(skb->data + offset); + key = key_off ? *(__be32 *)(skb->data + key_off) :0 ; t =ip6gre_tunnel_lookup (skb->dev, &ipv6h->daddr, &ipv6h->saddr, - flags &GRE_KEY ? - *(((__be32 *)p) + (grehlen /4 ) -1 ) :0 , - p[1 ]); + key, greh->protocol);if (!t)return ;
Greg Kroah-Hartman
maintainerPATCH 9/20 ipv6: tcp: add a missing tcp_v6_restore_cb()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit ebf6c9cb23d7e56eec8575a88071dec97ad5c6e2 ]
Dmitry reported use-after-free in ip6_datagram_recv_specific_ctl()
A similar bug was fixed in commit 8ce48623f0cf ("ipv6: tcp: restore IP6CB for pktoptions skbs"), but I missed another spot.
tcp_v6_syn_recv_sock() can indeed set np->pktoptions from ireq->pktopts
--- net/ipv6/tcp_ipv6.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-)
net/ipv6/tcp_ipv6.c +13 -11
@@ -974,6 +974,16 @@ drop:return 0 ;/* don't send reset */ } +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 )); +} + static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, struct request_sock *req, struct dst_entry *dst,
@@ -1163,8 +1173,10 @@ static struct sock *tcp_v6_syn_recv_sock sk_gfp_atomic(sk, GFP_ATOMIC));consume_skb (ireq->pktopts); ireq->pktopts =NULL ; -if (newnp->pktoptions) +if (newnp->pktoptions) { +tcp_v6_restore_cb (newnp->pktoptions);skb_set_owner_r (newnp->pktoptions, newsk); + } } }
@@ -1179,16 +1191,6 @@ 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. *
Greg Kroah-Hartman
maintainerPATCH 10/20 tcp: avoid infinite loop in tcp_splice_read()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit ccf7abb93af09ad0868ae9033d1ca8108bdaec82 ]
Splicing from TCP socket is vulnerable when a packet with URG flag is received and stored into receive queue.
__tcp_splice_read() returns 0, and sk_wait_data() immediately returns since there is the problematic skb in queue.
This is a nice way to burn cpu (aka infinite loop) and trigger soft lockups.
Again, this gem was found by syzkaller tool.
--- net/ipv4/tcp.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/ipv4/tcp.c +6 -0
@@ -783,6 +783,12 @@ ssize_t tcp_splice_read(struct socket *s ret = -EAGAIN ;break ; } +/* if __tcp_splice_read() got nothing while we have +* an skb in receive queue, we do not want to loop. +* This might happen with URG data. +*/ +if (!skb_queue_empty (&sk->sk_receive_queue)) +break ;sk_wait_data (sk, &timeo,NULL );if (signal_pending (current)) { ret =sock_intr_errno (timeo);
Greg Kroah-Hartman
maintainerPATCH 11/20 tun: read vnet_hdr_sz once
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit e1edab87faf6ca30cd137e0795bc73aa9a9a22ec ]
When IFF_VNET_HDR is enabled, a virtio_net header must precede data. Data length is verified to be greater than or equal to expected header length tun->vnet_hdr_sz before copying.
Read this value once and cache locally, as it can be updated between the test and use (TOCTOU).
--- drivers/net/tun.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/net/tun.c +6 -4
@@ -1108,9 +1108,11 @@ static ssize_t tun_get_user(struct tun_s }if (tun->flags &IFF_VNET_HDR ) { -if (len < tun->vnet_hdr_sz) +int vnet_hdr_sz =READ_ONCE (tun->vnet_hdr_sz); + +if (len < vnet_hdr_sz)return -EINVAL ; - len -= tun->vnet_hdr_sz; + len -= vnet_hdr_sz; n =copy_from_iter (&gso,sizeof (gso), from);if (n !=sizeof (gso))
@@ -1122,7 +1124,7 @@ static ssize_t tun_get_user(struct tun_sif (tun16_to_cpu (tun, gso.hdr_len) > len)return -EINVAL ; -iov_iter_advance (from, tun->vnet_hdr_sz -sizeof (gso)); +iov_iter_advance (from, vnet_hdr_sz -sizeof (gso)); }if ((tun->flags &TUN_TYPE_MASK ) ==IFF_TAP ) {
@@ -1301,7 +1303,7 @@ static ssize_t tun_put_user(struct tun_s vlan_hlen =VLAN_HLEN ;if (tun->flags &IFF_VNET_HDR ) - vnet_hdr_sz = tun->vnet_hdr_sz; + vnet_hdr_sz =READ_ONCE (tun->vnet_hdr_sz); total = skb->len + vlan_hlen + vnet_hdr_sz;
Greg Kroah-Hartman
maintainerPATCH 12/20 macvtap: read vnet_hdr_size once
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit 837585a5375c38d40361cfe64e6fd11e1addb936 ]
When IFF_VNET_HDR is enabled, a virtio_net header must precede data. Data length is verified to be greater than or equal to expected header length tun->vnet_hdr_sz before copying.
Macvtap functions read the value once, but unless READ_ONCE is used, the compiler may ignore this and read multiple times. Enforce a single read and locally cached value to avoid updates between test and use.
--- drivers/net/macvtap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/macvtap.c +2 -2
@@ -725,7 +725,7 @@ static ssize_t macvtap_get_user(struct mssize_t n;if (q->flags &IFF_VNET_HDR ) { - vnet_hdr_len = q->vnet_hdr_sz; + vnet_hdr_len =READ_ONCE (q->vnet_hdr_sz); err = -EINVAL ;if (len < vnet_hdr_len)
@@ -865,7 +865,7 @@ static ssize_t macvtap_put_user(struct mif (q->flags &IFF_VNET_HDR ) {struct virtio_net_hdr vnet_hdr; - vnet_hdr_len = q->vnet_hdr_sz; + vnet_hdr_len =READ_ONCE (q->vnet_hdr_sz);if (iov_iter_count (iter) < vnet_hdr_len)return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 13/20 mlx4: Invoke softirqs after napi_reschedule
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Poirier <[email protected]>
[ Upstream commit bd4ce941c8d5b862b2f83364be5dbe8fc8ab48f8 ]
mlx4 may schedule napi from a workqueue. Afterwards, softirqs are not run in a deterministic time frame and the following message may be logged:
NOHZ: local_softirq_pending 08
The problem is the same as what was described in commit ec13ee80145c ("virtio_net: invoke softirqs after __napi_schedule") and this patch applies the same fix to mlx4.
--- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx4/en_rx.c +4 -1
@@ -502,8 +502,11 @@ void mlx4_en_recover_from_oom(struct mlxreturn ;for (ring =0 ; ring < priv->rx_ring_num; ring++) { -if (mlx4_en_is_ring_empty (priv->rx_ring[ring])) +if (mlx4_en_is_ring_empty (priv->rx_ring[ring])) { +local_bh_disable ();napi_reschedule (&priv->rx_cq[ring]->napi); +local_bh_enable (); + } } }
Greg Kroah-Hartman
maintainerPATCH 14/20 sctp: avoid BUG_ON on sctp_wait_for_sndbuf
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marcelo Ricardo Leitner <[email protected]>
[ Upstream commit 2dcab598484185dea7ec22219c76dcdd59e3cb90 ]
Alexander Popov reported that an application may trigger a BUG_ON in sctp_wait_for_sndbuf if the socket tx buffer is full, a thread is waiting on it to queue more data and meanwhile another thread peels off the association being used by the first thread.
This patch replaces the BUG_ON call with a proper error handling. It will return -EPIPE to the original sendmsg call, similarly to what would have been done if the association wasn't found in the first place.
--- net/sctp/socket.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/sctp/socket.c +2 -1
@@ -6960,7 +6960,8 @@ static int sctp_wait_for_sndbuf(struct s*/ release_sock (sk); current_timeo =schedule_timeout (current_timeo); -BUG_ON (sk != asoc->base.sk); +if (sk != asoc->base.sk) + goto do_error;lock_sock (sk); *timeo_p = current_timeo;
Re: [PATCH 4.4 14/20] sctp: avoid BUG_ON on sctp_wait_for_sndbuf
Quoted 8 lines · Greg Kroah-Hartman
4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marcelo Ricardo Leitner <[email protected]>
[ Upstream commit
2dcab598484185dea7ec22219c76dcdd59e3cb90]
[...]
net/sctp/socket.c static int sctp_wait_for_sndbuf(struct s · line 6964
Quoted 9 lines
net/sctp/socket.c +2
-1@@ -6960,7 +6960,8 @@ static int sctp_wait_for_sndbuf(struct s*/ release_sock(sk); current_timeo = schedule_timeout(current_timeo); -BUG_ON (sk != asoc->base.sk); +if (sk != asoc->base.sk) + goto do_error;
This function normally returns with sk still locked, but in this case it returns with sk unlocked. Perhaps this check should be moved after the lock_sock(sk)?
Ben.
Quoted 5 lines
net/sctp/socket.c +0
-0lock_sock(sk);
*timeo_p=current_timeo;
Signature · 2 lines
Ben Hutchings 73.46% of all statistics are made up.
Marcelo
maintainerRe: [PATCH 4.4 14/20] sctp: avoid BUG_ON on sctp_wait_for_sndbuf
Em 21 de fevereiro de 2017 13:08:44 BRT, Ben Hutchings <[email protected]> escreveu:
Quoted 11 lines · Greg Kroah-Hartman
Quoted 1 line
4.4-stable review patch. If anyone has any objections, please let me
know.
Quoted 7 lines
------------------
From: Marcelo Ricardo Leitner <[email protected]>
[ Upstream commit
2dcab598484185dea7ec22219c76dcdd59e3cb90][...]
Quoted 14 lines
net/sctp/socket.c static int sctp_wait_for_sndbuf(struct s · line 6964
Quoted 9 lines
net/sctp/socket.c +2
-1@@ -6960,7 +6960,8 @@ static int sctp_wait_for_sndbuf(struct s*/ release_sock(sk); current_timeo = schedule_timeout(current_timeo); -BUG_ON (sk != asoc->base.sk); +if (sk != asoc->base.sk) + goto do_error;This function normally returns with sk still locked, but in this case it returns with sk unlocked. Perhaps this check should be moved after the
lock_sock(sk)?
Looks like so. Will check more in a few. Thanks Ben
Quoted 7 lines
Ben.
Quoted 5 lines
net/sctp/socket.c +0
-0lock_sock(sk);
*timeo_p=current_timeo;
Signature · 1 line
Enviado de meu dispositivo Android com K-9 mail. Desculpe-me pela brevidade.
Marcelo Ricardo Leitner
maintainerRe: [PATCH 4.4 14/20] sctp: avoid BUG_ON on sctp_wait_for_sndbuf
Quoted 29 lines · Marcelo
Em 21 de fevereiro de 2017 13:08:44 BRT, Ben Hutchings <[email protected]> escreveu:
Quoted 11 lines · Greg Kroah-Hartman
Quoted 1 line
4.4-stable review patch. If anyone has any objections, please let me
know.
Quoted 7 lines
------------------
From: Marcelo Ricardo Leitner <[email protected]>
[ Upstream commit
2dcab598484185dea7ec22219c76dcdd59e3cb90][...]
Quoted 14 lines
net/sctp/socket.c static int sctp_wait_for_sndbuf(struct s · line 6964
Quoted 9 lines
net/sctp/socket.c +2
-1@@ -6960,7 +6960,8 @@ static int sctp_wait_for_sndbuf(struct s*/ release_sock (sk); current_timeo =schedule_timeout (current_timeo); -BUG_ON (sk != asoc->base.sk); +if (sk != asoc->base.sk) + goto do_error;This function normally returns with sk still locked, but in this case it returns with sk unlocked. Perhaps this check should be moved after the
lock_sock(sk)?
Quoted 1 line
Looks like so. Will check more in a few. Thanks Ben
Yes, we need to move the check to after the lock_sock(sk) call.
There is also another problem: consider a thread A sending a packet to a new asoc (which creates a new asoc during sctp_sendsmg), and while waiting for more sndbuf space, it gets peeled off by another thread. This would cause a double-free of the asoc as sctp_sendmsg() will free this asoc thinking it errored out but it actually now belongs to another thread.
Testing both patches now, should be ready by tomorrow.
Marcelo
Quoted 11 lines
Quoted 8 lines
Ben.
Quoted 5 lines
net/sctp/socket.c +0
-0lock_sock (sk); *timeo_p = current_timeo;--
Enviado de meu dispositivo Android com K-9 mail. Desculpe-me pela brevidade.
Greg Kroah-Hartman
maintainerPATCH 15/20 sit: fix a double free on error path
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: WANG Cong <[email protected]>
[ Upstream commit d7426c69a1942b2b9b709bf66b944ff09f561484 ]
Dmitry reported a double free in sit_init_net():
kernel BUG at mm/percpu.c:689!
invalid opcode: 0000 [#1] SMP KASAN
Dumping ftrace buffer:
(ftrace buffer empty)
Modules linked in: CPU: 0 PID: 15692 Comm: syz-executor1 Not tainted 4.10.0-rc6-next-20170206 #1 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 task: ffff8801c9cc27c0 task.stack: ffff88017d1d8000 RIP: 0010:pcpu_free_area+0x68b/0x810 mm/percpu.c:689 RSP: 0018:ffff88017d1df488 EFLAGS: 00010046 RAX: 0000000000010000 RBX: 00000000000007c0 RCX: ffffc90002829000 RDX: 0000000000010000 RSI: ffffffff81940efb RDI: ffff8801db841d94 RBP: ffff88017d1df590 R08: dffffc0000000000 R09: 1ffffffff0bb3bdd R10: dffffc0000000000 R11: 00000000000135dd R12: ffff8801db841d80 R13: 0000000000038e40 R14: 00000000000007c0 R15: 00000000000007c0 FS: 00007f6ea608f700(0000) GS:ffff8801dbe00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000002000aff8 CR3: 00000001c8d44000 CR4: 00000000001426f0 DR0: 0000000020000000 DR1: 0000000020000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000600 Call Trace: free_percpu+0x212/0x520 mm/percpu.c:1264 ipip6_dev_free+0x43/0x60 net/ipv6/sit.c:1335 sit_init_net+0x3cb/0xa10 net/ipv6/sit.c:1831 ops_init+0x10a/0x530 net/core/net_namespace.c:115 setup_net+0x2ed/0x690 net/core/net_namespace.c:291 copy_net_ns+0x26c/0x530 net/core/net_namespace.c:396 create_new_namespaces+0x409/0x860 kernel/nsproxy.c:106 unshare_nsproxy_namespaces+0xae/0x1e0 kernel/nsproxy.c:205 SYSC_unshare kernel/fork.c:2281 [inline] SyS_unshare+0x64e/0xfc0 kernel/fork.c:2231 entry_SYSCALL_64_fastpath+0x1f/0xc2
This is because when tunnel->dst_cache init fails, we free dev->tstats once in ipip6_tunnel_init() and twice in sit_init_net(). This looks redundant but its ndo_uinit() does not seem enough to clean up everything here. So avoid this by setting dev->tstats to NULL after the first free, at least for -net.
--- net/ipv6/sit.c | 1 + 1 file changed, 1 insertion(+)
net/ipv6/sit.c +1 -0
@@ -1389,6 +1389,7 @@ static int ipip6_tunnel_init(struct net_ tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);if (!tunnel->dst_cache) {free_percpu (dev->tstats); + dev->tstats =NULL ;return -ENOMEM ; }
Greg Kroah-Hartman
maintainerPATCH 16/20 net: introduce device min_header_len
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit 217e6fa24ce28ec87fca8da93c9016cb78028612 ]
The stack must not pass packets to device drivers that are shorter than the minimum link layer header length.
Previously, packet sockets would drop packets smaller than or equal to dev->hard_header_len, but this has false positives. Zero length payload is used over Ethernet. Other link layer protocols support variable length headers. Support for validation of these protocols removed the min length check for all protocols.
Introduce an explicit dev->min_header_len parameter and drop all packets below this value. Initially, set it to non-zero only for Ethernet and loopback. Other protocols can follow in a patch to net-next.
--- drivers/net/loopback.c | 1 + include/linux/netdevice.h | 4 ++++ net/ethernet/eth.c | 1 + 3 files changed, 6 insertions(+)
drivers/net/loopback.c +1 -0
@@ -164,6 +164,7 @@ static void loopback_setup(struct net_de { dev->mtu =64 *1024 ; dev->hard_header_len =ETH_HLEN ;/* 14 */ + dev->min_header_len =ETH_HLEN ;/* 14 */ dev->addr_len =ETH_ALEN ;/* 6 */ dev->type =ARPHRD_LOOPBACK ;/* 0x0001*/ dev->flags =IFF_LOOPBACK ;
include/linux/netdevice.h +4 -0
@@ -1399,6 +1399,7 @@ enum netdev_priv_flags {* @mtu: Interface MTU value * @type: Interface hardware type * @hard_header_len: Maximum hardware header length. +* @min_header_len: Minimum hardware header length * * @needed_headroom: Extra headroom the hardware may need, but not in all * cases can this be guaranteed
@@ -1619,6 +1620,7 @@ struct net_device {unsigned int mtu;unsigned short type;unsigned short hard_header_len; +unsigned short min_header_len;unsigned short needed_headroom;unsigned short needed_tailroom;
@@ -2541,6 +2543,8 @@ static inline bool dev_validate_header(c {if (likely (len >= dev->hard_header_len))return true; +if (len < dev->min_header_len) +return false;if (capable (CAP_SYS_RAWIO )) {memset (ll_header + len,0 , dev->hard_header_len - len);
net/ethernet/eth.c +1 -0
@@ -353,6 +353,7 @@ void ether_setup(struct net_device *dev) dev->header_ops = ð_header_ops; dev->type =ARPHRD_ETHER ; dev->hard_header_len =ETH_HLEN ; + dev->min_header_len =ETH_HLEN ; dev->mtu =ETH_DATA_LEN ; dev->addr_len =ETH_ALEN ; dev->tx_queue_len =1000 ;/* Ethernet wants good queues */
Greg Kroah-Hartman
maintainerPATCH 17/20 packet: round up linear to header len
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit 57031eb794906eea4e1c7b31dc1e2429c0af0c66 ]
Link layer protocols may unconditionally pull headers, as Ethernet does in eth_type_trans. Ensure that the entire link layer header always lies in the skb linear segment. tpacket_snd has such a check. Extend this to packet_snd.
Variable length link layer headers complicate the computation somewhat. Here skb->len may be smaller than dev->hard_header_len.
Round up the linear length to be at least as long as the smallest of the two.
--- net/packet/af_packet.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
net/packet/af_packet.c +4 -3
@@ -2637,7 +2637,7 @@ static int packet_snd(struct socket *socint vnet_hdr_len;struct packet_sock *po =pkt_sk (sk);unsigned short gso_type =0 ; -int hlen, tlen; +int hlen, tlen, linear;int extra_len =0 ;ssize_t n;
@@ -2741,8 +2741,9 @@ static int packet_snd(struct socket *soc err = -ENOBUFS ; hlen =LL_RESERVED_SPACE (dev); tlen = dev->needed_tailroom; - skb =packet_alloc_skb (sk, hlen + tlen, hlen, len, -__virtio16_to_cpu (vio_le (), vnet_hdr.hdr_len), + linear =__virtio16_to_cpu (vio_le (), vnet_hdr.hdr_len); + linear =max (linear,min_t (int, len, dev->hard_header_len)); + skb =packet_alloc_skb (sk, hlen + tlen, hlen, len, linear, msg->msg_flags &MSG_DONTWAIT , &err);if (skb ==NULL ) goto out_unlock;
Greg Kroah-Hartman
maintainerPATCH 18/20 ping: fix a null pointer dereference
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: WANG Cong <[email protected]>
[ Upstream commit 73d2c6678e6c3af7e7a42b1e78cd0211782ade32 ]
Andrey reported a kernel crash:
general protection fault: 0000 [#1] SMP KASAN
Dumping ftrace buffer:
(ftrace buffer empty)
Modules linked in:
CPU: 2 PID: 3880 Comm: syz-executor1 Not tainted 4.10.0-rc6+ #124
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: ffff880060048040 task.stack: ffff880069be8000
RIP: 0010:ping_v4_push_pending_frames net/ipv4/ping.c:647 [inline]
RIP: 0010:ping_v4_sendmsg+0x1acd/0x23f0 net/ipv4/ping.c:837
RSP: 0018:ffff880069bef8b8 EFLAGS: 00010206
RAX: dffffc0000000000 RBX: ffff880069befb90 RCX: 0000000000000000
RDX: 0000000000000018 RSI: ffff880069befa30 RDI: 00000000000000c2
RBP: ffff880069befbb8 R08: 0000000000000008 R09: 0000000000000000
R10: 0000000000000002 R11: 0000000000000000 R12: ffff880069befab0
R13: ffff88006c624a80 R14: ffff880069befa70 R15: 0000000000000000
FS: 00007f6f7c716700(0000) GS:ffff88006de00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000004a6f28 CR3: 000000003a134000 CR4: 00000000000006e0
Call Trace:
inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:744
sock_sendmsg_nosec net/socket.c:635 [inline]
sock_sendmsg+0xca/0x110 net/socket.c:645
SYSC_sendto+0x660/0x810 net/socket.c:1687
SyS_sendto+0x40/0x50 net/socket.c:1655
entry_SYSCALL_64_fastpath+0x1f/0xc2This is because we miss a check for NULL pointer for skb_peek() when the queue is empty. Other places already have the same check.
--- net/ipv4/ping.c | 2 ++ 1 file changed, 2 insertions(+)
net/ipv4/ping.c +2 -0
@@ -645,6 +645,8 @@ static int ping_v4_push_pending_frames(s {struct sk_buff *skb =skb_peek (&sk->sk_write_queue); +if (!skb) +return 0 ; pfh->wcheck =csum_partial ((char *)&pfh->icmph,sizeof (struct icmphdr ), pfh->wcheck); pfh->icmph.checksum =csum_fold (pfh->wcheck);
Greg Kroah-Hartman
maintainerPATCH 19/20 l2tp: do not use udp_ioctl()
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 72fb96e7bdbbdd4421b0726992496531060f3636 ]
udp_ioctl(), as its name suggests, is used by UDP protocols, but is also used by L2TP :(
L2TP should use its own handler, because it really does not look the same.
SIOCINQ for instance should not assume UDP checksum or headers.
Thanks to Andrey and syzkaller team for providing the report and a nice reproducer.
While crashes only happen on recent kernels (after commit 7c13f97ffde6 ("udp: do fwd memory scheduling on dequeue")), this probably needs to be backported to older kernels.
--- net/l2tp/l2tp_core.h | 1 + net/l2tp/l2tp_ip.c | 27 ++++++++++++++++++++++++++- net/l2tp/l2tp_ip6.c | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-)
net/l2tp/l2tp_core.h +1 -0
@@ -273,6 +273,7 @@ int l2tp_xmit_skb(struct l2tp_session *sint l2tp_nl_register_ops (enum l2tp_pwtype pw_type,const struct l2tp_nl_cmd_ops *ops);void l2tp_nl_unregister_ops (enum l2tp_pwtype pw_type); +int l2tp_ioctl (struct sock *sk,int cmd,unsigned long arg);/* Session reference counts. Incremented when code obtains a reference * to a session.
net/l2tp/l2tp_ip.c +26 -1
@@ -11,6 +11,7 @@#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt +#include <asm/ioctls.h> #include <linux/icmp.h> #include <linux/module.h> #include <linux/skbuff.h>
@@ -555,6 +556,30 @@ out:return err ? err : copied; } +int l2tp_ioctl (struct sock *sk,int cmd,unsigned long arg) +{ +struct sk_buff *skb; +int amount; + +switch (cmd) { +case SIOCOUTQ : + amount =sk_wmem_alloc_get (sk); +break ; +case SIOCINQ : +spin_lock_bh (&sk->sk_receive_queue.lock); + skb =skb_peek (&sk->sk_receive_queue); + amount = skb ? skb->len :0 ; +spin_unlock_bh (&sk->sk_receive_queue.lock); +break ; + +default : +return -ENOIOCTLCMD ; + } + +return put_user (amount, (int __user *)arg); +} +EXPORT_SYMBOL (l2tp_ioctl); +static struct proto l2tp_ip_prot = { .name ="L2TP/IP" , .owner =THIS_MODULE ,
@@ -563,7 +588,7 @@ static struct proto l2tp_ip_prot = { .bind = l2tp_ip_bind, .connect = l2tp_ip_connect, .disconnect = l2tp_ip_disconnect, - .ioctl = udp_ioctl, + .ioctl = l2tp_ioctl, .destroy = l2tp_ip_destroy_sock, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt,
net/l2tp/l2tp_ip6.c +1 -1
@@ -714,7 +714,7 @@ static struct proto l2tp_ip6_prot = { .bind = l2tp_ip6_bind, .connect = l2tp_ip6_connect, .disconnect = l2tp_ip6_disconnect, - .ioctl = udp_ioctl, + .ioctl = l2tp_ioctl, .destroy = l2tp_ip6_destroy_sock, .setsockopt = ipv6_setsockopt, .getsockopt = ipv6_getsockopt,
Greg Kroah-Hartman
maintainerPATCH 20/20 tcp: fix mark propagation with fwmark_reflect enabled
In reply to Greg Kroah-Hartman4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pau Espin Pedrol <[email protected]>
commit bf99b4ded5f8a4767dbb9d180626f06c51f9881f upstream.
Otherwise, RST packets generated by the TCP stack for non-existing sockets always have mark 0.
The mark from the original packet is assigned to the netns_ipv4/6 socket used to send the response so that it can get copied into the response skb when the socket sends it.
--- net/ipv4/ip_output.c | 1 + net/ipv6/tcp_ipv6.c | 1 + 2 files changed, 2 insertions(+)
net/ipv4/ip_output.c +1 -0
@@ -1592,6 +1592,7 @@ void ip_send_unicast_reply(struct sock * sk->sk_protocol =ip_hdr (skb)->protocol; sk->sk_bound_dev_if = arg->bound_dev_if; sk->sk_sndbuf = sysctl_wmem_default; + sk->sk_mark = fl4.flowi4_mark; err =ip_append_data (sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, len,0 , &ipc, &rt,MSG_DONTWAIT );if (unlikely (err)) {
net/ipv6/tcp_ipv6.c +1 -0
@@ -822,6 +822,7 @@ static void tcp_v6_send_response(const s dst =ip6_dst_lookup_flow (ctl_sk, &fl6,NULL );if (!IS_ERR (dst)) {skb_dst_set (buff, dst); + ctl_sk->sk_mark = fl6.flowi6_mark;ip6_xmit (ctl_sk, buff, &fl6,NULL , tclass);TCP_INC_STATS_BH (net,TCP_MIB_OUTSEGS );if (rst)
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.50 release. There are 20 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 Sat Feb 18 17:52:49 UTC 2017. Anything received after that time might be too late.
Build results:
total: 149 pass: 149 fail: 0 Qemu test results: total: 115 pass: 115 fail: 0
Details are available at http://kerneltests.org/builders.
Guenter
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: 31 boots: 0 failed, 31 passed (v4.4.49-21-g967e7e889dce)
Better than the 4.9 number of boots, but still odd...