Merge tag 'asoc-v3.16-rc1' into asoc-linus
[cascardo/linux.git] / net / sched / cls_api.c
index bdbdb1a..45527e6 100644 (file)
@@ -134,7 +134,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
        int err;
        int tp_created = 0;
 
-       if ((n->nlmsg_type != RTM_GETTFILTER) && !netlink_capable(skb, CAP_NET_ADMIN))
+       if ((n->nlmsg_type != RTM_GETTFILTER) &&
+           !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
 replay:
@@ -317,7 +318,8 @@ replay:
                }
        }
 
-       err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh);
+       err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
+                             n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE);
        if (err == 0) {
                if (tp_created) {
                        spin_lock_bh(root_lock);
@@ -504,7 +506,7 @@ void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
 EXPORT_SYMBOL(tcf_exts_destroy);
 
 int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
-                 struct nlattr *rate_tlv, struct tcf_exts *exts)
+                 struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr)
 {
 #ifdef CONFIG_NET_CLS_ACT
        {
@@ -513,7 +515,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
                INIT_LIST_HEAD(&exts->actions);
                if (exts->police && tb[exts->police]) {
                        act = tcf_action_init_1(net, tb[exts->police], rate_tlv,
-                                               "police", TCA_ACT_NOREPLACE,
+                                               "police", ovr,
                                                TCA_ACT_BIND);
                        if (IS_ERR(act))
                                return PTR_ERR(act);
@@ -523,7 +525,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
                } else if (exts->action && tb[exts->action]) {
                        int err;
                        err = tcf_action_init(net, tb[exts->action], rate_tlv,
-                                             NULL, TCA_ACT_NOREPLACE,
+                                             NULL, ovr,
                                              TCA_ACT_BIND, &exts->actions);
                        if (err)
                                return err;
@@ -543,14 +545,12 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
                     struct tcf_exts *src)
 {
 #ifdef CONFIG_NET_CLS_ACT
-       if (!list_empty(&src->actions)) {
-               LIST_HEAD(tmp);
-               tcf_tree_lock(tp);
-               list_splice_init(&dst->actions, &tmp);
-               list_splice(&src->actions, &dst->actions);
-               tcf_tree_unlock(tp);
-               tcf_action_destroy(&tmp, TCA_ACT_UNBIND);
-       }
+       LIST_HEAD(tmp);
+       tcf_tree_lock(tp);
+       list_splice_init(&dst->actions, &tmp);
+       list_splice(&src->actions, &dst->actions);
+       tcf_tree_unlock(tp);
+       tcf_action_destroy(&tmp, TCA_ACT_UNBIND);
 #endif
 }
 EXPORT_SYMBOL(tcf_exts_change);