netfilter: xt_owner: Add supplementary groups option 57/209357/1
authorLukasz Pawelczyk <l.pawelczyk@samsung.com>
Fri, 10 May 2019 11:46:22 +0000 (13:46 +0200)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Fri, 5 Jul 2019 06:20:26 +0000 (15:20 +0900)
The XT_OWNER_SUPPL_GROUPS flag causes GIDs specified with XT_OWNER_GID
to be also checked in the supplementary groups of a process.

f_cred->group_info cannot be modified during its lifetime and f_cred
holds a reference to it so it's safe to use.

Signed-off-by: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
[sw0312.kim: backport from mainline to apply supplementary groups on netfilter]
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Change-Id: I30739d09c47d0623d0638de685905d3ac2ca131a

include/uapi/linux/netfilter/xt_owner.h
net/netfilter/xt_owner.c

index 2081761..e7731dc 100644 (file)
@@ -4,9 +4,10 @@
 #include <linux/types.h>
 
 enum {
-       XT_OWNER_UID    = 1 << 0,
-       XT_OWNER_GID    = 1 << 1,
-       XT_OWNER_SOCKET = 1 << 2,
+       XT_OWNER_UID          = 1 << 0,
+       XT_OWNER_GID          = 1 << 1,
+       XT_OWNER_SOCKET       = 1 << 2,
+       XT_OWNER_SUPPL_GROUPS = 1 << 3,
 };
 
 struct xt_owner_match_info {
index 1302b47..6423e48 100644 (file)
@@ -60,11 +60,28 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
        }
 
        if (info->match & XT_OWNER_GID) {
+               unsigned int i, match = false;
                kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min);
                kgid_t gid_max = make_kgid(&init_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))
+               struct group_info *gi = filp->f_cred->group_info;
+
+               if (gid_gte(filp->f_cred->fsgid, gid_min) &&
+                   gid_lte(filp->f_cred->fsgid, gid_max))
+                       match = true;
+
+               if (!match && (info->match & XT_OWNER_SUPPL_GROUPS) && gi) {
+                       for (i = 0; i < gi->ngroups; ++i) {
+                               kgid_t group = gi->gid[i];
+
+                               if (gid_gte(group, gid_min) &&
+                                   gid_lte(group, gid_max)) {
+                                       match = true;
+                                       break;
+                               }
+                       }
+               }
+
+               if (match ^ !(info->invert & XT_OWNER_GID))
                        return false;
        }