diff options
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/cls_api.c | 26 | ||||
-rw-r--r-- | net/sched/cls_basic.c | 10 | ||||
-rw-r--r-- | net/sched/cls_bpf.c | 14 | ||||
-rw-r--r-- | net/sched/cls_cgroup.c | 4 | ||||
-rw-r--r-- | net/sched/cls_flow.c | 4 | ||||
-rw-r--r-- | net/sched/cls_fw.c | 10 | ||||
-rw-r--r-- | net/sched/cls_route.c | 11 | ||||
-rw-r--r-- | net/sched/cls_rsvp.h | 4 | ||||
-rw-r--r-- | net/sched/cls_tcindex.c | 8 | ||||
-rw-r--r-- | net/sched/cls_u32.c | 10 | ||||
-rw-r--r-- | net/sched/sch_api.c | 10 | ||||
-rw-r--r-- | net/sched/sch_choke.c | 7 | ||||
-rw-r--r-- | net/sched/sch_drr.c | 4 | ||||
-rw-r--r-- | net/sched/sch_fq.c | 5 | ||||
-rw-r--r-- | net/sched/sch_fq_codel.c | 7 | ||||
-rw-r--r-- | net/sched/sch_hhf.c | 9 | ||||
-rw-r--r-- | net/sched/sch_netem.c | 7 | ||||
-rw-r--r-- | net/sched/sch_sfq.c | 7 |
18 files changed, 67 insertions, 90 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index bdbdb1a7920a..45527e6b52db 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -134,7 +134,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) | |||
134 | int err; | 134 | int err; |
135 | int tp_created = 0; | 135 | int tp_created = 0; |
136 | 136 | ||
137 | if ((n->nlmsg_type != RTM_GETTFILTER) && !netlink_capable(skb, CAP_NET_ADMIN)) | 137 | if ((n->nlmsg_type != RTM_GETTFILTER) && |
138 | !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) | ||
138 | return -EPERM; | 139 | return -EPERM; |
139 | 140 | ||
140 | replay: | 141 | replay: |
@@ -317,7 +318,8 @@ replay: | |||
317 | } | 318 | } |
318 | } | 319 | } |
319 | 320 | ||
320 | err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh); | 321 | err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh, |
322 | n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE); | ||
321 | if (err == 0) { | 323 | if (err == 0) { |
322 | if (tp_created) { | 324 | if (tp_created) { |
323 | spin_lock_bh(root_lock); | 325 | spin_lock_bh(root_lock); |
@@ -504,7 +506,7 @@ void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts) | |||
504 | EXPORT_SYMBOL(tcf_exts_destroy); | 506 | EXPORT_SYMBOL(tcf_exts_destroy); |
505 | 507 | ||
506 | int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, | 508 | int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, |
507 | struct nlattr *rate_tlv, struct tcf_exts *exts) | 509 | struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr) |
508 | { | 510 | { |
509 | #ifdef CONFIG_NET_CLS_ACT | 511 | #ifdef CONFIG_NET_CLS_ACT |
510 | { | 512 | { |
@@ -513,7 +515,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, | |||
513 | INIT_LIST_HEAD(&exts->actions); | 515 | INIT_LIST_HEAD(&exts->actions); |
514 | if (exts->police && tb[exts->police]) { | 516 | if (exts->police && tb[exts->police]) { |
515 | act = tcf_action_init_1(net, tb[exts->police], rate_tlv, | 517 | act = tcf_action_init_1(net, tb[exts->police], rate_tlv, |
516 | "police", TCA_ACT_NOREPLACE, | 518 | "police", ovr, |
517 | TCA_ACT_BIND); | 519 | TCA_ACT_BIND); |
518 | if (IS_ERR(act)) | 520 | if (IS_ERR(act)) |
519 | return PTR_ERR(act); | 521 | return PTR_ERR(act); |
@@ -523,7 +525,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, | |||
523 | } else if (exts->action && tb[exts->action]) { | 525 | } else if (exts->action && tb[exts->action]) { |
524 | int err; | 526 | int err; |
525 | err = tcf_action_init(net, tb[exts->action], rate_tlv, | 527 | err = tcf_action_init(net, tb[exts->action], rate_tlv, |
526 | NULL, TCA_ACT_NOREPLACE, | 528 | NULL, ovr, |
527 | TCA_ACT_BIND, &exts->actions); | 529 | TCA_ACT_BIND, &exts->actions); |
528 | if (err) | 530 | if (err) |
529 | return err; | 531 | return err; |
@@ -543,14 +545,12 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, | |||
543 | struct tcf_exts *src) | 545 | struct tcf_exts *src) |
544 | { | 546 | { |
545 | #ifdef CONFIG_NET_CLS_ACT | 547 | #ifdef CONFIG_NET_CLS_ACT |
546 | if (!list_empty(&src->actions)) { | 548 | LIST_HEAD(tmp); |
547 | LIST_HEAD(tmp); | 549 | tcf_tree_lock(tp); |
548 | tcf_tree_lock(tp); | 550 | list_splice_init(&dst->actions, &tmp); |
549 | list_splice_init(&dst->actions, &tmp); | 551 | list_splice(&src->actions, &dst->actions); |
550 | list_splice(&src->actions, &dst->actions); | 552 | tcf_tree_unlock(tp); |
551 | tcf_tree_unlock(tp); | 553 | tcf_action_destroy(&tmp, TCA_ACT_UNBIND); |
552 | tcf_action_destroy(&tmp, TCA_ACT_UNBIND); | ||
553 | } | ||
554 | #endif | 554 | #endif |
555 | } | 555 | } |
556 | EXPORT_SYMBOL(tcf_exts_change); | 556 | EXPORT_SYMBOL(tcf_exts_change); |
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] = { | |||
130 | static int basic_set_parms(struct net *net, struct tcf_proto *tp, | 130 | static 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 | ||
162 | static int basic_change(struct net *net, struct sk_buff *in_skb, | 162 | static 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..13f64df2c710 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
@@ -156,11 +156,11 @@ 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; |
163 | struct sock_fprog tmp; | 163 | struct sock_fprog_kern tmp; |
164 | struct sk_filter *fp, *fp_old; | 164 | struct sk_filter *fp, *fp_old; |
165 | u16 bpf_size, bpf_len; | 165 | u16 bpf_size, bpf_len; |
166 | u32 classid; | 166 | u32 classid; |
@@ -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 | ||
@@ -191,7 +191,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, | |||
191 | memcpy(bpf_ops, nla_data(tb[TCA_BPF_OPS]), bpf_size); | 191 | memcpy(bpf_ops, nla_data(tb[TCA_BPF_OPS]), bpf_size); |
192 | 192 | ||
193 | tmp.len = bpf_len; | 193 | tmp.len = bpf_len; |
194 | tmp.filter = (struct sock_filter __user *) bpf_ops; | 194 | tmp.filter = bpf_ops; |
195 | 195 | ||
196 | ret = sk_unattached_filter_create(&fp, &tmp); | 196 | ret = sk_unattached_filter_create(&fp, &tmp); |
197 | if (ret) | 197 | if (ret) |
@@ -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 | ||
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] = { | |||
83 | static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb, | 83 | static 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] = { | |||
349 | static int flow_change(struct net *net, struct sk_buff *in_skb, | 349 | static 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 | ||
170 | static int | 170 | static int |
171 | fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f, | 171 | fw_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] = { | |||
333 | static int route4_set_parms(struct net *net, struct tcf_proto *tp, | 333 | static 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 f435a88d899a..c721cd4a469f 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -198,7 +198,7 @@ static int | |||
198 | tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, | 198 | tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, |
199 | u32 handle, struct tcindex_data *p, | 199 | u32 handle, struct tcindex_data *p, |
200 | struct tcindex_filter_result *r, struct nlattr **tb, | 200 | struct tcindex_filter_result *r, struct nlattr **tb, |
201 | struct nlattr *est) | 201 | struct nlattr *est, bool ovr) |
202 | { | 202 | { |
203 | int err, balloc = 0; | 203 | int err, balloc = 0; |
204 | struct tcindex_filter_result new_filter_result, *old_r = r; | 204 | struct tcindex_filter_result new_filter_result, *old_r = r; |
@@ -208,7 +208,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, | |||
208 | struct tcf_exts e; | 208 | struct tcf_exts e; |
209 | 209 | ||
210 | tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); | 210 | tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); |
211 | err = tcf_exts_validate(net, tp, tb, est, &e); | 211 | err = tcf_exts_validate(net, tp, tb, est, &e, ovr); |
212 | if (err < 0) | 212 | if (err < 0) |
213 | return err; | 213 | return err; |
214 | 214 | ||
@@ -341,7 +341,7 @@ errout: | |||
341 | static int | 341 | static int |
342 | tcindex_change(struct net *net, struct sk_buff *in_skb, | 342 | tcindex_change(struct net *net, struct sk_buff *in_skb, |
343 | struct tcf_proto *tp, unsigned long base, u32 handle, | 343 | struct tcf_proto *tp, unsigned long base, u32 handle, |
344 | struct nlattr **tca, unsigned long *arg) | 344 | struct nlattr **tca, unsigned long *arg, bool ovr) |
345 | { | 345 | { |
346 | struct nlattr *opt = tca[TCA_OPTIONS]; | 346 | struct nlattr *opt = tca[TCA_OPTIONS]; |
347 | struct nlattr *tb[TCA_TCINDEX_MAX + 1]; | 347 | struct nlattr *tb[TCA_TCINDEX_MAX + 1]; |
@@ -361,7 +361,7 @@ tcindex_change(struct net *net, struct sk_buff *in_skb, | |||
361 | return err; | 361 | return err; |
362 | 362 | ||
363 | return tcindex_set_parms(net, tp, base, handle, p, r, tb, | 363 | return tcindex_set_parms(net, tp, base, handle, p, r, tb, |
364 | tca[TCA_RATE]); | 364 | tca[TCA_RATE], ovr); |
365 | } | 365 | } |
366 | 366 | ||
367 | 367 | ||
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] = { | |||
486 | static int u32_set_parms(struct net *net, struct tcf_proto *tp, | 486 | static 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: | |||
545 | static int u32_change(struct net *net, struct sk_buff *in_skb, | 545 | static 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) |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 400769014bbd..58bed7599db7 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -563,7 +563,7 @@ out: | |||
563 | } | 563 | } |
564 | EXPORT_SYMBOL(__qdisc_calculate_pkt_len); | 564 | EXPORT_SYMBOL(__qdisc_calculate_pkt_len); |
565 | 565 | ||
566 | void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc) | 566 | void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc) |
567 | { | 567 | { |
568 | if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { | 568 | if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { |
569 | pr_warn("%s: %s qdisc %X: is non-work-conserving?\n", | 569 | pr_warn("%s: %s qdisc %X: is non-work-conserving?\n", |
@@ -1084,7 +1084,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n) | |||
1084 | struct Qdisc *p = NULL; | 1084 | struct Qdisc *p = NULL; |
1085 | int err; | 1085 | int err; |
1086 | 1086 | ||
1087 | if ((n->nlmsg_type != RTM_GETQDISC) && !netlink_capable(skb, CAP_NET_ADMIN)) | 1087 | if ((n->nlmsg_type != RTM_GETQDISC) && |
1088 | !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) | ||
1088 | return -EPERM; | 1089 | return -EPERM; |
1089 | 1090 | ||
1090 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1091 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1151,7 +1152,7 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n) | |||
1151 | struct Qdisc *q, *p; | 1152 | struct Qdisc *q, *p; |
1152 | int err; | 1153 | int err; |
1153 | 1154 | ||
1154 | if (!netlink_capable(skb, CAP_NET_ADMIN)) | 1155 | if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) |
1155 | return -EPERM; | 1156 | return -EPERM; |
1156 | 1157 | ||
1157 | replay: | 1158 | replay: |
@@ -1490,7 +1491,8 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n) | |||
1490 | u32 qid; | 1491 | u32 qid; |
1491 | int err; | 1492 | int err; |
1492 | 1493 | ||
1493 | if ((n->nlmsg_type != RTM_GETTCLASS) && !netlink_capable(skb, CAP_NET_ADMIN)) | 1494 | if ((n->nlmsg_type != RTM_GETTCLASS) && |
1495 | !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) | ||
1494 | return -EPERM; | 1496 | return -EPERM; |
1495 | 1497 | ||
1496 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1498 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index 2aee02802c27..ed30e436128b 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c | |||
@@ -391,12 +391,7 @@ static const struct nla_policy choke_policy[TCA_CHOKE_MAX + 1] = { | |||
391 | 391 | ||
392 | static void choke_free(void *addr) | 392 | static void choke_free(void *addr) |
393 | { | 393 | { |
394 | if (addr) { | 394 | kvfree(addr); |
395 | if (is_vmalloc_addr(addr)) | ||
396 | vfree(addr); | ||
397 | else | ||
398 | kfree(addr); | ||
399 | } | ||
400 | } | 395 | } |
401 | 396 | ||
402 | static int choke_change(struct Qdisc *sch, struct nlattr *opt) | 397 | static int choke_change(struct Qdisc *sch, struct nlattr *opt) |
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 8302717ea303..7bbbfe112192 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c | |||
@@ -391,8 +391,10 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch) | |||
391 | while (1) { | 391 | while (1) { |
392 | cl = list_first_entry(&q->active, struct drr_class, alist); | 392 | cl = list_first_entry(&q->active, struct drr_class, alist); |
393 | skb = cl->qdisc->ops->peek(cl->qdisc); | 393 | skb = cl->qdisc->ops->peek(cl->qdisc); |
394 | if (skb == NULL) | 394 | if (skb == NULL) { |
395 | qdisc_warn_nonwc(__func__, cl->qdisc); | ||
395 | goto out; | 396 | goto out; |
397 | } | ||
396 | 398 | ||
397 | len = qdisc_pkt_len(skb); | 399 | len = qdisc_pkt_len(skb); |
398 | if (len <= cl->deficit) { | 400 | if (len <= cl->deficit) { |
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 23c682b42f99..ba32c2b005d0 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c | |||
@@ -591,10 +591,7 @@ static void *fq_alloc_node(size_t sz, int node) | |||
591 | 591 | ||
592 | static void fq_free(void *addr) | 592 | static void fq_free(void *addr) |
593 | { | 593 | { |
594 | if (addr && is_vmalloc_addr(addr)) | 594 | kvfree(addr); |
595 | vfree(addr); | ||
596 | else | ||
597 | kfree(addr); | ||
598 | } | 595 | } |
599 | 596 | ||
600 | static int fq_resize(struct Qdisc *sch, u32 log) | 597 | static int fq_resize(struct Qdisc *sch, u32 log) |
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 0bf432c782c1..063b726bf1f8 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c | |||
@@ -365,12 +365,7 @@ static void *fq_codel_zalloc(size_t sz) | |||
365 | 365 | ||
366 | static void fq_codel_free(void *addr) | 366 | static void fq_codel_free(void *addr) |
367 | { | 367 | { |
368 | if (addr) { | 368 | kvfree(addr); |
369 | if (is_vmalloc_addr(addr)) | ||
370 | vfree(addr); | ||
371 | else | ||
372 | kfree(addr); | ||
373 | } | ||
374 | } | 369 | } |
375 | 370 | ||
376 | static void fq_codel_destroy(struct Qdisc *sch) | 371 | static void fq_codel_destroy(struct Qdisc *sch) |
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c index 6e957c3b9854..d85b6812a7d4 100644 --- a/net/sched/sch_hhf.c +++ b/net/sched/sch_hhf.c | |||
@@ -414,7 +414,7 @@ static int hhf_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
414 | } | 414 | } |
415 | bucket->deficit = weight * q->quantum; | 415 | bucket->deficit = weight * q->quantum; |
416 | } | 416 | } |
417 | if (++sch->q.qlen < sch->limit) | 417 | if (++sch->q.qlen <= sch->limit) |
418 | return NET_XMIT_SUCCESS; | 418 | return NET_XMIT_SUCCESS; |
419 | 419 | ||
420 | q->drop_overlimit++; | 420 | q->drop_overlimit++; |
@@ -494,12 +494,7 @@ static void *hhf_zalloc(size_t sz) | |||
494 | 494 | ||
495 | static void hhf_free(void *addr) | 495 | static void hhf_free(void *addr) |
496 | { | 496 | { |
497 | if (addr) { | 497 | kvfree(addr); |
498 | if (is_vmalloc_addr(addr)) | ||
499 | vfree(addr); | ||
500 | else | ||
501 | kfree(addr); | ||
502 | } | ||
503 | } | 498 | } |
504 | 499 | ||
505 | static void hhf_destroy(struct Qdisc *sch) | 500 | static void hhf_destroy(struct Qdisc *sch) |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index f1669a00f571..111d70fddaea 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -648,12 +648,7 @@ static void netem_reset(struct Qdisc *sch) | |||
648 | 648 | ||
649 | static void dist_free(struct disttable *d) | 649 | static void dist_free(struct disttable *d) |
650 | { | 650 | { |
651 | if (d) { | 651 | kvfree(d); |
652 | if (is_vmalloc_addr(d)) | ||
653 | vfree(d); | ||
654 | else | ||
655 | kfree(d); | ||
656 | } | ||
657 | } | 652 | } |
658 | 653 | ||
659 | /* | 654 | /* |
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 87317ff0b4ec..1af2f73906d0 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -716,12 +716,7 @@ static void *sfq_alloc(size_t sz) | |||
716 | 716 | ||
717 | static void sfq_free(void *addr) | 717 | static void sfq_free(void *addr) |
718 | { | 718 | { |
719 | if (addr) { | 719 | kvfree(addr); |
720 | if (is_vmalloc_addr(addr)) | ||
721 | vfree(addr); | ||
722 | else | ||
723 | kfree(addr); | ||
724 | } | ||
725 | } | 720 | } |
726 | 721 | ||
727 | static void sfq_destroy(struct Qdisc *sch) | 722 | static void sfq_destroy(struct Qdisc *sch) |