]> git.proxmox.com Git - mirror_spl.git/blob - module/spl/spl-cred.c
Linux 4.9 compat: group_info changes
[mirror_spl.git] / module / spl / spl-cred.c
1 /*****************************************************************************\
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
6 * UCRL-CODE-235197
7 *
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://zfsonlinux.org/>.
10 *
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting Layer (SPL) Credential Implementation.
25 \*****************************************************************************/
26
27 #include <sys/cred.h>
28
29 #ifdef DEBUG_SUBSYSTEM
30 #undef DEBUG_SUBSYSTEM
31 #endif
32
33 #define DEBUG_SUBSYSTEM S_CRED
34
35 static int
36 #ifdef HAVE_KUIDGID_T
37 cr_groups_search(const struct group_info *group_info, kgid_t grp)
38 #else
39 cr_groups_search(const struct group_info *group_info, gid_t grp)
40 #endif
41 {
42 unsigned int left, right, mid;
43 int cmp;
44
45 if (!group_info)
46 return 0;
47
48 left = 0;
49 right = group_info->ngroups;
50 while (left < right) {
51 mid = (left + right) / 2;
52 cmp = KGID_TO_SGID(grp) -
53 KGID_TO_SGID(GROUP_AT(group_info, mid));
54
55 if (cmp > 0)
56 left = mid + 1;
57 else if (cmp < 0)
58 right = mid;
59 else
60 return 1;
61 }
62 return 0;
63 }
64
65 /* Hold a reference on the credential */
66 void
67 crhold(cred_t *cr)
68 {
69 (void)get_cred((const cred_t *)cr);
70 }
71
72 /* Free a reference on the credential */
73 void
74 crfree(cred_t *cr)
75 {
76 put_cred((const cred_t *)cr);
77 }
78
79 /* Return the number of supplemental groups */
80 int
81 crgetngroups(const cred_t *cr)
82 {
83 struct group_info *gi;
84 int rc;
85
86 gi = cr->group_info;
87 rc = gi->ngroups;
88 #ifndef HAVE_GROUP_INFO_GID
89 /*
90 * For Linux <= 4.8,
91 * crgetgroups will only returns gi->blocks[0], which contains only
92 * the first NGROUPS_PER_BLOCK groups.
93 */
94 if (rc > NGROUPS_PER_BLOCK) {
95 WARN_ON_ONCE(1);
96 rc = NGROUPS_PER_BLOCK;
97 }
98 #endif
99 return rc;
100 }
101
102 /*
103 * Return an array of supplemental gids. The returned address is safe
104 * to use as long as the caller has taken a reference with crhold().
105 *
106 * Linux 4.9 API change, group_info changed from 2d array via ->blocks to 1d
107 * array via ->gid.
108 */
109 gid_t *
110 crgetgroups(const cred_t *cr)
111 {
112 struct group_info *gi;
113 gid_t *gids = NULL;
114
115 gi = cr->group_info;
116 #ifdef HAVE_GROUP_INFO_GID
117 gids = KGIDP_TO_SGIDP(gi->gid);
118 #else
119 if (gi->nblocks > 0)
120 gids = KGIDP_TO_SGIDP(gi->blocks[0]);
121 #endif
122 return gids;
123 }
124
125 /* Check if the passed gid is available in supplied credential. */
126 int
127 groupmember(gid_t gid, const cred_t *cr)
128 {
129 struct group_info *gi;
130 int rc;
131
132 gi = cr->group_info;
133 rc = cr_groups_search(gi, SGID_TO_KGID(gid));
134
135 return rc;
136 }
137
138 /* Return the effective user id */
139 uid_t
140 crgetuid(const cred_t *cr)
141 {
142 return KUID_TO_SUID(cr->euid);
143 }
144
145 /* Return the real user id */
146 uid_t
147 crgetruid(const cred_t *cr)
148 {
149 return KUID_TO_SUID(cr->uid);
150 }
151
152 /* Return the saved user id */
153 uid_t
154 crgetsuid(const cred_t *cr)
155 {
156 return KUID_TO_SUID(cr->suid);
157 }
158
159 /* Return the filesystem user id */
160 uid_t
161 crgetfsuid(const cred_t *cr)
162 {
163 return KUID_TO_SUID(cr->fsuid);
164 }
165
166 /* Return the effective group id */
167 gid_t
168 crgetgid(const cred_t *cr)
169 {
170 return KGID_TO_SGID(cr->egid);
171 }
172
173 /* Return the real group id */
174 gid_t
175 crgetrgid(const cred_t *cr)
176 {
177 return KGID_TO_SGID(cr->gid);
178 }
179
180 /* Return the saved group id */
181 gid_t
182 crgetsgid(const cred_t *cr)
183 {
184 return KGID_TO_SGID(cr->sgid);
185 }
186
187 /* Return the filesystem group id */
188 gid_t
189 crgetfsgid(const cred_t *cr)
190 {
191 return KGID_TO_SGID(cr->fsgid);
192 }
193
194 EXPORT_SYMBOL(crhold);
195 EXPORT_SYMBOL(crfree);
196 EXPORT_SYMBOL(crgetuid);
197 EXPORT_SYMBOL(crgetruid);
198 EXPORT_SYMBOL(crgetsuid);
199 EXPORT_SYMBOL(crgetfsuid);
200 EXPORT_SYMBOL(crgetgid);
201 EXPORT_SYMBOL(crgetrgid);
202 EXPORT_SYMBOL(crgetsgid);
203 EXPORT_SYMBOL(crgetfsgid);
204 EXPORT_SYMBOL(crgetngroups);
205 EXPORT_SYMBOL(crgetgroups);
206 EXPORT_SYMBOL(groupmember);