From: Cong Wang <xiyou.wangcong@gmail.com>
To: Lucas Bates <lucasb@mojatatu.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>,
Linux Kernel Network Developers <netdev@vger.kernel.org>,
Chris Mi <chrism@mellanox.com>,
Daniel Borkmann <daniel@iogearbox.net>,
Jiri Pirko <jiri@resnulli.us>,
John Fastabend <john.fastabend@gmail.com>,
"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Subject: Re: [Patch net 00/16] net_sched: fix races with RCU callbacks
Date: Tue, 31 Oct 2017 16:02:17 -0700 [thread overview]
Message-ID: <CAM_iQpV+4_ae++398_Jrr4W=u_Ep=g9SXfGs5O-=_2ZkyosYgQ@mail.gmail.com> (raw)
In-Reply-To: <CAM_iQpXCHbPG0JfWLET+d7AEB5W=Rhxu6xB_kLgBjzwGq43jXg@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 495 bytes --]
On Tue, Oct 31, 2017 at 3:09 PM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
>
> This almost rules out the guilty of this patchset.
>
> I will provide a patch for you to test, since I can't reproduce it here.
>
Lucas, please test the attached patch, it applies to latest -net.
Note, it is a combination of 3 patches which together close the
use-after-free you reported here, I hope.
Please let me know if this works. My basic tests run well without
any stack traces or memory leaks.
Thanks!
[-- Attachment #2: tc-action-fixes.diff --]
[-- Type: text/plain, Size: 9945 bytes --]
diff --git a/include/net/act_api.h b/include/net/act_api.h
index b944e0eb93be..c6c8129c3647 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -13,6 +13,7 @@
struct tcf_idrinfo {
spinlock_t lock;
struct idr action_idr;
+ struct net *net;
};
struct tc_action_ops;
@@ -100,11 +101,12 @@ struct tc_action_ops {
struct tc_action_net {
struct tcf_idrinfo *idrinfo;
const struct tc_action_ops *ops;
+ struct net *net;
};
static inline
int tc_action_net_init(struct tc_action_net *tn,
- const struct tc_action_ops *ops)
+ const struct tc_action_ops *ops, struct net *net)
{
int err = 0;
@@ -112,6 +114,7 @@ int tc_action_net_init(struct tc_action_net *tn,
if (!tn->idrinfo)
return -ENOMEM;
tn->ops = ops;
+ tn->idrinfo->net = net;
spin_lock_init(&tn->idrinfo->lock);
idr_init(&tn->idrinfo->action_idr);
return err;
@@ -122,7 +125,9 @@ void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
static inline void tc_action_net_exit(struct tc_action_net *tn)
{
+ rtnl_lock();
tcf_idrinfo_destroy(tn->ops, tn->idrinfo);
+ rtnl_unlock();
kfree(tn->idrinfo);
}
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index da6fa82c98a8..241bf3f925de 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -78,6 +78,7 @@ static void tcf_idr_remove(struct tcf_idrinfo *idrinfo, struct tc_action *p)
spin_lock_bh(&idrinfo->lock);
idr_remove_ext(&idrinfo->action_idr, p->tcfa_index);
spin_unlock_bh(&idrinfo->lock);
+ put_net(idrinfo->net);
gen_kill_estimator(&p->tcfa_rate_est);
free_tcf(p);
}
@@ -86,6 +87,8 @@ int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
{
int ret = 0;
+ ASSERT_RTNL();
+
if (p) {
if (bind)
p->tcfa_bindcnt--;
@@ -93,7 +96,7 @@ int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
return -EPERM;
p->tcfa_refcnt--;
- if (p->tcfa_bindcnt <= 0 && p->tcfa_refcnt <= 0) {
+ if (p->tcfa_bindcnt == 0 && p->tcfa_refcnt == 0) {
if (p->ops->cleanup)
p->ops->cleanup(p, bind);
tcf_idr_remove(p->idrinfo, p);
@@ -334,6 +337,7 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
p->idrinfo = idrinfo;
p->ops = ops;
INIT_LIST_HEAD(&p->list);
+ get_net(idrinfo->net);
*a = p;
return 0;
}
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index c0c707eb2c96..9bce8cc84cbb 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -398,7 +398,7 @@ static __net_init int bpf_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, bpf_net_id);
- return tc_action_net_init(tn, &act_bpf_ops);
+ return tc_action_net_init(tn, &act_bpf_ops, net);
}
static void __net_exit bpf_exit_net(struct net *net)
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 10b7a8855a6c..34e52d01a5dd 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -206,7 +206,7 @@ static __net_init int connmark_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, connmark_net_id);
- return tc_action_net_init(tn, &act_connmark_ops);
+ return tc_action_net_init(tn, &act_connmark_ops, net);
}
static void __net_exit connmark_exit_net(struct net *net)
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 1c40caadcff9..35171df2ebef 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -626,7 +626,7 @@ static __net_init int csum_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, csum_net_id);
- return tc_action_net_init(tn, &act_csum_ops);
+ return tc_action_net_init(tn, &act_csum_ops, net);
}
static void __net_exit csum_exit_net(struct net *net)
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index e29a48ef7fc3..ef7f7f39d26d 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -232,7 +232,7 @@ static __net_init int gact_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, gact_net_id);
- return tc_action_net_init(tn, &act_gact_ops);
+ return tc_action_net_init(tn, &act_gact_ops, net);
}
static void __net_exit gact_exit_net(struct net *net)
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 8ccd35825b6b..f65e4b5058e0 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -818,7 +818,7 @@ static __net_init int ife_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, ife_net_id);
- return tc_action_net_init(tn, &act_ife_ops);
+ return tc_action_net_init(tn, &act_ife_ops, net);
}
static void __net_exit ife_exit_net(struct net *net)
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index d9e399a7e3d5..dbdf3b2470d5 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -334,7 +334,7 @@ static __net_init int ipt_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, ipt_net_id);
- return tc_action_net_init(tn, &act_ipt_ops);
+ return tc_action_net_init(tn, &act_ipt_ops, net);
}
static void __net_exit ipt_exit_net(struct net *net)
@@ -384,7 +384,7 @@ static __net_init int xt_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, xt_net_id);
- return tc_action_net_init(tn, &act_xt_ops);
+ return tc_action_net_init(tn, &act_xt_ops, net);
}
static void __net_exit xt_exit_net(struct net *net)
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 416627c66f08..84759cfd5a33 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -343,7 +343,7 @@ static __net_init int mirred_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, mirred_net_id);
- return tc_action_net_init(tn, &act_mirred_ops);
+ return tc_action_net_init(tn, &act_mirred_ops, net);
}
static void __net_exit mirred_exit_net(struct net *net)
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index c365d01b99c8..7eeaaf9217b6 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -307,7 +307,7 @@ static __net_init int nat_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, nat_net_id);
- return tc_action_net_init(tn, &act_nat_ops);
+ return tc_action_net_init(tn, &act_nat_ops, net);
}
static void __net_exit nat_exit_net(struct net *net)
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 491fe5deb09e..b3d82c334a5f 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -450,7 +450,7 @@ static __net_init int pedit_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, pedit_net_id);
- return tc_action_net_init(tn, &act_pedit_ops);
+ return tc_action_net_init(tn, &act_pedit_ops, net);
}
static void __net_exit pedit_exit_net(struct net *net)
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 3bb2ebf9e9ae..9ec42b26e4b9 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -331,7 +331,7 @@ static __net_init int police_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, police_net_id);
- return tc_action_net_init(tn, &act_police_ops);
+ return tc_action_net_init(tn, &act_police_ops, net);
}
static void __net_exit police_exit_net(struct net *net)
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c
index a9f9a2ccc664..71b8405e9718 100644
--- a/net/sched/act_sample.c
+++ b/net/sched/act_sample.c
@@ -240,7 +240,7 @@ static __net_init int sample_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, sample_net_id);
- return tc_action_net_init(tn, &act_sample_ops);
+ return tc_action_net_init(tn, &act_sample_ops, net);
}
static void __net_exit sample_exit_net(struct net *net)
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index e7b57e5071a3..a8d0ea95f894 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -201,7 +201,7 @@ static __net_init int simp_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, simp_net_id);
- return tc_action_net_init(tn, &act_simp_ops);
+ return tc_action_net_init(tn, &act_simp_ops, net);
}
static void __net_exit simp_exit_net(struct net *net)
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 59949d61f20d..fbac62472e09 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -238,7 +238,7 @@ static __net_init int skbedit_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
- return tc_action_net_init(tn, &act_skbedit_ops);
+ return tc_action_net_init(tn, &act_skbedit_ops, net);
}
static void __net_exit skbedit_exit_net(struct net *net)
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index b642ad3d39dd..8e12d8897d2f 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -263,7 +263,7 @@ static __net_init int skbmod_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, skbmod_net_id);
- return tc_action_net_init(tn, &act_skbmod_ops);
+ return tc_action_net_init(tn, &act_skbmod_ops, net);
}
static void __net_exit skbmod_exit_net(struct net *net)
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index 30c96274c638..c33faa373cf2 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -322,7 +322,7 @@ static __net_init int tunnel_key_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
- return tc_action_net_init(tn, &act_tunnel_key_ops);
+ return tc_action_net_init(tn, &act_tunnel_key_ops, net);
}
static void __net_exit tunnel_key_exit_net(struct net *net)
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 16eb067a8d8f..115fc33cc6d8 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -269,7 +269,7 @@ static __net_init int vlan_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, vlan_net_id);
- return tc_action_net_init(tn, &act_vlan_ops);
+ return tc_action_net_init(tn, &act_vlan_ops, net);
}
static void __net_exit vlan_exit_net(struct net *net)
next prev parent reply other threads:[~2017-10-31 23:02 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-27 1:24 [Patch net 00/16] net_sched: fix races with RCU callbacks Cong Wang
2017-10-27 1:24 ` [Patch net 01/16] net_sched: introduce a workqueue for RCU callbacks of tc filter Cong Wang
2017-10-27 4:05 ` Eric Dumazet
2017-10-27 4:28 ` Cong Wang
2017-10-27 4:39 ` Eric Dumazet
2017-10-27 11:55 ` Paul E. McKenney
2017-10-27 15:43 ` Cong Wang
2017-10-27 15:37 ` Cong Wang
2017-10-27 15:52 ` Eric Dumazet
2017-10-27 1:24 ` [Patch net 02/16] net_sched: use tcf_queue_work() in basic filter Cong Wang
2017-10-27 1:24 ` [Patch net 03/16] net_sched: use tcf_queue_work() in bpf filter Cong Wang
2017-10-27 1:24 ` [Patch net 04/16] net_sched: use tcf_queue_work() in cgroup filter Cong Wang
2017-10-27 1:24 ` [Patch net 05/16] net_sched: use tcf_queue_work() in flow filter Cong Wang
2017-10-27 1:24 ` [Patch net 06/16] net_sched: use tcf_queue_work() in flower filter Cong Wang
2017-10-27 1:24 ` [Patch net 07/16] net_sched: use tcf_queue_work() in fw filter Cong Wang
2017-10-27 1:24 ` [Patch net 08/16] net_sched: use tcf_queue_work() in matchall filter Cong Wang
2017-10-27 1:24 ` [Patch net 09/16] net_sched: use tcf_queue_work() in u32 filter Cong Wang
2017-10-27 1:24 ` [Patch net 10/16] net_sched: use tcf_queue_work() in route filter Cong Wang
2017-10-27 1:24 ` [Patch net 11/16] net_sched: use tcf_queue_work() in rsvp filter Cong Wang
2017-10-27 1:24 ` [Patch net 12/16] net_sched: use tcf_queue_work() in tcindex filter Cong Wang
2017-10-27 1:24 ` [Patch net 13/16] net_sched: add rtnl assertion to tcf_exts_destroy() Cong Wang
2017-10-27 1:24 ` [Patch net 14/16] net_sched: fix call_rcu() race on act_sample module removal Cong Wang
2017-10-27 1:24 ` [Patch net 15/16] selftests: Introduce a new script to generate tc batch file Cong Wang
2017-10-27 1:24 ` [Patch net 16/16] selftests: Introduce a new test case to tc testsuite Cong Wang
2017-10-29 14:41 ` [Patch net 00/16] net_sched: fix races with RCU callbacks David Miller
2017-10-30 22:39 ` Lucas Bates
2017-10-30 23:12 ` Cong Wang
2017-10-31 1:46 ` Lucas Bates
[not found] ` <CAMDBHYJTMv4MDQENNKjOXaUBHyXicOnkM_j+i7__3d1CAgdVRg@mail.gmail.com>
2017-10-31 5:44 ` Cong Wang
2017-10-31 11:00 ` Jamal Hadi Salim
2017-10-31 18:55 ` Lucas Bates
2017-10-31 19:13 ` Lucas Bates
2017-10-31 22:09 ` Cong Wang
2017-10-31 23:02 ` Cong Wang [this message]
2017-11-01 16:55 ` Lucas Bates
2017-11-01 16:59 ` Cong Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAM_iQpV+4_ae++398_Jrr4W=u_Ep=g9SXfGs5O-=_2ZkyosYgQ@mail.gmail.com' \
--to=xiyou.wangcong@gmail.com \
--cc=chrism@mellanox.com \
--cc=daniel@iogearbox.net \
--cc=jhs@mojatatu.com \
--cc=jiri@resnulli.us \
--cc=john.fastabend@gmail.com \
--cc=lucasb@mojatatu.com \
--cc=netdev@vger.kernel.org \
--cc=paulmck@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).