aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-09-16 13:31:58 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-09-16 13:31:58 +0200
commit2f2387e5223e1aa80876261d423f8ce7242ebe89 (patch)
tree56402f0615fe99ddc3d6305fbe232761d82c2029
parent41a221a7913ed754f56e4c3d6abed0f8979ba69f (diff)
downloadqueue-3.18-2f2387e5223e1aa80876261d423f8ce7242ebe89.tar.gz
more patches
-rw-r--r--ipv6-fix-the-link-time-qualifier-of-ping_v6_proc_exit_net.patch31
-rw-r--r--isdn-capi-check-message-length-in-capi_write.patch86
-rw-r--r--net-fix-null-de-reference-of-device-refcount.patch54
-rw-r--r--sch_hhf-ensure-quantum-and-hhf_non_hh_weight-are-non-zero.patch40
-rw-r--r--sctp-fix-the-link-time-qualifier-of-sctp_ctrlsock_exit.patch32
-rw-r--r--sctp-use-transport-pf_retrans-in-sctp_do_8_2_transport_strike.patch34
-rw-r--r--series8
-rw-r--r--tcp-fix-tcp_ecn_withdraw_cwr-to-clear-tcp_ecn_queue_cwr.patch59
-rw-r--r--tun-fix-use-after-free-when-register-netdev-failed.patch193
9 files changed, 537 insertions, 0 deletions
diff --git a/ipv6-fix-the-link-time-qualifier-of-ping_v6_proc_exit_net.patch b/ipv6-fix-the-link-time-qualifier-of-ping_v6_proc_exit_net.patch
new file mode 100644
index 0000000..1198a03
--- /dev/null
+++ b/ipv6-fix-the-link-time-qualifier-of-ping_v6_proc_exit_net.patch
@@ -0,0 +1,31 @@
+From foo@baz Mon 16 Sep 2019 01:29:13 PM CEST
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Date: Tue, 10 Sep 2019 13:29:59 +0200
+Subject: ipv6: Fix the link time qualifier of 'ping_v6_proc_exit_net()'
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit d23dbc479a8e813db4161a695d67da0e36557846 ]
+
+The '.exit' functions from 'pernet_operations' structure should be marked
+as __net_exit, not __net_init.
+
+Fixes: d862e5461423 ("net: ipv6: Implement /proc/net/icmp6.")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ping.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv6/ping.c
++++ b/net/ipv6/ping.c
+@@ -227,7 +227,7 @@ static int __net_init ping_v6_proc_init_
+ return ping_proc_register(net, &ping_v6_seq_afinfo);
+ }
+
+-static void __net_init ping_v6_proc_exit_net(struct net *net)
++static void __net_exit ping_v6_proc_exit_net(struct net *net)
+ {
+ return ping_proc_unregister(net, &ping_v6_seq_afinfo);
+ }
diff --git a/isdn-capi-check-message-length-in-capi_write.patch b/isdn-capi-check-message-length-in-capi_write.patch
new file mode 100644
index 0000000..d3be6f6
--- /dev/null
+++ b/isdn-capi-check-message-length-in-capi_write.patch
@@ -0,0 +1,86 @@
+From foo@baz Mon 16 Sep 2019 01:29:13 PM CEST
+From: Eric Biggers <ebiggers@google.com>
+Date: Thu, 5 Sep 2019 19:36:37 -0700
+Subject: isdn/capi: check message length in capi_write()
+
+From: Eric Biggers <ebiggers@google.com>
+
+[ Upstream commit fe163e534e5eecdfd7b5920b0dfd24c458ee85d6 ]
+
+syzbot reported:
+
+ BUG: KMSAN: uninit-value in capi_write+0x791/0xa90 drivers/isdn/capi/capi.c:700
+ CPU: 0 PID: 10025 Comm: syz-executor379 Not tainted 4.20.0-rc7+ #2
+ Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+ Call Trace:
+ __dump_stack lib/dump_stack.c:77 [inline]
+ dump_stack+0x173/0x1d0 lib/dump_stack.c:113
+ kmsan_report+0x12e/0x2a0 mm/kmsan/kmsan.c:613
+ __msan_warning+0x82/0xf0 mm/kmsan/kmsan_instr.c:313
+ capi_write+0x791/0xa90 drivers/isdn/capi/capi.c:700
+ do_loop_readv_writev fs/read_write.c:703 [inline]
+ do_iter_write+0x83e/0xd80 fs/read_write.c:961
+ vfs_writev fs/read_write.c:1004 [inline]
+ do_writev+0x397/0x840 fs/read_write.c:1039
+ __do_sys_writev fs/read_write.c:1112 [inline]
+ __se_sys_writev+0x9b/0xb0 fs/read_write.c:1109
+ __x64_sys_writev+0x4a/0x70 fs/read_write.c:1109
+ do_syscall_64+0xbc/0xf0 arch/x86/entry/common.c:291
+ entry_SYSCALL_64_after_hwframe+0x63/0xe7
+ [...]
+
+The problem is that capi_write() is reading past the end of the message.
+Fix it by checking the message's length in the needed places.
+
+Reported-and-tested-by: syzbot+0849c524d9c634f5ae66@syzkaller.appspotmail.com
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/isdn/capi/capi.c | 10 +++++++++-
+ include/uapi/linux/isdn/capicmd.h | 1 +
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+--- a/drivers/isdn/capi/capi.c
++++ b/drivers/isdn/capi/capi.c
+@@ -687,6 +687,9 @@ capi_write(struct file *file, const char
+ if (!cdev->ap.applid)
+ return -ENODEV;
+
++ if (count < CAPIMSG_BASELEN)
++ return -EINVAL;
++
+ skb = alloc_skb(count, GFP_USER);
+ if (!skb)
+ return -ENOMEM;
+@@ -697,7 +700,8 @@ capi_write(struct file *file, const char
+ }
+ mlen = CAPIMSG_LEN(skb->data);
+ if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
+- if ((size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {
++ if (count < CAPI_DATA_B3_REQ_LEN ||
++ (size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+@@ -710,6 +714,10 @@ capi_write(struct file *file, const char
+ CAPIMSG_SETAPPID(skb->data, cdev->ap.applid);
+
+ if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) {
++ if (count < CAPI_DISCONNECT_B3_RESP_LEN) {
++ kfree_skb(skb);
++ return -EINVAL;
++ }
+ mutex_lock(&cdev->lock);
+ capincci_free(cdev, CAPIMSG_NCCI(skb->data));
+ mutex_unlock(&cdev->lock);
+--- a/include/uapi/linux/isdn/capicmd.h
++++ b/include/uapi/linux/isdn/capicmd.h
+@@ -15,6 +15,7 @@
+ #define CAPI_MSG_BASELEN 8
+ #define CAPI_DATA_B3_REQ_LEN (CAPI_MSG_BASELEN+4+4+2+2+2)
+ #define CAPI_DATA_B3_RESP_LEN (CAPI_MSG_BASELEN+4+2)
++#define CAPI_DISCONNECT_B3_RESP_LEN (CAPI_MSG_BASELEN+4)
+
+ /*----- CAPI commands -----*/
+ #define CAPI_ALERT 0x01
diff --git a/net-fix-null-de-reference-of-device-refcount.patch b/net-fix-null-de-reference-of-device-refcount.patch
new file mode 100644
index 0000000..41f919a
--- /dev/null
+++ b/net-fix-null-de-reference-of-device-refcount.patch
@@ -0,0 +1,54 @@
+From foo@baz Mon 16 Sep 2019 01:29:13 PM CEST
+From: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
+Date: Tue, 10 Sep 2019 14:02:57 -0600
+Subject: net: Fix null de-reference of device refcount
+
+From: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
+
+[ Upstream commit 10cc514f451a0f239aa34f91bc9dc954a9397840 ]
+
+In event of failure during register_netdevice, free_netdev is
+invoked immediately. free_netdev assumes that all the netdevice
+refcounts have been dropped prior to it being called and as a
+result frees and clears out the refcount pointer.
+
+However, this is not necessarily true as some of the operations
+in the NETDEV_UNREGISTER notifier handlers queue RCU callbacks for
+invocation after a grace period. The IPv4 callback in_dev_rcu_put
+tries to access the refcount after free_netdev is called which
+leads to a null de-reference-
+
+44837.761523: <6> Unable to handle kernel paging request at
+ virtual address 0000004a88287000
+44837.761651: <2> pc : in_dev_finish_destroy+0x4c/0xc8
+44837.761654: <2> lr : in_dev_finish_destroy+0x2c/0xc8
+44837.762393: <2> Call trace:
+44837.762398: <2> in_dev_finish_destroy+0x4c/0xc8
+44837.762404: <2> in_dev_rcu_put+0x24/0x30
+44837.762412: <2> rcu_nocb_kthread+0x43c/0x468
+44837.762418: <2> kthread+0x118/0x128
+44837.762424: <2> ret_from_fork+0x10/0x1c
+
+Fix this by waiting for the completion of the call_rcu() in
+case of register_netdevice errors.
+
+Fixes: 93ee31f14f6f ("[NET]: Fix free_netdev on register_netdev failure.")
+Cc: Sean Tranchetti <stranche@codeaurora.org>
+Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/dev.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -6314,6 +6314,8 @@ int register_netdevice(struct net_device
+ ret = notifier_to_errno(ret);
+ if (ret) {
+ rollback_registered(dev);
++ rcu_barrier();
++
+ dev->reg_state = NETREG_UNREGISTERED;
+ }
+ /*
diff --git a/sch_hhf-ensure-quantum-and-hhf_non_hh_weight-are-non-zero.patch b/sch_hhf-ensure-quantum-and-hhf_non_hh_weight-are-non-zero.patch
new file mode 100644
index 0000000..531e383
--- /dev/null
+++ b/sch_hhf-ensure-quantum-and-hhf_non_hh_weight-are-non-zero.patch
@@ -0,0 +1,40 @@
+From foo@baz Mon 16 Sep 2019 01:29:13 PM CEST
+From: Cong Wang <xiyou.wangcong@gmail.com>
+Date: Sun, 8 Sep 2019 13:40:51 -0700
+Subject: sch_hhf: ensure quantum and hhf_non_hh_weight are non-zero
+
+From: Cong Wang <xiyou.wangcong@gmail.com>
+
+[ Upstream commit d4d6ec6dac07f263f06d847d6f732d6855522845 ]
+
+In case of TCA_HHF_NON_HH_WEIGHT or TCA_HHF_QUANTUM is zero,
+it would make no progress inside the loop in hhf_dequeue() thus
+kernel would get stuck.
+
+Fix this by checking this corner case in hhf_change().
+
+Fixes: 10239edf86f1 ("net-qdisc-hhf: Heavy-Hitter Filter (HHF) qdisc")
+Reported-by: syzbot+bc6297c11f19ee807dc2@syzkaller.appspotmail.com
+Reported-by: syzbot+041483004a7f45f1f20a@syzkaller.appspotmail.com
+Reported-by: syzbot+55be5f513bed37fc4367@syzkaller.appspotmail.com
+Cc: Jamal Hadi Salim <jhs@mojatatu.com>
+Cc: Jiri Pirko <jiri@resnulli.us>
+Cc: Terry Lam <vtlam@google.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sched/sch_hhf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sched/sch_hhf.c
++++ b/net/sched/sch_hhf.c
+@@ -557,7 +557,7 @@ static int hhf_change(struct Qdisc *sch,
+ new_hhf_non_hh_weight = nla_get_u32(tb[TCA_HHF_NON_HH_WEIGHT]);
+
+ non_hh_quantum = (u64)new_quantum * new_hhf_non_hh_weight;
+- if (non_hh_quantum > INT_MAX)
++ if (non_hh_quantum == 0 || non_hh_quantum > INT_MAX)
+ return -EINVAL;
+
+ sch_tree_lock(sch);
diff --git a/sctp-fix-the-link-time-qualifier-of-sctp_ctrlsock_exit.patch b/sctp-fix-the-link-time-qualifier-of-sctp_ctrlsock_exit.patch
new file mode 100644
index 0000000..9e134a3
--- /dev/null
+++ b/sctp-fix-the-link-time-qualifier-of-sctp_ctrlsock_exit.patch
@@ -0,0 +1,32 @@
+From foo@baz Mon 16 Sep 2019 01:29:13 PM CEST
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Date: Wed, 11 Sep 2019 18:02:39 +0200
+Subject: sctp: Fix the link time qualifier of 'sctp_ctrlsock_exit()'
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit b456d72412ca8797234449c25815e82f4e1426c0 ]
+
+The '.exit' functions from 'pernet_operations' structure should be marked
+as __net_exit, not __net_init.
+
+Fixes: 8e2d61e0aed2 ("sctp: fix race on protocol/netns initialization")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/protocol.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -1311,7 +1311,7 @@ static int __net_init sctp_ctrlsock_init
+ return status;
+ }
+
+-static void __net_init sctp_ctrlsock_exit(struct net *net)
++static void __net_exit sctp_ctrlsock_exit(struct net *net)
+ {
+ /* Free the control endpoint. */
+ inet_ctl_sock_destroy(net->sctp.ctl_sock);
diff --git a/sctp-use-transport-pf_retrans-in-sctp_do_8_2_transport_strike.patch b/sctp-use-transport-pf_retrans-in-sctp_do_8_2_transport_strike.patch
new file mode 100644
index 0000000..4cab90e
--- /dev/null
+++ b/sctp-use-transport-pf_retrans-in-sctp_do_8_2_transport_strike.patch
@@ -0,0 +1,34 @@
+From foo@baz Mon 16 Sep 2019 01:29:13 PM CEST
+From: Xin Long <lucien.xin@gmail.com>
+Date: Mon, 2 Sep 2019 23:24:21 +0800
+Subject: sctp: use transport pf_retrans in sctp_do_8_2_transport_strike
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit 10eb56c582c557c629271f1ee31e15e7a9b2558b ]
+
+Transport should use its own pf_retrans to do the error_count
+check, instead of asoc's. Otherwise, it's meaningless to make
+pf_retrans per transport.
+
+Fixes: 5aa93bcf66f4 ("sctp: Implement quick failover draft from tsvwg")
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/sm_sideeffect.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sctp/sm_sideeffect.c
++++ b/net/sctp/sm_sideeffect.c
+@@ -501,7 +501,7 @@ static void sctp_do_8_2_transport_strike
+ */
+ if ((transport->state == SCTP_ACTIVE) &&
+ (transport->error_count < transport->pathmaxrxt) &&
+- (transport->error_count > asoc->pf_retrans)) {
++ (transport->error_count > transport->pf_retrans)) {
+
+ sctp_assoc_control_transport(asoc, transport,
+ SCTP_TRANSPORT_PF,
diff --git a/series b/series
index e69de29..e04ee79 100644
--- a/series
+++ b/series
@@ -0,0 +1,8 @@
+ipv6-fix-the-link-time-qualifier-of-ping_v6_proc_exit_net.patch
+isdn-capi-check-message-length-in-capi_write.patch
+net-fix-null-de-reference-of-device-refcount.patch
+sch_hhf-ensure-quantum-and-hhf_non_hh_weight-are-non-zero.patch
+sctp-fix-the-link-time-qualifier-of-sctp_ctrlsock_exit.patch
+sctp-use-transport-pf_retrans-in-sctp_do_8_2_transport_strike.patch
+tcp-fix-tcp_ecn_withdraw_cwr-to-clear-tcp_ecn_queue_cwr.patch
+tun-fix-use-after-free-when-register-netdev-failed.patch
diff --git a/tcp-fix-tcp_ecn_withdraw_cwr-to-clear-tcp_ecn_queue_cwr.patch b/tcp-fix-tcp_ecn_withdraw_cwr-to-clear-tcp_ecn_queue_cwr.patch
new file mode 100644
index 0000000..41519f2
--- /dev/null
+++ b/tcp-fix-tcp_ecn_withdraw_cwr-to-clear-tcp_ecn_queue_cwr.patch
@@ -0,0 +1,59 @@
+From foo@baz Mon 16 Sep 2019 01:29:13 PM CEST
+From: Neal Cardwell <ncardwell@google.com>
+Date: Mon, 9 Sep 2019 16:56:02 -0400
+Subject: tcp: fix tcp_ecn_withdraw_cwr() to clear TCP_ECN_QUEUE_CWR
+
+From: Neal Cardwell <ncardwell@google.com>
+
+[ Upstream commit af38d07ed391b21f7405fa1f936ca9686787d6d2 ]
+
+Fix tcp_ecn_withdraw_cwr() to clear the correct bit:
+TCP_ECN_QUEUE_CWR.
+
+Rationale: basically, TCP_ECN_DEMAND_CWR is a bit that is purely about
+the behavior of data receivers, and deciding whether to reflect
+incoming IP ECN CE marks as outgoing TCP th->ece marks. The
+TCP_ECN_QUEUE_CWR bit is purely about the behavior of data senders,
+and deciding whether to send CWR. The tcp_ecn_withdraw_cwr() function
+is only called from tcp_undo_cwnd_reduction() by data senders during
+an undo, so it should zero the sender-side state,
+TCP_ECN_QUEUE_CWR. It does not make sense to stop the reflection of
+incoming CE bits on incoming data packets just because outgoing
+packets were spuriously retransmitted.
+
+The bug has been reproduced with packetdrill to manifest in a scenario
+with RFC3168 ECN, with an incoming data packet with CE bit set and
+carrying a TCP timestamp value that causes cwnd undo. Before this fix,
+the IP CE bit was ignored and not reflected in the TCP ECE header bit,
+and sender sent a TCP CWR ('W') bit on the next outgoing data packet,
+even though the cwnd reduction had been undone. After this fix, the
+sender properly reflects the CE bit and does not set the W bit.
+
+Note: the bug actually predates 2005 git history; this Fixes footer is
+chosen to be the oldest SHA1 I have tested (from Sep 2007) for which
+the patch applies cleanly (since before this commit the code was in a
+.h file).
+
+Fixes: bdf1ee5d3bd3 ("[TCP]: Move code from tcp_ecn.h to tcp*.c and tcp.h & remove it")
+Signed-off-by: Neal Cardwell <ncardwell@google.com>
+Acked-by: Yuchung Cheng <ycheng@google.com>
+Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
+Cc: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_input.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -219,7 +219,7 @@ static void tcp_ecn_accept_cwr(struct tc
+
+ static void tcp_ecn_withdraw_cwr(struct tcp_sock *tp)
+ {
+- tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR;
++ tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR;
+ }
+
+ static void __tcp_ecn_check_ce(struct sock *sk, const struct sk_buff *skb)
diff --git a/tun-fix-use-after-free-when-register-netdev-failed.patch b/tun-fix-use-after-free-when-register-netdev-failed.patch
new file mode 100644
index 0000000..3b84704
--- /dev/null
+++ b/tun-fix-use-after-free-when-register-netdev-failed.patch
@@ -0,0 +1,193 @@
+From foo@baz Mon 16 Sep 2019 01:07:00 PM CEST
+From: Yang Yingliang <yangyingliang@huawei.com>
+Date: Tue, 10 Sep 2019 18:56:57 +0800
+Subject: tun: fix use-after-free when register netdev failed
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit 77f22f92dff8e7b45c7786a430626d38071d4670 ]
+
+I got a UAF repport in tun driver when doing fuzzy test:
+
+[ 466.269490] ==================================================================
+[ 466.271792] BUG: KASAN: use-after-free in tun_chr_read_iter+0x2ca/0x2d0
+[ 466.271806] Read of size 8 at addr ffff888372139250 by task tun-test/2699
+[ 466.271810]
+[ 466.271824] CPU: 1 PID: 2699 Comm: tun-test Not tainted 5.3.0-rc1-00001-g5a9433db2614-dirty #427
+[ 466.271833] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
+[ 466.271838] Call Trace:
+[ 466.271858] dump_stack+0xca/0x13e
+[ 466.271871] ? tun_chr_read_iter+0x2ca/0x2d0
+[ 466.271890] print_address_description+0x79/0x440
+[ 466.271906] ? vprintk_func+0x5e/0xf0
+[ 466.271920] ? tun_chr_read_iter+0x2ca/0x2d0
+[ 466.271935] __kasan_report+0x15c/0x1df
+[ 466.271958] ? tun_chr_read_iter+0x2ca/0x2d0
+[ 466.271976] kasan_report+0xe/0x20
+[ 466.271987] tun_chr_read_iter+0x2ca/0x2d0
+[ 466.272013] do_iter_readv_writev+0x4b7/0x740
+[ 466.272032] ? default_llseek+0x2d0/0x2d0
+[ 466.272072] do_iter_read+0x1c5/0x5e0
+[ 466.272110] vfs_readv+0x108/0x180
+[ 466.299007] ? compat_rw_copy_check_uvector+0x440/0x440
+[ 466.299020] ? fsnotify+0x888/0xd50
+[ 466.299040] ? __fsnotify_parent+0xd0/0x350
+[ 466.299064] ? fsnotify_first_mark+0x1e0/0x1e0
+[ 466.304548] ? vfs_write+0x264/0x510
+[ 466.304569] ? ksys_write+0x101/0x210
+[ 466.304591] ? do_preadv+0x116/0x1a0
+[ 466.304609] do_preadv+0x116/0x1a0
+[ 466.309829] do_syscall_64+0xc8/0x600
+[ 466.309849] entry_SYSCALL_64_after_hwframe+0x49/0xbe
+[ 466.309861] RIP: 0033:0x4560f9
+[ 466.309875] Code: 00 00 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
+[ 466.309889] RSP: 002b:00007ffffa5166e8 EFLAGS: 00000206 ORIG_RAX: 0000000000000127
+[ 466.322992] RAX: ffffffffffffffda RBX: 0000000000400460 RCX: 00000000004560f9
+[ 466.322999] RDX: 0000000000000003 RSI: 00000000200008c0 RDI: 0000000000000003
+[ 466.323007] RBP: 00007ffffa516700 R08: 0000000000000004 R09: 0000000000000000
+[ 466.323014] R10: 0000000000000000 R11: 0000000000000206 R12: 000000000040cb10
+[ 466.323021] R13: 0000000000000000 R14: 00000000006d7018 R15: 0000000000000000
+[ 466.323057]
+[ 466.323064] Allocated by task 2605:
+[ 466.335165] save_stack+0x19/0x80
+[ 466.336240] __kasan_kmalloc.constprop.8+0xa0/0xd0
+[ 466.337755] kmem_cache_alloc+0xe8/0x320
+[ 466.339050] getname_flags+0xca/0x560
+[ 466.340229] user_path_at_empty+0x2c/0x50
+[ 466.341508] vfs_statx+0xe6/0x190
+[ 466.342619] __do_sys_newstat+0x81/0x100
+[ 466.343908] do_syscall_64+0xc8/0x600
+[ 466.345303] entry_SYSCALL_64_after_hwframe+0x49/0xbe
+[ 466.347034]
+[ 466.347517] Freed by task 2605:
+[ 466.348471] save_stack+0x19/0x80
+[ 466.349476] __kasan_slab_free+0x12e/0x180
+[ 466.350726] kmem_cache_free+0xc8/0x430
+[ 466.351874] putname+0xe2/0x120
+[ 466.352921] filename_lookup+0x257/0x3e0
+[ 466.354319] vfs_statx+0xe6/0x190
+[ 466.355498] __do_sys_newstat+0x81/0x100
+[ 466.356889] do_syscall_64+0xc8/0x600
+[ 466.358037] entry_SYSCALL_64_after_hwframe+0x49/0xbe
+[ 466.359567]
+[ 466.360050] The buggy address belongs to the object at ffff888372139100
+[ 466.360050] which belongs to the cache names_cache of size 4096
+[ 466.363735] The buggy address is located 336 bytes inside of
+[ 466.363735] 4096-byte region [ffff888372139100, ffff88837213a100)
+[ 466.367179] The buggy address belongs to the page:
+[ 466.368604] page:ffffea000dc84e00 refcount:1 mapcount:0 mapping:ffff8883df1b4f00 index:0x0 compound_mapcount: 0
+[ 466.371582] flags: 0x2fffff80010200(slab|head)
+[ 466.372910] raw: 002fffff80010200 dead000000000100 dead000000000122 ffff8883df1b4f00
+[ 466.375209] raw: 0000000000000000 0000000000070007 00000001ffffffff 0000000000000000
+[ 466.377778] page dumped because: kasan: bad access detected
+[ 466.379730]
+[ 466.380288] Memory state around the buggy address:
+[ 466.381844] ffff888372139100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[ 466.384009] ffff888372139180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[ 466.386131] >ffff888372139200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[ 466.388257] ^
+[ 466.390234] ffff888372139280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[ 466.392512] ffff888372139300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+[ 466.394667] ==================================================================
+
+tun_chr_read_iter() accessed the memory which freed by free_netdev()
+called by tun_set_iff():
+
+ CPUA CPUB
+ tun_set_iff()
+ alloc_netdev_mqs()
+ tun_attach()
+ tun_chr_read_iter()
+ tun_get()
+ tun_do_read()
+ tun_ring_recv()
+ register_netdevice() <-- inject error
+ goto err_detach
+ tun_detach_all() <-- set RCV_SHUTDOWN
+ free_netdev() <-- called from
+ err_free_dev path
+ netdev_freemem() <-- free the memory
+ without check refcount
+ (In this path, the refcount cannot prevent
+ freeing the memory of dev, and the memory
+ will be used by dev_put() called by
+ tun_chr_read_iter() on CPUB.)
+ (Break from tun_ring_recv(),
+ because RCV_SHUTDOWN is set)
+ tun_put()
+ dev_put() <-- use the memory
+ freed by netdev_freemem()
+
+Put the publishing of tfile->tun after register_netdevice(),
+so tun_get() won't get the tun pointer that freed by
+err_detach path if register_netdevice() failed.
+
+Fixes: eb0fb363f920 ("tuntap: attach queue 0 before registering netdevice")
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Suggested-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/tun.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -529,7 +529,8 @@ static void tun_detach_all(struct net_de
+ module_put(THIS_MODULE);
+ }
+
+-static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filter)
++static int tun_attach(struct tun_struct *tun, struct file *file,
++ bool skip_filter, bool publish_tun)
+ {
+ struct tun_file *tfile = file->private_data;
+ int err;
+@@ -561,7 +562,8 @@ static int tun_attach(struct tun_struct
+ }
+ tfile->queue_index = tun->numqueues;
+ tfile->socket.sk->sk_shutdown &= ~RCV_SHUTDOWN;
+- rcu_assign_pointer(tfile->tun, tun);
++ if (publish_tun)
++ rcu_assign_pointer(tfile->tun, tun);
+ rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
+ tun->numqueues++;
+
+@@ -1613,7 +1615,7 @@ static int tun_set_iff(struct net *net,
+ if (err < 0)
+ return err;
+
+- err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER);
++ err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER, true);
+ if (err < 0)
+ return err;
+
+@@ -1693,13 +1695,17 @@ static int tun_set_iff(struct net *net,
+ NETIF_F_HW_VLAN_STAG_TX);
+
+ INIT_LIST_HEAD(&tun->disabled);
+- err = tun_attach(tun, file, false);
++ err = tun_attach(tun, file, false, false);
+ if (err < 0)
+ goto err_free_flow;
+
+ err = register_netdevice(tun->dev);
+ if (err < 0)
+ goto err_detach;
++ /* free_netdev() won't check refcnt, to aovid race
++ * with dev_put() we need publish tun after registration.
++ */
++ rcu_assign_pointer(tfile->tun, tun);
+
+ if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
+ device_create_file(&tun->dev->dev, &dev_attr_owner) ||
+@@ -1857,7 +1863,7 @@ static int tun_set_queue(struct file *fi
+ ret = security_tun_dev_attach_queue(tun->security);
+ if (ret < 0)
+ goto unlock;
+- ret = tun_attach(tun, file, false);
++ ret = tun_attach(tun, file, false, true);
+ } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
+ tun = rtnl_dereference(tfile->tun);
+ if (!tun || !(tun->flags & TUN_TAP_MQ) || tfile->detached)