Skip to content

Commit d5f984f

Browse files
congwangdavem330
authored andcommitted
cls_fw: use tcf_exts_get_net() before call_rcu()
Hold netns refcnt before call_rcu() and release it after the tcf_exts_destroy() is done. Note, on ->destroy() path we have to respect the return value of tcf_exts_get_net(), on other paths it should always return true, so we don't need to care. Cc: 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>
1 parent 0dadc11 commit d5f984f

1 file changed

Lines changed: 14 additions & 3 deletions

File tree

net/sched/cls_fw.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,19 @@ static int fw_init(struct tcf_proto *tp)
122122
return 0;
123123
}
124124

125+
static void __fw_delete_filter(struct fw_filter *f)
126+
{
127+
tcf_exts_destroy(&f->exts);
128+
tcf_exts_put_net(&f->exts);
129+
kfree(f);
130+
}
131+
125132
static void fw_delete_filter_work(struct work_struct *work)
126133
{
127134
struct fw_filter *f = container_of(work, struct fw_filter, work);
128135

129136
rtnl_lock();
130-
tcf_exts_destroy(&f->exts);
131-
kfree(f);
137+
__fw_delete_filter(f);
132138
rtnl_unlock();
133139
}
134140

@@ -154,7 +160,10 @@ static void fw_destroy(struct tcf_proto *tp)
154160
RCU_INIT_POINTER(head->ht[h],
155161
rtnl_dereference(f->next));
156162
tcf_unbind_filter(tp, &f->res);
157-
call_rcu(&f->rcu, fw_delete_filter);
163+
if (tcf_exts_get_net(&f->exts))
164+
call_rcu(&f->rcu, fw_delete_filter);
165+
else
166+
__fw_delete_filter(f);
158167
}
159168
}
160169
kfree_rcu(head, rcu);
@@ -179,6 +188,7 @@ static int fw_delete(struct tcf_proto *tp, void *arg, bool *last)
179188
if (pfp == f) {
180189
RCU_INIT_POINTER(*fp, rtnl_dereference(f->next));
181190
tcf_unbind_filter(tp, &f->res);
191+
tcf_exts_get_net(&f->exts);
182192
call_rcu(&f->rcu, fw_delete_filter);
183193
ret = 0;
184194
break;
@@ -299,6 +309,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
299309
RCU_INIT_POINTER(fnew->next, rtnl_dereference(pfp->next));
300310
rcu_assign_pointer(*fp, fnew);
301311
tcf_unbind_filter(tp, &f->res);
312+
tcf_exts_get_net(&f->exts);
302313
call_rcu(&f->rcu, fw_delete_filter);
303314

304315
*arg = fnew;

0 commit comments

Comments
 (0)