]> git.ipfire.org Git - thirdparty/kernel/stable.git/blobdiff - net/netfilter/xt_cgroup.c
netfilter: xt_cgroup: shrink size of v2 path
[thirdparty/kernel/stable.git] / net / netfilter / xt_cgroup.c
index 891f4e7e8ea7f507eebf1a22fa5dd818fc3ab49c..db18c0177b0f9caed3faf4b40ee4864a47fde25a 100644 (file)
@@ -66,6 +66,38 @@ static int cgroup_mt_check_v1(const struct xt_mtchk_param *par)
        return 0;
 }
 
+static int cgroup_mt_check_v2(const struct xt_mtchk_param *par)
+{
+       struct xt_cgroup_info_v2 *info = par->matchinfo;
+       struct cgroup *cgrp;
+
+       if ((info->invert_path & ~1) || (info->invert_classid & ~1))
+               return -EINVAL;
+
+       if (!info->has_path && !info->has_classid) {
+               pr_info("xt_cgroup: no path or classid specified\n");
+               return -EINVAL;
+       }
+
+       if (info->has_path && info->has_classid) {
+               pr_info_ratelimited("path and classid specified\n");
+               return -EINVAL;
+       }
+
+       info->priv = NULL;
+       if (info->has_path) {
+               cgrp = cgroup_get_from_path(info->path);
+               if (IS_ERR(cgrp)) {
+                       pr_info_ratelimited("invalid path, errno=%ld\n",
+                                           PTR_ERR(cgrp));
+                       return -EINVAL;
+               }
+               info->priv = cgrp;
+       }
+
+       return 0;
+}
+
 static bool
 cgroup_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
 {
@@ -95,6 +127,24 @@ static bool cgroup_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
                        info->invert_classid;
 }
 
+static bool cgroup_mt_v2(const struct sk_buff *skb, struct xt_action_param *par)
+{
+       const struct xt_cgroup_info_v2 *info = par->matchinfo;
+       struct sock_cgroup_data *skcd = &skb->sk->sk_cgrp_data;
+       struct cgroup *ancestor = info->priv;
+       struct sock *sk = skb->sk;
+
+       if (!sk || !sk_fullsock(sk) || !net_eq(xt_net(par), sock_net(sk)))
+               return false;
+
+       if (ancestor)
+               return cgroup_is_descendant(sock_cgroup_ptr(skcd), ancestor) ^
+                       info->invert_path;
+       else
+               return (info->classid == sock_cgroup_classid(skcd)) ^
+                       info->invert_classid;
+}
+
 static void cgroup_mt_destroy_v1(const struct xt_mtdtor_param *par)
 {
        struct xt_cgroup_info_v1 *info = par->matchinfo;
@@ -103,6 +153,14 @@ static void cgroup_mt_destroy_v1(const struct xt_mtdtor_param *par)
                cgroup_put(info->priv);
 }
 
+static void cgroup_mt_destroy_v2(const struct xt_mtdtor_param *par)
+{
+       struct xt_cgroup_info_v2 *info = par->matchinfo;
+
+       if (info->priv)
+               cgroup_put(info->priv);
+}
+
 static struct xt_match cgroup_mt_reg[] __read_mostly = {
        {
                .name           = "cgroup",
@@ -130,6 +188,20 @@ static struct xt_match cgroup_mt_reg[] __read_mostly = {
                                  (1 << NF_INET_POST_ROUTING) |
                                  (1 << NF_INET_LOCAL_IN),
        },
+       {
+               .name           = "cgroup",
+               .revision       = 2,
+               .family         = NFPROTO_UNSPEC,
+               .checkentry     = cgroup_mt_check_v2,
+               .match          = cgroup_mt_v2,
+               .matchsize      = sizeof(struct xt_cgroup_info_v2),
+               .usersize       = offsetof(struct xt_cgroup_info_v2, priv),
+               .destroy        = cgroup_mt_destroy_v2,
+               .me             = THIS_MODULE,
+               .hooks          = (1 << NF_INET_LOCAL_OUT) |
+                                 (1 << NF_INET_POST_ROUTING) |
+                                 (1 << NF_INET_LOCAL_IN),
+       },
 };
 
 static int __init cgroup_mt_init(void)