diff options
author | Cong Wang <cwang@twopensource.com> | 2014-04-25 16:54:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-04-27 23:42:39 -0400 |
commit | 2f7ef2f8790f5bf53db4fc6b2310943139285827 (patch) | |
tree | f2deb92bec03f3af01b9d7c1bf4dfb7b97760ecf /net/sched/cls_bpf.c | |
parent | 4940b8cd1bc6d452eaffa442d92a28534850ca78 (diff) |
sched, cls: check if we could overwrite actions when changing a filter
When actions are attached to a filter, they are a part of the filter
itself, so when changing a filter we should allow to overwrite the actions
inside as well.
In my specific case, when I tried to _append_ a new action to an existing
filter which already has an action, I got EEXIST since kernel refused
to overwrite the existing one in kernel.
This patch checks if we are changing the filter checking NLM_F_CREATE flag
(Sigh, filters don't use NLM_F_REPLACE...) and then passes the boolean down
to actions. This fixes the problem above.
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Cong Wang <cwang@twopensource.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/cls_bpf.c')
-rw-r--r-- | net/sched/cls_bpf.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 8e3cf49118e3..16186965af97 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
@@ -156,7 +156,7 @@ static void cls_bpf_put(struct tcf_proto *tp, unsigned long f) | |||
156 | static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, | 156 | static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, |
157 | struct cls_bpf_prog *prog, | 157 | struct cls_bpf_prog *prog, |
158 | unsigned long base, struct nlattr **tb, | 158 | unsigned long base, struct nlattr **tb, |
159 | struct nlattr *est) | 159 | struct nlattr *est, bool ovr) |
160 | { | 160 | { |
161 | struct sock_filter *bpf_ops, *bpf_old; | 161 | struct sock_filter *bpf_ops, *bpf_old; |
162 | struct tcf_exts exts; | 162 | struct tcf_exts exts; |
@@ -170,7 +170,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, | |||
170 | return -EINVAL; | 170 | return -EINVAL; |
171 | 171 | ||
172 | tcf_exts_init(&exts, TCA_BPF_ACT, TCA_BPF_POLICE); | 172 | tcf_exts_init(&exts, TCA_BPF_ACT, TCA_BPF_POLICE); |
173 | ret = tcf_exts_validate(net, tp, tb, est, &exts); | 173 | ret = tcf_exts_validate(net, tp, tb, est, &exts, ovr); |
174 | if (ret < 0) | 174 | if (ret < 0) |
175 | return ret; | 175 | return ret; |
176 | 176 | ||
@@ -242,7 +242,7 @@ static u32 cls_bpf_grab_new_handle(struct tcf_proto *tp, | |||
242 | static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, | 242 | static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, |
243 | struct tcf_proto *tp, unsigned long base, | 243 | struct tcf_proto *tp, unsigned long base, |
244 | u32 handle, struct nlattr **tca, | 244 | u32 handle, struct nlattr **tca, |
245 | unsigned long *arg) | 245 | unsigned long *arg, bool ovr) |
246 | { | 246 | { |
247 | struct cls_bpf_head *head = tp->root; | 247 | struct cls_bpf_head *head = tp->root; |
248 | struct cls_bpf_prog *prog = (struct cls_bpf_prog *) *arg; | 248 | struct cls_bpf_prog *prog = (struct cls_bpf_prog *) *arg; |
@@ -260,7 +260,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, | |||
260 | if (handle && prog->handle != handle) | 260 | if (handle && prog->handle != handle) |
261 | return -EINVAL; | 261 | return -EINVAL; |
262 | return cls_bpf_modify_existing(net, tp, prog, base, tb, | 262 | return cls_bpf_modify_existing(net, tp, prog, base, tb, |
263 | tca[TCA_RATE]); | 263 | tca[TCA_RATE], ovr); |
264 | } | 264 | } |
265 | 265 | ||
266 | prog = kzalloc(sizeof(*prog), GFP_KERNEL); | 266 | prog = kzalloc(sizeof(*prog), GFP_KERNEL); |
@@ -277,7 +277,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, | |||
277 | goto errout; | 277 | goto errout; |
278 | } | 278 | } |
279 | 279 | ||
280 | ret = cls_bpf_modify_existing(net, tp, prog, base, tb, tca[TCA_RATE]); | 280 | ret = cls_bpf_modify_existing(net, tp, prog, base, tb, tca[TCA_RATE], ovr); |
281 | if (ret < 0) | 281 | if (ret < 0) |
282 | goto errout; | 282 | goto errout; |
283 | 283 | ||