aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCong Wang <cwang@twopensource.com>2014-04-25 16:54:06 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-27 23:42:39 -0400
commit2f7ef2f8790f5bf53db4fc6b2310943139285827 (patch)
treef2deb92bec03f3af01b9d7c1bf4dfb7b97760ecf
parent4940b8cd1bc6d452eaffa442d92a28534850ca78 (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>
-rw-r--r--include/net/pkt_cls.h2
-rw-r--r--include/net/sch_generic.h2
-rw-r--r--net/sched/cls_api.c9
-rw-r--r--net/sched/cls_basic.c10
-rw-r--r--net/sched/cls_bpf.c10
-rw-r--r--net/sched/cls_cgroup.c4
-rw-r--r--net/sched/cls_flow.c4
-rw-r--r--net/sched/cls_fw.c10
-rw-r--r--net/sched/cls_route.c11
-rw-r--r--net/sched/cls_rsvp.h4
-rw-r--r--net/sched/cls_tcindex.c8
-rw-r--r--net/sched/cls_u32.c10
12 files changed, 43 insertions, 41 deletions
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index a2441fb1428f..6da46dcf1049 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -136,7 +136,7 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
136 136
137int tcf_exts_validate(struct net *net, struct tcf_proto *tp, 137int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
138 struct nlattr **tb, struct nlattr *rate_tlv, 138 struct nlattr **tb, struct nlattr *rate_tlv,
139 struct tcf_exts *exts); 139 struct tcf_exts *exts, bool ovr);
140void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts); 140void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts);
141void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, 141void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
142 struct tcf_exts *src); 142 struct tcf_exts *src);
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index d062f81c692f..624f9857c83e 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -199,7 +199,7 @@ struct tcf_proto_ops {
199 int (*change)(struct net *net, struct sk_buff *, 199 int (*change)(struct net *net, struct sk_buff *,
200 struct tcf_proto*, unsigned long, 200 struct tcf_proto*, unsigned long,
201 u32 handle, struct nlattr **, 201 u32 handle, struct nlattr **,
202 unsigned long *); 202 unsigned long *, bool);
203 int (*delete)(struct tcf_proto*, unsigned long); 203 int (*delete)(struct tcf_proto*, unsigned long);
204 void (*walk)(struct tcf_proto*, struct tcf_walker *arg); 204 void (*walk)(struct tcf_proto*, struct tcf_walker *arg);
205 205
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 29a30a14c315..6786130a4f59 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -317,7 +317,8 @@ replay:
317 } 317 }
318 } 318 }
319 319
320 err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh); 320 err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
321 n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE);
321 if (err == 0) { 322 if (err == 0) {
322 if (tp_created) { 323 if (tp_created) {
323 spin_lock_bh(root_lock); 324 spin_lock_bh(root_lock);
@@ -504,7 +505,7 @@ void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
504EXPORT_SYMBOL(tcf_exts_destroy); 505EXPORT_SYMBOL(tcf_exts_destroy);
505 506
506int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, 507int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
507 struct nlattr *rate_tlv, struct tcf_exts *exts) 508 struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr)
508{ 509{
509#ifdef CONFIG_NET_CLS_ACT 510#ifdef CONFIG_NET_CLS_ACT
510 { 511 {
@@ -513,7 +514,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
513 INIT_LIST_HEAD(&exts->actions); 514 INIT_LIST_HEAD(&exts->actions);
514 if (exts->police && tb[exts->police]) { 515 if (exts->police && tb[exts->police]) {
515 act = tcf_action_init_1(net, tb[exts->police], rate_tlv, 516 act = tcf_action_init_1(net, tb[exts->police], rate_tlv,
516 "police", TCA_ACT_NOREPLACE, 517 "police", ovr,
517 TCA_ACT_BIND); 518 TCA_ACT_BIND);
518 if (IS_ERR(act)) 519 if (IS_ERR(act))
519 return PTR_ERR(act); 520 return PTR_ERR(act);
@@ -523,7 +524,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
523 } else if (exts->action && tb[exts->action]) { 524 } else if (exts->action && tb[exts->action]) {
524 int err; 525 int err;
525 err = tcf_action_init(net, tb[exts->action], rate_tlv, 526 err = tcf_action_init(net, tb[exts->action], rate_tlv,
526 NULL, TCA_ACT_NOREPLACE, 527 NULL, ovr,
527 TCA_ACT_BIND, &exts->actions); 528 TCA_ACT_BIND, &exts->actions);
528 if (err) 529 if (err)
529 return err; 530 return err;
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index e98ca99c202b..0ae1813e3e90 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -130,14 +130,14 @@ static const struct nla_policy basic_policy[TCA_BASIC_MAX + 1] = {
130static int basic_set_parms(struct net *net, struct tcf_proto *tp, 130static int basic_set_parms(struct net *net, struct tcf_proto *tp,
131 struct basic_filter *f, unsigned long base, 131 struct basic_filter *f, unsigned long base,
132 struct nlattr **tb, 132 struct nlattr **tb,
133 struct nlattr *est) 133 struct nlattr *est, bool ovr)
134{ 134{
135 int err; 135 int err;
136 struct tcf_exts e; 136 struct tcf_exts e;
137 struct tcf_ematch_tree t; 137 struct tcf_ematch_tree t;
138 138
139 tcf_exts_init(&e, TCA_BASIC_ACT, TCA_BASIC_POLICE); 139 tcf_exts_init(&e, TCA_BASIC_ACT, TCA_BASIC_POLICE);
140 err = tcf_exts_validate(net, tp, tb, est, &e); 140 err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
141 if (err < 0) 141 if (err < 0)
142 return err; 142 return err;
143 143
@@ -161,7 +161,7 @@ errout:
161 161
162static int basic_change(struct net *net, struct sk_buff *in_skb, 162static int basic_change(struct net *net, struct sk_buff *in_skb,
163 struct tcf_proto *tp, unsigned long base, u32 handle, 163 struct tcf_proto *tp, unsigned long base, u32 handle,
164 struct nlattr **tca, unsigned long *arg) 164 struct nlattr **tca, unsigned long *arg, bool ovr)
165{ 165{
166 int err; 166 int err;
167 struct basic_head *head = tp->root; 167 struct basic_head *head = tp->root;
@@ -179,7 +179,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
179 if (f != NULL) { 179 if (f != NULL) {
180 if (handle && f->handle != handle) 180 if (handle && f->handle != handle)
181 return -EINVAL; 181 return -EINVAL;
182 return basic_set_parms(net, tp, f, base, tb, tca[TCA_RATE]); 182 return basic_set_parms(net, tp, f, base, tb, tca[TCA_RATE], ovr);
183 } 183 }
184 184
185 err = -ENOBUFS; 185 err = -ENOBUFS;
@@ -206,7 +206,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
206 f->handle = head->hgenerator; 206 f->handle = head->hgenerator;
207 } 207 }
208 208
209 err = basic_set_parms(net, tp, f, base, tb, tca[TCA_RATE]); 209 err = basic_set_parms(net, tp, f, base, tb, tca[TCA_RATE], ovr);
210 if (err < 0) 210 if (err < 0)
211 goto errout; 211 goto errout;
212 212
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)
156static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, 156static 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,
242static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, 242static 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
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 8e2158ab551c..cacf01bd04f0 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -83,7 +83,7 @@ static const struct nla_policy cgroup_policy[TCA_CGROUP_MAX + 1] = {
83static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb, 83static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
84 struct tcf_proto *tp, unsigned long base, 84 struct tcf_proto *tp, unsigned long base,
85 u32 handle, struct nlattr **tca, 85 u32 handle, struct nlattr **tca,
86 unsigned long *arg) 86 unsigned long *arg, bool ovr)
87{ 87{
88 struct nlattr *tb[TCA_CGROUP_MAX + 1]; 88 struct nlattr *tb[TCA_CGROUP_MAX + 1];
89 struct cls_cgroup_head *head = tp->root; 89 struct cls_cgroup_head *head = tp->root;
@@ -119,7 +119,7 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
119 return err; 119 return err;
120 120
121 tcf_exts_init(&e, TCA_CGROUP_ACT, TCA_CGROUP_POLICE); 121 tcf_exts_init(&e, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
122 err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e); 122 err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
123 if (err < 0) 123 if (err < 0)
124 return err; 124 return err;
125 125
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 257029c54332..35be16f7c192 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -349,7 +349,7 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = {
349static int flow_change(struct net *net, struct sk_buff *in_skb, 349static int flow_change(struct net *net, struct sk_buff *in_skb,
350 struct tcf_proto *tp, unsigned long base, 350 struct tcf_proto *tp, unsigned long base,
351 u32 handle, struct nlattr **tca, 351 u32 handle, struct nlattr **tca,
352 unsigned long *arg) 352 unsigned long *arg, bool ovr)
353{ 353{
354 struct flow_head *head = tp->root; 354 struct flow_head *head = tp->root;
355 struct flow_filter *f; 355 struct flow_filter *f;
@@ -393,7 +393,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
393 } 393 }
394 394
395 tcf_exts_init(&e, TCA_FLOW_ACT, TCA_FLOW_POLICE); 395 tcf_exts_init(&e, TCA_FLOW_ACT, TCA_FLOW_POLICE);
396 err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e); 396 err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
397 if (err < 0) 397 if (err < 0)
398 return err; 398 return err;
399 399
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 63a3ce75c02e..861b03ccfed0 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -169,7 +169,7 @@ static const struct nla_policy fw_policy[TCA_FW_MAX + 1] = {
169 169
170static int 170static int
171fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f, 171fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
172 struct nlattr **tb, struct nlattr **tca, unsigned long base) 172 struct nlattr **tb, struct nlattr **tca, unsigned long base, bool ovr)
173{ 173{
174 struct fw_head *head = tp->root; 174 struct fw_head *head = tp->root;
175 struct tcf_exts e; 175 struct tcf_exts e;
@@ -177,7 +177,7 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
177 int err; 177 int err;
178 178
179 tcf_exts_init(&e, TCA_FW_ACT, TCA_FW_POLICE); 179 tcf_exts_init(&e, TCA_FW_ACT, TCA_FW_POLICE);
180 err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e); 180 err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
181 if (err < 0) 181 if (err < 0)
182 return err; 182 return err;
183 183
@@ -218,7 +218,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
218 struct tcf_proto *tp, unsigned long base, 218 struct tcf_proto *tp, unsigned long base,
219 u32 handle, 219 u32 handle,
220 struct nlattr **tca, 220 struct nlattr **tca,
221 unsigned long *arg) 221 unsigned long *arg, bool ovr)
222{ 222{
223 struct fw_head *head = tp->root; 223 struct fw_head *head = tp->root;
224 struct fw_filter *f = (struct fw_filter *) *arg; 224 struct fw_filter *f = (struct fw_filter *) *arg;
@@ -236,7 +236,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
236 if (f != NULL) { 236 if (f != NULL) {
237 if (f->id != handle && handle) 237 if (f->id != handle && handle)
238 return -EINVAL; 238 return -EINVAL;
239 return fw_change_attrs(net, tp, f, tb, tca, base); 239 return fw_change_attrs(net, tp, f, tb, tca, base, ovr);
240 } 240 }
241 241
242 if (!handle) 242 if (!handle)
@@ -264,7 +264,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
264 tcf_exts_init(&f->exts, TCA_FW_ACT, TCA_FW_POLICE); 264 tcf_exts_init(&f->exts, TCA_FW_ACT, TCA_FW_POLICE);
265 f->id = handle; 265 f->id = handle;
266 266
267 err = fw_change_attrs(net, tp, f, tb, tca, base); 267 err = fw_change_attrs(net, tp, f, tb, tca, base, ovr);
268 if (err < 0) 268 if (err < 0)
269 goto errout; 269 goto errout;
270 270
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 1ad3068f2ce1..dd9fc2523c76 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -333,7 +333,8 @@ static const struct nla_policy route4_policy[TCA_ROUTE4_MAX + 1] = {
333static int route4_set_parms(struct net *net, struct tcf_proto *tp, 333static int route4_set_parms(struct net *net, struct tcf_proto *tp,
334 unsigned long base, struct route4_filter *f, 334 unsigned long base, struct route4_filter *f,
335 u32 handle, struct route4_head *head, 335 u32 handle, struct route4_head *head,
336 struct nlattr **tb, struct nlattr *est, int new) 336 struct nlattr **tb, struct nlattr *est, int new,
337 bool ovr)
337{ 338{
338 int err; 339 int err;
339 u32 id = 0, to = 0, nhandle = 0x8000; 340 u32 id = 0, to = 0, nhandle = 0x8000;
@@ -343,7 +344,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
343 struct tcf_exts e; 344 struct tcf_exts e;
344 345
345 tcf_exts_init(&e, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE); 346 tcf_exts_init(&e, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
346 err = tcf_exts_validate(net, tp, tb, est, &e); 347 err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
347 if (err < 0) 348 if (err < 0)
348 return err; 349 return err;
349 350
@@ -428,7 +429,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
428 struct tcf_proto *tp, unsigned long base, 429 struct tcf_proto *tp, unsigned long base,
429 u32 handle, 430 u32 handle,
430 struct nlattr **tca, 431 struct nlattr **tca,
431 unsigned long *arg) 432 unsigned long *arg, bool ovr)
432{ 433{
433 struct route4_head *head = tp->root; 434 struct route4_head *head = tp->root;
434 struct route4_filter *f, *f1, **fp; 435 struct route4_filter *f, *f1, **fp;
@@ -455,7 +456,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
455 old_handle = f->handle; 456 old_handle = f->handle;
456 457
457 err = route4_set_parms(net, tp, base, f, handle, head, tb, 458 err = route4_set_parms(net, tp, base, f, handle, head, tb,
458 tca[TCA_RATE], 0); 459 tca[TCA_RATE], 0, ovr);
459 if (err < 0) 460 if (err < 0)
460 return err; 461 return err;
461 462
@@ -479,7 +480,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
479 480
480 tcf_exts_init(&f->exts, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE); 481 tcf_exts_init(&f->exts, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
481 err = route4_set_parms(net, tp, base, f, handle, head, tb, 482 err = route4_set_parms(net, tp, base, f, handle, head, tb,
482 tca[TCA_RATE], 1); 483 tca[TCA_RATE], 1, ovr);
483 if (err < 0) 484 if (err < 0)
484 goto errout; 485 goto errout;
485 486
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 19f8e5dfa8bd..1020e233a5d6 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -415,7 +415,7 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb,
415 struct tcf_proto *tp, unsigned long base, 415 struct tcf_proto *tp, unsigned long base,
416 u32 handle, 416 u32 handle,
417 struct nlattr **tca, 417 struct nlattr **tca,
418 unsigned long *arg) 418 unsigned long *arg, bool ovr)
419{ 419{
420 struct rsvp_head *data = tp->root; 420 struct rsvp_head *data = tp->root;
421 struct rsvp_filter *f, **fp; 421 struct rsvp_filter *f, **fp;
@@ -436,7 +436,7 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb,
436 return err; 436 return err;
437 437
438 tcf_exts_init(&e, TCA_RSVP_ACT, TCA_RSVP_POLICE); 438 tcf_exts_init(&e, TCA_RSVP_ACT, TCA_RSVP_POLICE);
439 err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e); 439 err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
440 if (err < 0) 440 if (err < 0)
441 return err; 441 return err;
442 442
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index eed8404443d8..d11d0a4fbe34 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -192,7 +192,7 @@ static int
192tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, 192tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
193 u32 handle, struct tcindex_data *p, 193 u32 handle, struct tcindex_data *p,
194 struct tcindex_filter_result *r, struct nlattr **tb, 194 struct tcindex_filter_result *r, struct nlattr **tb,
195 struct nlattr *est) 195 struct nlattr *est, bool ovr)
196{ 196{
197 int err, balloc = 0; 197 int err, balloc = 0;
198 struct tcindex_filter_result new_filter_result, *old_r = r; 198 struct tcindex_filter_result new_filter_result, *old_r = r;
@@ -202,7 +202,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
202 struct tcf_exts e; 202 struct tcf_exts e;
203 203
204 tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); 204 tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
205 err = tcf_exts_validate(net, tp, tb, est, &e); 205 err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
206 if (err < 0) 206 if (err < 0)
207 return err; 207 return err;
208 208
@@ -331,7 +331,7 @@ errout:
331static int 331static int
332tcindex_change(struct net *net, struct sk_buff *in_skb, 332tcindex_change(struct net *net, struct sk_buff *in_skb,
333 struct tcf_proto *tp, unsigned long base, u32 handle, 333 struct tcf_proto *tp, unsigned long base, u32 handle,
334 struct nlattr **tca, unsigned long *arg) 334 struct nlattr **tca, unsigned long *arg, bool ovr)
335{ 335{
336 struct nlattr *opt = tca[TCA_OPTIONS]; 336 struct nlattr *opt = tca[TCA_OPTIONS];
337 struct nlattr *tb[TCA_TCINDEX_MAX + 1]; 337 struct nlattr *tb[TCA_TCINDEX_MAX + 1];
@@ -351,7 +351,7 @@ tcindex_change(struct net *net, struct sk_buff *in_skb,
351 return err; 351 return err;
352 352
353 return tcindex_set_parms(net, tp, base, handle, p, r, tb, 353 return tcindex_set_parms(net, tp, base, handle, p, r, tb,
354 tca[TCA_RATE]); 354 tca[TCA_RATE], ovr);
355} 355}
356 356
357 357
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 84c28daff848..c39b583ace32 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -486,13 +486,13 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
486static int u32_set_parms(struct net *net, struct tcf_proto *tp, 486static int u32_set_parms(struct net *net, struct tcf_proto *tp,
487 unsigned long base, struct tc_u_hnode *ht, 487 unsigned long base, struct tc_u_hnode *ht,
488 struct tc_u_knode *n, struct nlattr **tb, 488 struct tc_u_knode *n, struct nlattr **tb,
489 struct nlattr *est) 489 struct nlattr *est, bool ovr)
490{ 490{
491 int err; 491 int err;
492 struct tcf_exts e; 492 struct tcf_exts e;
493 493
494 tcf_exts_init(&e, TCA_U32_ACT, TCA_U32_POLICE); 494 tcf_exts_init(&e, TCA_U32_ACT, TCA_U32_POLICE);
495 err = tcf_exts_validate(net, tp, tb, est, &e); 495 err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
496 if (err < 0) 496 if (err < 0)
497 return err; 497 return err;
498 498
@@ -545,7 +545,7 @@ errout:
545static int u32_change(struct net *net, struct sk_buff *in_skb, 545static int u32_change(struct net *net, struct sk_buff *in_skb,
546 struct tcf_proto *tp, unsigned long base, u32 handle, 546 struct tcf_proto *tp, unsigned long base, u32 handle,
547 struct nlattr **tca, 547 struct nlattr **tca,
548 unsigned long *arg) 548 unsigned long *arg, bool ovr)
549{ 549{
550 struct tc_u_common *tp_c = tp->data; 550 struct tc_u_common *tp_c = tp->data;
551 struct tc_u_hnode *ht; 551 struct tc_u_hnode *ht;
@@ -569,7 +569,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
569 return -EINVAL; 569 return -EINVAL;
570 570
571 return u32_set_parms(net, tp, base, n->ht_up, n, tb, 571 return u32_set_parms(net, tp, base, n->ht_up, n, tb,
572 tca[TCA_RATE]); 572 tca[TCA_RATE], ovr);
573 } 573 }
574 574
575 if (tb[TCA_U32_DIVISOR]) { 575 if (tb[TCA_U32_DIVISOR]) {
@@ -656,7 +656,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
656 } 656 }
657#endif 657#endif
658 658
659 err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE]); 659 err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE], ovr);
660 if (err == 0) { 660 if (err == 0) {
661 struct tc_u_knode **ins; 661 struct tc_u_knode **ins;
662 for (ins = &ht->ht[TC_U32_HASH(handle)]; *ins; ins = &(*ins)->next) 662 for (ins = &ht->ht[TC_U32_HASH(handle)]; *ins; ins = &(*ins)->next)