x86/asm: Get rid of __read_cr4_safe()
[cascardo/linux.git] / net / netfilter / xt_owner.c
index 1302b47..a20e731 100644 (file)
 static int owner_check(const struct xt_mtchk_param *par)
 {
        struct xt_owner_match_info *info = par->matchinfo;
+       struct net *net = par->net;
 
-       /* For now only allow adding matches from the initial user namespace */
+       /* Only allow the common case where the userns of the writer
+        * matches the userns of the network namespace.
+        */
        if ((info->match & (XT_OWNER_UID|XT_OWNER_GID)) &&
-           (current_user_ns() != &init_user_ns))
+           (current_user_ns() != net->user_ns))
                return -EINVAL;
+
+       /* Ensure the uids are valid */
+       if (info->match & XT_OWNER_UID) {
+               kuid_t uid_min = make_kuid(net->user_ns, info->uid_min);
+               kuid_t uid_max = make_kuid(net->user_ns, info->uid_max);
+
+               if (!uid_valid(uid_min) || !uid_valid(uid_max) ||
+                   (info->uid_max < info->uid_min) ||
+                   uid_lt(uid_max, uid_min)) {
+                       return -EINVAL;
+               }
+       }
+
+       /* Ensure the gids are valid */
+       if (info->match & XT_OWNER_GID) {
+               kgid_t gid_min = make_kgid(net->user_ns, info->gid_min);
+               kgid_t gid_max = make_kgid(net->user_ns, info->gid_max);
+
+               if (!gid_valid(gid_min) || !gid_valid(gid_max) ||
+                   (info->gid_max < info->gid_min) ||
+                   gid_lt(gid_max, gid_min)) {
+                       return -EINVAL;
+               }
+       }
+
        return 0;
 }
 
@@ -35,6 +63,7 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
        const struct xt_owner_match_info *info = par->matchinfo;
        const struct file *filp;
        struct sock *sk = skb_to_full_sk(skb);
+       struct net *net = par->net;
 
        if (sk == NULL || sk->sk_socket == NULL)
                return (info->match ^ info->invert) == 0;
@@ -51,8 +80,8 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
                       (XT_OWNER_UID | XT_OWNER_GID)) == 0;
 
        if (info->match & XT_OWNER_UID) {
-               kuid_t uid_min = make_kuid(&init_user_ns, info->uid_min);
-               kuid_t uid_max = make_kuid(&init_user_ns, info->uid_max);
+               kuid_t uid_min = make_kuid(net->user_ns, info->uid_min);
+               kuid_t uid_max = make_kuid(net->user_ns, info->uid_max);
                if ((uid_gte(filp->f_cred->fsuid, uid_min) &&
                     uid_lte(filp->f_cred->fsuid, uid_max)) ^
                    !(info->invert & XT_OWNER_UID))
@@ -60,8 +89,8 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
        }
 
        if (info->match & XT_OWNER_GID) {
-               kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min);
-               kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max);
+               kgid_t gid_min = make_kgid(net->user_ns, info->gid_min);
+               kgid_t gid_max = make_kgid(net->user_ns, info->gid_max);
                if ((gid_gte(filp->f_cred->fsgid, gid_min) &&
                     gid_lte(filp->f_cred->fsgid, gid_max)) ^
                    !(info->invert & XT_OWNER_GID))