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.
Unified · Split
| @@ -5,9 +5,10 @@ · 4 unmodified lines | ||
| 5 | 5 | #include <linux/types.h> |
| 6 | 6 | |
| 7 | 7 | enum { |
| 8 | − XT_OWNER_UID = 1 << 0, | |
| 9 | − XT_OWNER_GID = 1 << 1, | |
| 10 | − XT_OWNER_SOCKET = 1 << 2, | |
| 8 | + XT_OWNER_UID = 1 << 0, | |
| 9 | + XT_OWNER_GID = 1 << 1, | |
| 10 | + XT_OWNER_SOCKET = 1 << 2, | |
| 11 | + XT_OWNER_SUPPL_GROUPS = 1 << 3, | |
| 11 | 12 | }; |
| 12 | 13 | |
| 13 | 14 | struct xt_owner_match_info { |
| @@ -91,11 +91,28 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par) · 90 unmodified lines | ||
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | if (info->match & XT_OWNER_GID) { |
| 94 | + unsigned int i, match = false; | |
| 94 | 95 | kgid_t gid_min = make_kgid(net->user_ns, info->gid_min); |
| 95 | 96 | kgid_t gid_max = make_kgid(net->user_ns, info->gid_max); |
| 96 | − if ((gid_gte(filp->f_cred->fsgid, gid_min) && | |
| 97 | − gid_lte(filp->f_cred->fsgid, gid_max)) ^ | |
| 98 | − !(info->invert & XT_OWNER_GID)) | |
| 97 | + struct group_info *gi = filp->f_cred->group_info; | |
| 98 | + | |
| 99 | + if (gid_gte(filp->f_cred->fsgid, gid_min) && | |
| 100 | + gid_lte(filp->f_cred->fsgid, gid_max)) | |
| 101 | + match = true; | |
| 102 | + | |
| 103 | + if (!match && (info->match & XT_OWNER_SUPPL_GROUPS) && gi) { | |
| 104 | + for (i = 0; i < gi->ngroups; ++i) { | |
| 105 | + kgid_t group = gi->gid[i]; | |
| 106 | + | |
| 107 | + if (gid_gte(group, gid_min) && | |
| 108 | + gid_lte(group, gid_max)) { | |
| 109 | + match = true; | |
| 110 | + break; | |
| 111 | + } | |
| 112 | + } | |
| 113 | + } | |
| 114 | + | |
| 115 | + if (match ^ !(info->invert & XT_OWNER_GID)) | |
| 99 | 116 | return false; |
| 100 | 117 | } |
| 101 | 118 | |