diff options
author | Cong Wang <xiyou.wangcong@gmail.com> | 2017-11-01 10:23:50 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-11-03 10:30:38 +0900 |
commit | ceffcc5e254b450e6159f173e4538215cebf1b59 (patch) | |
tree | e774e0c77b5f8a2979794ed08cc93b6365852114 /include/net | |
parent | a159d3c4b8291998c018f0dbddd4678315264a1e (diff) | |
download | linux-rpi-ceffcc5e254b450e6159f173e4538215cebf1b59.tar.gz linux-rpi-ceffcc5e254b450e6159f173e4538215cebf1b59.tar.bz2 linux-rpi-ceffcc5e254b450e6159f173e4538215cebf1b59.zip |
net_sched: hold netns refcnt for each action
TC actions have been destroyed asynchronously for a long time,
previously in a RCU callback and now in a workqueue. If we
don't hold a refcnt for its netns, we could use the per netns
data structure, struct tcf_idrinfo, after it has been freed by
netns workqueue.
Hold refcnt to ensure netns destroy happens after all actions
are gone.
Fixes: ddf97ccdd7cb ("net_sched: add network namespace support for tc actions")
Reported-by: Lucas Bates <lucasb@mojatatu.com>
Tested-by: Lucas Bates <lucasb@mojatatu.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r-- | include/net/act_api.h | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/include/net/act_api.h b/include/net/act_api.h index 5072446d5f06..c68551255032 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; @@ -104,7 +105,7 @@ struct tc_action_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 +113,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; |