netfilter: xt_owner: Add supplementary groups option 36/203436/6
authorLukasz Pawelczyk <l.pawelczyk@samsung.com>
Fri, 10 May 2019 11:46:22 +0000 (13:46 +0200)
committerManish Rathod <manish.r@samsung.com>
Tue, 10 Sep 2019 12:06:57 +0000 (12:06 +0000)
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>
backport from mainline to apply supplementary groups on netfilter

Change-Id: I900d03042c82b4d5f13dec7695e4b1eba7f2aa74
(cherry picked from commit e7a26f2b0e8021c9415f0b92caf9538974720855)

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

index 7fcac2e..e5c670d 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,
 };
 
 #define XT_OWNER_MASK  (XT_OWNER_UID |         \
index 127823f..88aa4bf 100644 (file)
@@ -63,11 +63,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 = GROUP_AT(gi, i);
+
+                               if (gid_gte(group, gid_min) &&
+                                   gid_lte(group, gid_max)) {
+                                       match = true;
+                                       break;
+                               }
+                       }
+               }
+
+               if (match ^ !(info->invert & XT_OWNER_GID))
                        return false;
        }