Commit 00fcd1ceab6c42f7facfa0168b207fe70ee198c2

Authored by Eric W. Biederman
Committed by Greg Kroah-Hartman
1 parent 5f20adeafc

groups: Consolidate the setgroups permission checks

commit 7ff4d90b4c24a03666f296c3d4878cd39001e81e upstream.

Today there are 3 instances of setgroups and due to an oversight their
permission checking has diverged.  Add a common function so that
they may all share the same permission checking code.

This corrects the current oversight in the current permission checks
and adds a helper to avoid this in the future.

A user namespace security fix will update this new helper, shortly.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 4 changed files with 11 additions and 3 deletions Inline Diff

arch/s390/kernel/compat_linux.c
1 /* 1 /*
2 * S390 version 2 * S390 version
3 * Copyright IBM Corp. 2000 3 * Copyright IBM Corp. 2000
4 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 4 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
5 * Gerhard Tonn (ton@de.ibm.com) 5 * Gerhard Tonn (ton@de.ibm.com)
6 * Thomas Spatzier (tspat@de.ibm.com) 6 * Thomas Spatzier (tspat@de.ibm.com)
7 * 7 *
8 * Conversion between 31bit and 64bit native syscalls. 8 * Conversion between 31bit and 64bit native syscalls.
9 * 9 *
10 * Heavily inspired by the 32-bit Sparc compat code which is 10 * Heavily inspired by the 32-bit Sparc compat code which is
11 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 11 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
12 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) 12 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
13 * 13 *
14 */ 14 */
15 15
16 16
17 #include <linux/kernel.h> 17 #include <linux/kernel.h>
18 #include <linux/sched.h> 18 #include <linux/sched.h>
19 #include <linux/fs.h> 19 #include <linux/fs.h>
20 #include <linux/mm.h> 20 #include <linux/mm.h>
21 #include <linux/file.h> 21 #include <linux/file.h>
22 #include <linux/signal.h> 22 #include <linux/signal.h>
23 #include <linux/resource.h> 23 #include <linux/resource.h>
24 #include <linux/times.h> 24 #include <linux/times.h>
25 #include <linux/smp.h> 25 #include <linux/smp.h>
26 #include <linux/sem.h> 26 #include <linux/sem.h>
27 #include <linux/msg.h> 27 #include <linux/msg.h>
28 #include <linux/shm.h> 28 #include <linux/shm.h>
29 #include <linux/uio.h> 29 #include <linux/uio.h>
30 #include <linux/quota.h> 30 #include <linux/quota.h>
31 #include <linux/module.h> 31 #include <linux/module.h>
32 #include <linux/poll.h> 32 #include <linux/poll.h>
33 #include <linux/personality.h> 33 #include <linux/personality.h>
34 #include <linux/stat.h> 34 #include <linux/stat.h>
35 #include <linux/filter.h> 35 #include <linux/filter.h>
36 #include <linux/highmem.h> 36 #include <linux/highmem.h>
37 #include <linux/highuid.h> 37 #include <linux/highuid.h>
38 #include <linux/mman.h> 38 #include <linux/mman.h>
39 #include <linux/ipv6.h> 39 #include <linux/ipv6.h>
40 #include <linux/in.h> 40 #include <linux/in.h>
41 #include <linux/icmpv6.h> 41 #include <linux/icmpv6.h>
42 #include <linux/syscalls.h> 42 #include <linux/syscalls.h>
43 #include <linux/sysctl.h> 43 #include <linux/sysctl.h>
44 #include <linux/binfmts.h> 44 #include <linux/binfmts.h>
45 #include <linux/capability.h> 45 #include <linux/capability.h>
46 #include <linux/compat.h> 46 #include <linux/compat.h>
47 #include <linux/vfs.h> 47 #include <linux/vfs.h>
48 #include <linux/ptrace.h> 48 #include <linux/ptrace.h>
49 #include <linux/fadvise.h> 49 #include <linux/fadvise.h>
50 #include <linux/ipc.h> 50 #include <linux/ipc.h>
51 #include <linux/slab.h> 51 #include <linux/slab.h>
52 52
53 #include <asm/types.h> 53 #include <asm/types.h>
54 #include <asm/uaccess.h> 54 #include <asm/uaccess.h>
55 55
56 #include <net/scm.h> 56 #include <net/scm.h>
57 #include <net/sock.h> 57 #include <net/sock.h>
58 58
59 #include "compat_linux.h" 59 #include "compat_linux.h"
60 60
61 /* For this source file, we want overflow handling. */ 61 /* For this source file, we want overflow handling. */
62 62
63 #undef high2lowuid 63 #undef high2lowuid
64 #undef high2lowgid 64 #undef high2lowgid
65 #undef low2highuid 65 #undef low2highuid
66 #undef low2highgid 66 #undef low2highgid
67 #undef SET_UID16 67 #undef SET_UID16
68 #undef SET_GID16 68 #undef SET_GID16
69 #undef NEW_TO_OLD_UID 69 #undef NEW_TO_OLD_UID
70 #undef NEW_TO_OLD_GID 70 #undef NEW_TO_OLD_GID
71 #undef SET_OLDSTAT_UID 71 #undef SET_OLDSTAT_UID
72 #undef SET_OLDSTAT_GID 72 #undef SET_OLDSTAT_GID
73 #undef SET_STAT_UID 73 #undef SET_STAT_UID
74 #undef SET_STAT_GID 74 #undef SET_STAT_GID
75 75
76 #define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid) 76 #define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
77 #define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) 77 #define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
78 #define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid) 78 #define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
79 #define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid) 79 #define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
80 #define SET_UID16(var, uid) var = high2lowuid(uid) 80 #define SET_UID16(var, uid) var = high2lowuid(uid)
81 #define SET_GID16(var, gid) var = high2lowgid(gid) 81 #define SET_GID16(var, gid) var = high2lowgid(gid)
82 #define NEW_TO_OLD_UID(uid) high2lowuid(uid) 82 #define NEW_TO_OLD_UID(uid) high2lowuid(uid)
83 #define NEW_TO_OLD_GID(gid) high2lowgid(gid) 83 #define NEW_TO_OLD_GID(gid) high2lowgid(gid)
84 #define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) 84 #define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
85 #define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) 85 #define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
86 #define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) 86 #define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
87 #define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) 87 #define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
88 88
89 asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group) 89 asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group)
90 { 90 {
91 return sys_chown(filename, low2highuid(user), low2highgid(group)); 91 return sys_chown(filename, low2highuid(user), low2highgid(group));
92 } 92 }
93 93
94 asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group) 94 asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group)
95 { 95 {
96 return sys_lchown(filename, low2highuid(user), low2highgid(group)); 96 return sys_lchown(filename, low2highuid(user), low2highgid(group));
97 } 97 }
98 98
99 asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group) 99 asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
100 { 100 {
101 return sys_fchown(fd, low2highuid(user), low2highgid(group)); 101 return sys_fchown(fd, low2highuid(user), low2highgid(group));
102 } 102 }
103 103
104 asmlinkage long sys32_setregid16(u16 rgid, u16 egid) 104 asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
105 { 105 {
106 return sys_setregid(low2highgid(rgid), low2highgid(egid)); 106 return sys_setregid(low2highgid(rgid), low2highgid(egid));
107 } 107 }
108 108
109 asmlinkage long sys32_setgid16(u16 gid) 109 asmlinkage long sys32_setgid16(u16 gid)
110 { 110 {
111 return sys_setgid((gid_t)gid); 111 return sys_setgid((gid_t)gid);
112 } 112 }
113 113
114 asmlinkage long sys32_setreuid16(u16 ruid, u16 euid) 114 asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
115 { 115 {
116 return sys_setreuid(low2highuid(ruid), low2highuid(euid)); 116 return sys_setreuid(low2highuid(ruid), low2highuid(euid));
117 } 117 }
118 118
119 asmlinkage long sys32_setuid16(u16 uid) 119 asmlinkage long sys32_setuid16(u16 uid)
120 { 120 {
121 return sys_setuid((uid_t)uid); 121 return sys_setuid((uid_t)uid);
122 } 122 }
123 123
124 asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid) 124 asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
125 { 125 {
126 return sys_setresuid(low2highuid(ruid), low2highuid(euid), 126 return sys_setresuid(low2highuid(ruid), low2highuid(euid),
127 low2highuid(suid)); 127 low2highuid(suid));
128 } 128 }
129 129
130 asmlinkage long sys32_getresuid16(u16 __user *ruidp, u16 __user *euidp, u16 __user *suidp) 130 asmlinkage long sys32_getresuid16(u16 __user *ruidp, u16 __user *euidp, u16 __user *suidp)
131 { 131 {
132 const struct cred *cred = current_cred(); 132 const struct cred *cred = current_cred();
133 int retval; 133 int retval;
134 u16 ruid, euid, suid; 134 u16 ruid, euid, suid;
135 135
136 ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid)); 136 ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid));
137 euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid)); 137 euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid));
138 suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid)); 138 suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid));
139 139
140 if (!(retval = put_user(ruid, ruidp)) && 140 if (!(retval = put_user(ruid, ruidp)) &&
141 !(retval = put_user(euid, euidp))) 141 !(retval = put_user(euid, euidp)))
142 retval = put_user(suid, suidp); 142 retval = put_user(suid, suidp);
143 143
144 return retval; 144 return retval;
145 } 145 }
146 146
147 asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid) 147 asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
148 { 148 {
149 return sys_setresgid(low2highgid(rgid), low2highgid(egid), 149 return sys_setresgid(low2highgid(rgid), low2highgid(egid),
150 low2highgid(sgid)); 150 low2highgid(sgid));
151 } 151 }
152 152
153 asmlinkage long sys32_getresgid16(u16 __user *rgidp, u16 __user *egidp, u16 __user *sgidp) 153 asmlinkage long sys32_getresgid16(u16 __user *rgidp, u16 __user *egidp, u16 __user *sgidp)
154 { 154 {
155 const struct cred *cred = current_cred(); 155 const struct cred *cred = current_cred();
156 int retval; 156 int retval;
157 u16 rgid, egid, sgid; 157 u16 rgid, egid, sgid;
158 158
159 rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid)); 159 rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid));
160 egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid)); 160 egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid));
161 sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid)); 161 sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid));
162 162
163 if (!(retval = put_user(rgid, rgidp)) && 163 if (!(retval = put_user(rgid, rgidp)) &&
164 !(retval = put_user(egid, egidp))) 164 !(retval = put_user(egid, egidp)))
165 retval = put_user(sgid, sgidp); 165 retval = put_user(sgid, sgidp);
166 166
167 return retval; 167 return retval;
168 } 168 }
169 169
170 asmlinkage long sys32_setfsuid16(u16 uid) 170 asmlinkage long sys32_setfsuid16(u16 uid)
171 { 171 {
172 return sys_setfsuid((uid_t)uid); 172 return sys_setfsuid((uid_t)uid);
173 } 173 }
174 174
175 asmlinkage long sys32_setfsgid16(u16 gid) 175 asmlinkage long sys32_setfsgid16(u16 gid)
176 { 176 {
177 return sys_setfsgid((gid_t)gid); 177 return sys_setfsgid((gid_t)gid);
178 } 178 }
179 179
180 static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info) 180 static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info)
181 { 181 {
182 struct user_namespace *user_ns = current_user_ns(); 182 struct user_namespace *user_ns = current_user_ns();
183 int i; 183 int i;
184 u16 group; 184 u16 group;
185 kgid_t kgid; 185 kgid_t kgid;
186 186
187 for (i = 0; i < group_info->ngroups; i++) { 187 for (i = 0; i < group_info->ngroups; i++) {
188 kgid = GROUP_AT(group_info, i); 188 kgid = GROUP_AT(group_info, i);
189 group = (u16)from_kgid_munged(user_ns, kgid); 189 group = (u16)from_kgid_munged(user_ns, kgid);
190 if (put_user(group, grouplist+i)) 190 if (put_user(group, grouplist+i))
191 return -EFAULT; 191 return -EFAULT;
192 } 192 }
193 193
194 return 0; 194 return 0;
195 } 195 }
196 196
197 static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist) 197 static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist)
198 { 198 {
199 struct user_namespace *user_ns = current_user_ns(); 199 struct user_namespace *user_ns = current_user_ns();
200 int i; 200 int i;
201 u16 group; 201 u16 group;
202 kgid_t kgid; 202 kgid_t kgid;
203 203
204 for (i = 0; i < group_info->ngroups; i++) { 204 for (i = 0; i < group_info->ngroups; i++) {
205 if (get_user(group, grouplist+i)) 205 if (get_user(group, grouplist+i))
206 return -EFAULT; 206 return -EFAULT;
207 207
208 kgid = make_kgid(user_ns, (gid_t)group); 208 kgid = make_kgid(user_ns, (gid_t)group);
209 if (!gid_valid(kgid)) 209 if (!gid_valid(kgid))
210 return -EINVAL; 210 return -EINVAL;
211 211
212 GROUP_AT(group_info, i) = kgid; 212 GROUP_AT(group_info, i) = kgid;
213 } 213 }
214 214
215 return 0; 215 return 0;
216 } 216 }
217 217
218 asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist) 218 asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
219 { 219 {
220 const struct cred *cred = current_cred(); 220 const struct cred *cred = current_cred();
221 int i; 221 int i;
222 222
223 if (gidsetsize < 0) 223 if (gidsetsize < 0)
224 return -EINVAL; 224 return -EINVAL;
225 225
226 get_group_info(cred->group_info); 226 get_group_info(cred->group_info);
227 i = cred->group_info->ngroups; 227 i = cred->group_info->ngroups;
228 if (gidsetsize) { 228 if (gidsetsize) {
229 if (i > gidsetsize) { 229 if (i > gidsetsize) {
230 i = -EINVAL; 230 i = -EINVAL;
231 goto out; 231 goto out;
232 } 232 }
233 if (groups16_to_user(grouplist, cred->group_info)) { 233 if (groups16_to_user(grouplist, cred->group_info)) {
234 i = -EFAULT; 234 i = -EFAULT;
235 goto out; 235 goto out;
236 } 236 }
237 } 237 }
238 out: 238 out:
239 put_group_info(cred->group_info); 239 put_group_info(cred->group_info);
240 return i; 240 return i;
241 } 241 }
242 242
243 asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) 243 asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
244 { 244 {
245 struct group_info *group_info; 245 struct group_info *group_info;
246 int retval; 246 int retval;
247 247
248 if (!capable(CAP_SETGID)) 248 if (!may_setgroups())
249 return -EPERM; 249 return -EPERM;
250 if ((unsigned)gidsetsize > NGROUPS_MAX) 250 if ((unsigned)gidsetsize > NGROUPS_MAX)
251 return -EINVAL; 251 return -EINVAL;
252 252
253 group_info = groups_alloc(gidsetsize); 253 group_info = groups_alloc(gidsetsize);
254 if (!group_info) 254 if (!group_info)
255 return -ENOMEM; 255 return -ENOMEM;
256 retval = groups16_from_user(group_info, grouplist); 256 retval = groups16_from_user(group_info, grouplist);
257 if (retval) { 257 if (retval) {
258 put_group_info(group_info); 258 put_group_info(group_info);
259 return retval; 259 return retval;
260 } 260 }
261 261
262 retval = set_current_groups(group_info); 262 retval = set_current_groups(group_info);
263 put_group_info(group_info); 263 put_group_info(group_info);
264 264
265 return retval; 265 return retval;
266 } 266 }
267 267
268 asmlinkage long sys32_getuid16(void) 268 asmlinkage long sys32_getuid16(void)
269 { 269 {
270 return high2lowuid(from_kuid_munged(current_user_ns(), current_uid())); 270 return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
271 } 271 }
272 272
273 asmlinkage long sys32_geteuid16(void) 273 asmlinkage long sys32_geteuid16(void)
274 { 274 {
275 return high2lowuid(from_kuid_munged(current_user_ns(), current_euid())); 275 return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
276 } 276 }
277 277
278 asmlinkage long sys32_getgid16(void) 278 asmlinkage long sys32_getgid16(void)
279 { 279 {
280 return high2lowgid(from_kgid_munged(current_user_ns(), current_gid())); 280 return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));
281 } 281 }
282 282
283 asmlinkage long sys32_getegid16(void) 283 asmlinkage long sys32_getegid16(void)
284 { 284 {
285 return high2lowgid(from_kgid_munged(current_user_ns(), current_egid())); 285 return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
286 } 286 }
287 287
288 #ifdef CONFIG_SYSVIPC 288 #ifdef CONFIG_SYSVIPC
289 COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, compat_ulong_t, second, 289 COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, compat_ulong_t, second,
290 compat_ulong_t, third, compat_uptr_t, ptr) 290 compat_ulong_t, third, compat_uptr_t, ptr)
291 { 291 {
292 if (call >> 16) /* hack for backward compatibility */ 292 if (call >> 16) /* hack for backward compatibility */
293 return -EINVAL; 293 return -EINVAL;
294 return compat_sys_ipc(call, first, second, third, ptr, third); 294 return compat_sys_ipc(call, first, second, third, ptr, third);
295 } 295 }
296 #endif 296 #endif
297 297
298 asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low) 298 asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
299 { 299 {
300 if ((int)high < 0) 300 if ((int)high < 0)
301 return -EINVAL; 301 return -EINVAL;
302 else 302 else
303 return sys_truncate(path, (high << 32) | low); 303 return sys_truncate(path, (high << 32) | low);
304 } 304 }
305 305
306 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low) 306 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
307 { 307 {
308 if ((int)high < 0) 308 if ((int)high < 0)
309 return -EINVAL; 309 return -EINVAL;
310 else 310 else
311 return sys_ftruncate(fd, (high << 32) | low); 311 return sys_ftruncate(fd, (high << 32) | low);
312 } 312 }
313 313
314 asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, 314 asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
315 size_t count, u32 poshi, u32 poslo) 315 size_t count, u32 poshi, u32 poslo)
316 { 316 {
317 if ((compat_ssize_t) count < 0) 317 if ((compat_ssize_t) count < 0)
318 return -EINVAL; 318 return -EINVAL;
319 return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); 319 return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
320 } 320 }
321 321
322 asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf, 322 asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
323 size_t count, u32 poshi, u32 poslo) 323 size_t count, u32 poshi, u32 poslo)
324 { 324 {
325 if ((compat_ssize_t) count < 0) 325 if ((compat_ssize_t) count < 0)
326 return -EINVAL; 326 return -EINVAL;
327 return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); 327 return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
328 } 328 }
329 329
330 asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count) 330 asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
331 { 331 {
332 return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count); 332 return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
333 } 333 }
334 334
335 struct stat64_emu31 { 335 struct stat64_emu31 {
336 unsigned long long st_dev; 336 unsigned long long st_dev;
337 unsigned int __pad1; 337 unsigned int __pad1;
338 #define STAT64_HAS_BROKEN_ST_INO 1 338 #define STAT64_HAS_BROKEN_ST_INO 1
339 u32 __st_ino; 339 u32 __st_ino;
340 unsigned int st_mode; 340 unsigned int st_mode;
341 unsigned int st_nlink; 341 unsigned int st_nlink;
342 u32 st_uid; 342 u32 st_uid;
343 u32 st_gid; 343 u32 st_gid;
344 unsigned long long st_rdev; 344 unsigned long long st_rdev;
345 unsigned int __pad3; 345 unsigned int __pad3;
346 long st_size; 346 long st_size;
347 u32 st_blksize; 347 u32 st_blksize;
348 unsigned char __pad4[4]; 348 unsigned char __pad4[4];
349 u32 __pad5; /* future possible st_blocks high bits */ 349 u32 __pad5; /* future possible st_blocks high bits */
350 u32 st_blocks; /* Number 512-byte blocks allocated. */ 350 u32 st_blocks; /* Number 512-byte blocks allocated. */
351 u32 st_atime; 351 u32 st_atime;
352 u32 __pad6; 352 u32 __pad6;
353 u32 st_mtime; 353 u32 st_mtime;
354 u32 __pad7; 354 u32 __pad7;
355 u32 st_ctime; 355 u32 st_ctime;
356 u32 __pad8; /* will be high 32 bits of ctime someday */ 356 u32 __pad8; /* will be high 32 bits of ctime someday */
357 unsigned long st_ino; 357 unsigned long st_ino;
358 }; 358 };
359 359
360 static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat) 360 static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat)
361 { 361 {
362 struct stat64_emu31 tmp; 362 struct stat64_emu31 tmp;
363 363
364 memset(&tmp, 0, sizeof(tmp)); 364 memset(&tmp, 0, sizeof(tmp));
365 365
366 tmp.st_dev = huge_encode_dev(stat->dev); 366 tmp.st_dev = huge_encode_dev(stat->dev);
367 tmp.st_ino = stat->ino; 367 tmp.st_ino = stat->ino;
368 tmp.__st_ino = (u32)stat->ino; 368 tmp.__st_ino = (u32)stat->ino;
369 tmp.st_mode = stat->mode; 369 tmp.st_mode = stat->mode;
370 tmp.st_nlink = (unsigned int)stat->nlink; 370 tmp.st_nlink = (unsigned int)stat->nlink;
371 tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid); 371 tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid);
372 tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid); 372 tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid);
373 tmp.st_rdev = huge_encode_dev(stat->rdev); 373 tmp.st_rdev = huge_encode_dev(stat->rdev);
374 tmp.st_size = stat->size; 374 tmp.st_size = stat->size;
375 tmp.st_blksize = (u32)stat->blksize; 375 tmp.st_blksize = (u32)stat->blksize;
376 tmp.st_blocks = (u32)stat->blocks; 376 tmp.st_blocks = (u32)stat->blocks;
377 tmp.st_atime = (u32)stat->atime.tv_sec; 377 tmp.st_atime = (u32)stat->atime.tv_sec;
378 tmp.st_mtime = (u32)stat->mtime.tv_sec; 378 tmp.st_mtime = (u32)stat->mtime.tv_sec;
379 tmp.st_ctime = (u32)stat->ctime.tv_sec; 379 tmp.st_ctime = (u32)stat->ctime.tv_sec;
380 380
381 return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 381 return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
382 } 382 }
383 383
384 asmlinkage long sys32_stat64(const char __user * filename, struct stat64_emu31 __user * statbuf) 384 asmlinkage long sys32_stat64(const char __user * filename, struct stat64_emu31 __user * statbuf)
385 { 385 {
386 struct kstat stat; 386 struct kstat stat;
387 int ret = vfs_stat(filename, &stat); 387 int ret = vfs_stat(filename, &stat);
388 if (!ret) 388 if (!ret)
389 ret = cp_stat64(statbuf, &stat); 389 ret = cp_stat64(statbuf, &stat);
390 return ret; 390 return ret;
391 } 391 }
392 392
393 asmlinkage long sys32_lstat64(const char __user * filename, struct stat64_emu31 __user * statbuf) 393 asmlinkage long sys32_lstat64(const char __user * filename, struct stat64_emu31 __user * statbuf)
394 { 394 {
395 struct kstat stat; 395 struct kstat stat;
396 int ret = vfs_lstat(filename, &stat); 396 int ret = vfs_lstat(filename, &stat);
397 if (!ret) 397 if (!ret)
398 ret = cp_stat64(statbuf, &stat); 398 ret = cp_stat64(statbuf, &stat);
399 return ret; 399 return ret;
400 } 400 }
401 401
402 asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf) 402 asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf)
403 { 403 {
404 struct kstat stat; 404 struct kstat stat;
405 int ret = vfs_fstat(fd, &stat); 405 int ret = vfs_fstat(fd, &stat);
406 if (!ret) 406 if (!ret)
407 ret = cp_stat64(statbuf, &stat); 407 ret = cp_stat64(statbuf, &stat);
408 return ret; 408 return ret;
409 } 409 }
410 410
411 asmlinkage long sys32_fstatat64(unsigned int dfd, const char __user *filename, 411 asmlinkage long sys32_fstatat64(unsigned int dfd, const char __user *filename,
412 struct stat64_emu31 __user* statbuf, int flag) 412 struct stat64_emu31 __user* statbuf, int flag)
413 { 413 {
414 struct kstat stat; 414 struct kstat stat;
415 int error; 415 int error;
416 416
417 error = vfs_fstatat(dfd, filename, &stat, flag); 417 error = vfs_fstatat(dfd, filename, &stat, flag);
418 if (error) 418 if (error)
419 return error; 419 return error;
420 return cp_stat64(statbuf, &stat); 420 return cp_stat64(statbuf, &stat);
421 } 421 }
422 422
423 /* 423 /*
424 * Linux/i386 didn't use to be able to handle more than 424 * Linux/i386 didn't use to be able to handle more than
425 * 4 system call parameters, so these system calls used a memory 425 * 4 system call parameters, so these system calls used a memory
426 * block for parameter passing.. 426 * block for parameter passing..
427 */ 427 */
428 428
429 struct mmap_arg_struct_emu31 { 429 struct mmap_arg_struct_emu31 {
430 compat_ulong_t addr; 430 compat_ulong_t addr;
431 compat_ulong_t len; 431 compat_ulong_t len;
432 compat_ulong_t prot; 432 compat_ulong_t prot;
433 compat_ulong_t flags; 433 compat_ulong_t flags;
434 compat_ulong_t fd; 434 compat_ulong_t fd;
435 compat_ulong_t offset; 435 compat_ulong_t offset;
436 }; 436 };
437 437
438 asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg) 438 asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
439 { 439 {
440 struct mmap_arg_struct_emu31 a; 440 struct mmap_arg_struct_emu31 a;
441 441
442 if (copy_from_user(&a, arg, sizeof(a))) 442 if (copy_from_user(&a, arg, sizeof(a)))
443 return -EFAULT; 443 return -EFAULT;
444 if (a.offset & ~PAGE_MASK) 444 if (a.offset & ~PAGE_MASK)
445 return -EINVAL; 445 return -EINVAL;
446 return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, 446 return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
447 a.offset >> PAGE_SHIFT); 447 a.offset >> PAGE_SHIFT);
448 } 448 }
449 449
450 asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) 450 asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
451 { 451 {
452 struct mmap_arg_struct_emu31 a; 452 struct mmap_arg_struct_emu31 a;
453 453
454 if (copy_from_user(&a, arg, sizeof(a))) 454 if (copy_from_user(&a, arg, sizeof(a)))
455 return -EFAULT; 455 return -EFAULT;
456 return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); 456 return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
457 } 457 }
458 458
459 asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count) 459 asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count)
460 { 460 {
461 if ((compat_ssize_t) count < 0) 461 if ((compat_ssize_t) count < 0)
462 return -EINVAL; 462 return -EINVAL;
463 463
464 return sys_read(fd, buf, count); 464 return sys_read(fd, buf, count);
465 } 465 }
466 466
467 asmlinkage long sys32_write(unsigned int fd, const char __user * buf, size_t count) 467 asmlinkage long sys32_write(unsigned int fd, const char __user * buf, size_t count)
468 { 468 {
469 if ((compat_ssize_t) count < 0) 469 if ((compat_ssize_t) count < 0)
470 return -EINVAL; 470 return -EINVAL;
471 471
472 return sys_write(fd, buf, count); 472 return sys_write(fd, buf, count);
473 } 473 }
474 474
475 /* 475 /*
476 * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. 476 * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64.
477 * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE} 477 * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE}
478 * because the 31 bit values differ from the 64 bit values. 478 * because the 31 bit values differ from the 64 bit values.
479 */ 479 */
480 480
481 asmlinkage long 481 asmlinkage long
482 sys32_fadvise64(int fd, loff_t offset, size_t len, int advise) 482 sys32_fadvise64(int fd, loff_t offset, size_t len, int advise)
483 { 483 {
484 if (advise == 4) 484 if (advise == 4)
485 advise = POSIX_FADV_DONTNEED; 485 advise = POSIX_FADV_DONTNEED;
486 else if (advise == 5) 486 else if (advise == 5)
487 advise = POSIX_FADV_NOREUSE; 487 advise = POSIX_FADV_NOREUSE;
488 return sys_fadvise64(fd, offset, len, advise); 488 return sys_fadvise64(fd, offset, len, advise);
489 } 489 }
490 490
491 struct fadvise64_64_args { 491 struct fadvise64_64_args {
492 int fd; 492 int fd;
493 long long offset; 493 long long offset;
494 long long len; 494 long long len;
495 int advice; 495 int advice;
496 }; 496 };
497 497
498 asmlinkage long 498 asmlinkage long
499 sys32_fadvise64_64(struct fadvise64_64_args __user *args) 499 sys32_fadvise64_64(struct fadvise64_64_args __user *args)
500 { 500 {
501 struct fadvise64_64_args a; 501 struct fadvise64_64_args a;
502 502
503 if ( copy_from_user(&a, args, sizeof(a)) ) 503 if ( copy_from_user(&a, args, sizeof(a)) )
504 return -EFAULT; 504 return -EFAULT;
505 if (a.advice == 4) 505 if (a.advice == 4)
506 a.advice = POSIX_FADV_DONTNEED; 506 a.advice = POSIX_FADV_DONTNEED;
507 else if (a.advice == 5) 507 else if (a.advice == 5)
508 a.advice = POSIX_FADV_NOREUSE; 508 a.advice = POSIX_FADV_NOREUSE;
509 return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); 509 return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);
510 } 510 }
511 511
include/linux/cred.h
1 /* Credentials management - see Documentation/security/credentials.txt 1 /* Credentials management - see Documentation/security/credentials.txt
2 * 2 *
3 * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence 7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version. 9 * 2 of the Licence, or (at your option) any later version.
10 */ 10 */
11 11
12 #ifndef _LINUX_CRED_H 12 #ifndef _LINUX_CRED_H
13 #define _LINUX_CRED_H 13 #define _LINUX_CRED_H
14 14
15 #include <linux/capability.h> 15 #include <linux/capability.h>
16 #include <linux/init.h> 16 #include <linux/init.h>
17 #include <linux/key.h> 17 #include <linux/key.h>
18 #include <linux/selinux.h> 18 #include <linux/selinux.h>
19 #include <linux/atomic.h> 19 #include <linux/atomic.h>
20 #include <linux/uidgid.h> 20 #include <linux/uidgid.h>
21 21
22 struct user_struct; 22 struct user_struct;
23 struct cred; 23 struct cred;
24 struct inode; 24 struct inode;
25 25
26 /* 26 /*
27 * COW Supplementary groups list 27 * COW Supplementary groups list
28 */ 28 */
29 #define NGROUPS_SMALL 32 29 #define NGROUPS_SMALL 32
30 #define NGROUPS_PER_BLOCK ((unsigned int)(PAGE_SIZE / sizeof(kgid_t))) 30 #define NGROUPS_PER_BLOCK ((unsigned int)(PAGE_SIZE / sizeof(kgid_t)))
31 31
32 struct group_info { 32 struct group_info {
33 atomic_t usage; 33 atomic_t usage;
34 int ngroups; 34 int ngroups;
35 int nblocks; 35 int nblocks;
36 kgid_t small_block[NGROUPS_SMALL]; 36 kgid_t small_block[NGROUPS_SMALL];
37 kgid_t *blocks[0]; 37 kgid_t *blocks[0];
38 }; 38 };
39 39
40 /** 40 /**
41 * get_group_info - Get a reference to a group info structure 41 * get_group_info - Get a reference to a group info structure
42 * @group_info: The group info to reference 42 * @group_info: The group info to reference
43 * 43 *
44 * This gets a reference to a set of supplementary groups. 44 * This gets a reference to a set of supplementary groups.
45 * 45 *
46 * If the caller is accessing a task's credentials, they must hold the RCU read 46 * If the caller is accessing a task's credentials, they must hold the RCU read
47 * lock when reading. 47 * lock when reading.
48 */ 48 */
49 static inline struct group_info *get_group_info(struct group_info *gi) 49 static inline struct group_info *get_group_info(struct group_info *gi)
50 { 50 {
51 atomic_inc(&gi->usage); 51 atomic_inc(&gi->usage);
52 return gi; 52 return gi;
53 } 53 }
54 54
55 /** 55 /**
56 * put_group_info - Release a reference to a group info structure 56 * put_group_info - Release a reference to a group info structure
57 * @group_info: The group info to release 57 * @group_info: The group info to release
58 */ 58 */
59 #define put_group_info(group_info) \ 59 #define put_group_info(group_info) \
60 do { \ 60 do { \
61 if (atomic_dec_and_test(&(group_info)->usage)) \ 61 if (atomic_dec_and_test(&(group_info)->usage)) \
62 groups_free(group_info); \ 62 groups_free(group_info); \
63 } while (0) 63 } while (0)
64 64
65 extern struct group_info *groups_alloc(int); 65 extern struct group_info *groups_alloc(int);
66 extern struct group_info init_groups; 66 extern struct group_info init_groups;
67 extern void groups_free(struct group_info *); 67 extern void groups_free(struct group_info *);
68 extern int set_current_groups(struct group_info *); 68 extern int set_current_groups(struct group_info *);
69 extern int set_groups(struct cred *, struct group_info *); 69 extern int set_groups(struct cred *, struct group_info *);
70 extern int groups_search(const struct group_info *, kgid_t); 70 extern int groups_search(const struct group_info *, kgid_t);
71 extern bool may_setgroups(void);
71 72
72 /* access the groups "array" with this macro */ 73 /* access the groups "array" with this macro */
73 #define GROUP_AT(gi, i) \ 74 #define GROUP_AT(gi, i) \
74 ((gi)->blocks[(i) / NGROUPS_PER_BLOCK][(i) % NGROUPS_PER_BLOCK]) 75 ((gi)->blocks[(i) / NGROUPS_PER_BLOCK][(i) % NGROUPS_PER_BLOCK])
75 76
76 extern int in_group_p(kgid_t); 77 extern int in_group_p(kgid_t);
77 extern int in_egroup_p(kgid_t); 78 extern int in_egroup_p(kgid_t);
78 79
79 /* 80 /*
80 * The security context of a task 81 * The security context of a task
81 * 82 *
82 * The parts of the context break down into two categories: 83 * The parts of the context break down into two categories:
83 * 84 *
84 * (1) The objective context of a task. These parts are used when some other 85 * (1) The objective context of a task. These parts are used when some other
85 * task is attempting to affect this one. 86 * task is attempting to affect this one.
86 * 87 *
87 * (2) The subjective context. These details are used when the task is acting 88 * (2) The subjective context. These details are used when the task is acting
88 * upon another object, be that a file, a task, a key or whatever. 89 * upon another object, be that a file, a task, a key or whatever.
89 * 90 *
90 * Note that some members of this structure belong to both categories - the 91 * Note that some members of this structure belong to both categories - the
91 * LSM security pointer for instance. 92 * LSM security pointer for instance.
92 * 93 *
93 * A task has two security pointers. task->real_cred points to the objective 94 * A task has two security pointers. task->real_cred points to the objective
94 * context that defines that task's actual details. The objective part of this 95 * context that defines that task's actual details. The objective part of this
95 * context is used whenever that task is acted upon. 96 * context is used whenever that task is acted upon.
96 * 97 *
97 * task->cred points to the subjective context that defines the details of how 98 * task->cred points to the subjective context that defines the details of how
98 * that task is going to act upon another object. This may be overridden 99 * that task is going to act upon another object. This may be overridden
99 * temporarily to point to another security context, but normally points to the 100 * temporarily to point to another security context, but normally points to the
100 * same context as task->real_cred. 101 * same context as task->real_cred.
101 */ 102 */
102 struct cred { 103 struct cred {
103 atomic_t usage; 104 atomic_t usage;
104 #ifdef CONFIG_DEBUG_CREDENTIALS 105 #ifdef CONFIG_DEBUG_CREDENTIALS
105 atomic_t subscribers; /* number of processes subscribed */ 106 atomic_t subscribers; /* number of processes subscribed */
106 void *put_addr; 107 void *put_addr;
107 unsigned magic; 108 unsigned magic;
108 #define CRED_MAGIC 0x43736564 109 #define CRED_MAGIC 0x43736564
109 #define CRED_MAGIC_DEAD 0x44656144 110 #define CRED_MAGIC_DEAD 0x44656144
110 #endif 111 #endif
111 kuid_t uid; /* real UID of the task */ 112 kuid_t uid; /* real UID of the task */
112 kgid_t gid; /* real GID of the task */ 113 kgid_t gid; /* real GID of the task */
113 kuid_t suid; /* saved UID of the task */ 114 kuid_t suid; /* saved UID of the task */
114 kgid_t sgid; /* saved GID of the task */ 115 kgid_t sgid; /* saved GID of the task */
115 kuid_t euid; /* effective UID of the task */ 116 kuid_t euid; /* effective UID of the task */
116 kgid_t egid; /* effective GID of the task */ 117 kgid_t egid; /* effective GID of the task */
117 kuid_t fsuid; /* UID for VFS ops */ 118 kuid_t fsuid; /* UID for VFS ops */
118 kgid_t fsgid; /* GID for VFS ops */ 119 kgid_t fsgid; /* GID for VFS ops */
119 unsigned securebits; /* SUID-less security management */ 120 unsigned securebits; /* SUID-less security management */
120 kernel_cap_t cap_inheritable; /* caps our children can inherit */ 121 kernel_cap_t cap_inheritable; /* caps our children can inherit */
121 kernel_cap_t cap_permitted; /* caps we're permitted */ 122 kernel_cap_t cap_permitted; /* caps we're permitted */
122 kernel_cap_t cap_effective; /* caps we can actually use */ 123 kernel_cap_t cap_effective; /* caps we can actually use */
123 kernel_cap_t cap_bset; /* capability bounding set */ 124 kernel_cap_t cap_bset; /* capability bounding set */
124 #ifdef CONFIG_KEYS 125 #ifdef CONFIG_KEYS
125 unsigned char jit_keyring; /* default keyring to attach requested 126 unsigned char jit_keyring; /* default keyring to attach requested
126 * keys to */ 127 * keys to */
127 struct key __rcu *session_keyring; /* keyring inherited over fork */ 128 struct key __rcu *session_keyring; /* keyring inherited over fork */
128 struct key *process_keyring; /* keyring private to this process */ 129 struct key *process_keyring; /* keyring private to this process */
129 struct key *thread_keyring; /* keyring private to this thread */ 130 struct key *thread_keyring; /* keyring private to this thread */
130 struct key *request_key_auth; /* assumed request_key authority */ 131 struct key *request_key_auth; /* assumed request_key authority */
131 #endif 132 #endif
132 #ifdef CONFIG_SECURITY 133 #ifdef CONFIG_SECURITY
133 void *security; /* subjective LSM security */ 134 void *security; /* subjective LSM security */
134 #endif 135 #endif
135 struct user_struct *user; /* real user ID subscription */ 136 struct user_struct *user; /* real user ID subscription */
136 struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */ 137 struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
137 struct group_info *group_info; /* supplementary groups for euid/fsgid */ 138 struct group_info *group_info; /* supplementary groups for euid/fsgid */
138 struct rcu_head rcu; /* RCU deletion hook */ 139 struct rcu_head rcu; /* RCU deletion hook */
139 }; 140 };
140 141
141 extern void __put_cred(struct cred *); 142 extern void __put_cred(struct cred *);
142 extern void exit_creds(struct task_struct *); 143 extern void exit_creds(struct task_struct *);
143 extern int copy_creds(struct task_struct *, unsigned long); 144 extern int copy_creds(struct task_struct *, unsigned long);
144 extern const struct cred *get_task_cred(struct task_struct *); 145 extern const struct cred *get_task_cred(struct task_struct *);
145 extern struct cred *cred_alloc_blank(void); 146 extern struct cred *cred_alloc_blank(void);
146 extern struct cred *prepare_creds(void); 147 extern struct cred *prepare_creds(void);
147 extern struct cred *prepare_exec_creds(void); 148 extern struct cred *prepare_exec_creds(void);
148 extern int commit_creds(struct cred *); 149 extern int commit_creds(struct cred *);
149 extern void abort_creds(struct cred *); 150 extern void abort_creds(struct cred *);
150 extern const struct cred *override_creds(const struct cred *); 151 extern const struct cred *override_creds(const struct cred *);
151 extern void revert_creds(const struct cred *); 152 extern void revert_creds(const struct cred *);
152 extern struct cred *prepare_kernel_cred(struct task_struct *); 153 extern struct cred *prepare_kernel_cred(struct task_struct *);
153 extern int change_create_files_as(struct cred *, struct inode *); 154 extern int change_create_files_as(struct cred *, struct inode *);
154 extern int set_security_override(struct cred *, u32); 155 extern int set_security_override(struct cred *, u32);
155 extern int set_security_override_from_ctx(struct cred *, const char *); 156 extern int set_security_override_from_ctx(struct cred *, const char *);
156 extern int set_create_files_as(struct cred *, struct inode *); 157 extern int set_create_files_as(struct cred *, struct inode *);
157 extern void __init cred_init(void); 158 extern void __init cred_init(void);
158 159
159 /* 160 /*
160 * check for validity of credentials 161 * check for validity of credentials
161 */ 162 */
162 #ifdef CONFIG_DEBUG_CREDENTIALS 163 #ifdef CONFIG_DEBUG_CREDENTIALS
163 extern void __invalid_creds(const struct cred *, const char *, unsigned); 164 extern void __invalid_creds(const struct cred *, const char *, unsigned);
164 extern void __validate_process_creds(struct task_struct *, 165 extern void __validate_process_creds(struct task_struct *,
165 const char *, unsigned); 166 const char *, unsigned);
166 167
167 extern bool creds_are_invalid(const struct cred *cred); 168 extern bool creds_are_invalid(const struct cred *cred);
168 169
169 static inline void __validate_creds(const struct cred *cred, 170 static inline void __validate_creds(const struct cred *cred,
170 const char *file, unsigned line) 171 const char *file, unsigned line)
171 { 172 {
172 if (unlikely(creds_are_invalid(cred))) 173 if (unlikely(creds_are_invalid(cred)))
173 __invalid_creds(cred, file, line); 174 __invalid_creds(cred, file, line);
174 } 175 }
175 176
176 #define validate_creds(cred) \ 177 #define validate_creds(cred) \
177 do { \ 178 do { \
178 __validate_creds((cred), __FILE__, __LINE__); \ 179 __validate_creds((cred), __FILE__, __LINE__); \
179 } while(0) 180 } while(0)
180 181
181 #define validate_process_creds() \ 182 #define validate_process_creds() \
182 do { \ 183 do { \
183 __validate_process_creds(current, __FILE__, __LINE__); \ 184 __validate_process_creds(current, __FILE__, __LINE__); \
184 } while(0) 185 } while(0)
185 186
186 extern void validate_creds_for_do_exit(struct task_struct *); 187 extern void validate_creds_for_do_exit(struct task_struct *);
187 #else 188 #else
188 static inline void validate_creds(const struct cred *cred) 189 static inline void validate_creds(const struct cred *cred)
189 { 190 {
190 } 191 }
191 static inline void validate_creds_for_do_exit(struct task_struct *tsk) 192 static inline void validate_creds_for_do_exit(struct task_struct *tsk)
192 { 193 {
193 } 194 }
194 static inline void validate_process_creds(void) 195 static inline void validate_process_creds(void)
195 { 196 {
196 } 197 }
197 #endif 198 #endif
198 199
199 /** 200 /**
200 * get_new_cred - Get a reference on a new set of credentials 201 * get_new_cred - Get a reference on a new set of credentials
201 * @cred: The new credentials to reference 202 * @cred: The new credentials to reference
202 * 203 *
203 * Get a reference on the specified set of new credentials. The caller must 204 * Get a reference on the specified set of new credentials. The caller must
204 * release the reference. 205 * release the reference.
205 */ 206 */
206 static inline struct cred *get_new_cred(struct cred *cred) 207 static inline struct cred *get_new_cred(struct cred *cred)
207 { 208 {
208 atomic_inc(&cred->usage); 209 atomic_inc(&cred->usage);
209 return cred; 210 return cred;
210 } 211 }
211 212
212 /** 213 /**
213 * get_cred - Get a reference on a set of credentials 214 * get_cred - Get a reference on a set of credentials
214 * @cred: The credentials to reference 215 * @cred: The credentials to reference
215 * 216 *
216 * Get a reference on the specified set of credentials. The caller must 217 * Get a reference on the specified set of credentials. The caller must
217 * release the reference. 218 * release the reference.
218 * 219 *
219 * This is used to deal with a committed set of credentials. Although the 220 * This is used to deal with a committed set of credentials. Although the
220 * pointer is const, this will temporarily discard the const and increment the 221 * pointer is const, this will temporarily discard the const and increment the
221 * usage count. The purpose of this is to attempt to catch at compile time the 222 * usage count. The purpose of this is to attempt to catch at compile time the
222 * accidental alteration of a set of credentials that should be considered 223 * accidental alteration of a set of credentials that should be considered
223 * immutable. 224 * immutable.
224 */ 225 */
225 static inline const struct cred *get_cred(const struct cred *cred) 226 static inline const struct cred *get_cred(const struct cred *cred)
226 { 227 {
227 struct cred *nonconst_cred = (struct cred *) cred; 228 struct cred *nonconst_cred = (struct cred *) cred;
228 validate_creds(cred); 229 validate_creds(cred);
229 return get_new_cred(nonconst_cred); 230 return get_new_cred(nonconst_cred);
230 } 231 }
231 232
232 /** 233 /**
233 * put_cred - Release a reference to a set of credentials 234 * put_cred - Release a reference to a set of credentials
234 * @cred: The credentials to release 235 * @cred: The credentials to release
235 * 236 *
236 * Release a reference to a set of credentials, deleting them when the last ref 237 * Release a reference to a set of credentials, deleting them when the last ref
237 * is released. 238 * is released.
238 * 239 *
239 * This takes a const pointer to a set of credentials because the credentials 240 * This takes a const pointer to a set of credentials because the credentials
240 * on task_struct are attached by const pointers to prevent accidental 241 * on task_struct are attached by const pointers to prevent accidental
241 * alteration of otherwise immutable credential sets. 242 * alteration of otherwise immutable credential sets.
242 */ 243 */
243 static inline void put_cred(const struct cred *_cred) 244 static inline void put_cred(const struct cred *_cred)
244 { 245 {
245 struct cred *cred = (struct cred *) _cred; 246 struct cred *cred = (struct cred *) _cred;
246 247
247 validate_creds(cred); 248 validate_creds(cred);
248 if (atomic_dec_and_test(&(cred)->usage)) 249 if (atomic_dec_and_test(&(cred)->usage))
249 __put_cred(cred); 250 __put_cred(cred);
250 } 251 }
251 252
252 /** 253 /**
253 * current_cred - Access the current task's subjective credentials 254 * current_cred - Access the current task's subjective credentials
254 * 255 *
255 * Access the subjective credentials of the current task. RCU-safe, 256 * Access the subjective credentials of the current task. RCU-safe,
256 * since nobody else can modify it. 257 * since nobody else can modify it.
257 */ 258 */
258 #define current_cred() \ 259 #define current_cred() \
259 rcu_dereference_protected(current->cred, 1) 260 rcu_dereference_protected(current->cred, 1)
260 261
261 /** 262 /**
262 * __task_cred - Access a task's objective credentials 263 * __task_cred - Access a task's objective credentials
263 * @task: The task to query 264 * @task: The task to query
264 * 265 *
265 * Access the objective credentials of a task. The caller must hold the RCU 266 * Access the objective credentials of a task. The caller must hold the RCU
266 * readlock. 267 * readlock.
267 * 268 *
268 * The result of this function should not be passed directly to get_cred(); 269 * The result of this function should not be passed directly to get_cred();
269 * rather get_task_cred() should be used instead. 270 * rather get_task_cred() should be used instead.
270 */ 271 */
271 #define __task_cred(task) \ 272 #define __task_cred(task) \
272 rcu_dereference((task)->real_cred) 273 rcu_dereference((task)->real_cred)
273 274
274 /** 275 /**
275 * get_current_cred - Get the current task's subjective credentials 276 * get_current_cred - Get the current task's subjective credentials
276 * 277 *
277 * Get the subjective credentials of the current task, pinning them so that 278 * Get the subjective credentials of the current task, pinning them so that
278 * they can't go away. Accessing the current task's credentials directly is 279 * they can't go away. Accessing the current task's credentials directly is
279 * not permitted. 280 * not permitted.
280 */ 281 */
281 #define get_current_cred() \ 282 #define get_current_cred() \
282 (get_cred(current_cred())) 283 (get_cred(current_cred()))
283 284
284 /** 285 /**
285 * get_current_user - Get the current task's user_struct 286 * get_current_user - Get the current task's user_struct
286 * 287 *
287 * Get the user record of the current task, pinning it so that it can't go 288 * Get the user record of the current task, pinning it so that it can't go
288 * away. 289 * away.
289 */ 290 */
290 #define get_current_user() \ 291 #define get_current_user() \
291 ({ \ 292 ({ \
292 struct user_struct *__u; \ 293 struct user_struct *__u; \
293 const struct cred *__cred; \ 294 const struct cred *__cred; \
294 __cred = current_cred(); \ 295 __cred = current_cred(); \
295 __u = get_uid(__cred->user); \ 296 __u = get_uid(__cred->user); \
296 __u; \ 297 __u; \
297 }) 298 })
298 299
299 /** 300 /**
300 * get_current_groups - Get the current task's supplementary group list 301 * get_current_groups - Get the current task's supplementary group list
301 * 302 *
302 * Get the supplementary group list of the current task, pinning it so that it 303 * Get the supplementary group list of the current task, pinning it so that it
303 * can't go away. 304 * can't go away.
304 */ 305 */
305 #define get_current_groups() \ 306 #define get_current_groups() \
306 ({ \ 307 ({ \
307 struct group_info *__groups; \ 308 struct group_info *__groups; \
308 const struct cred *__cred; \ 309 const struct cred *__cred; \
309 __cred = current_cred(); \ 310 __cred = current_cred(); \
310 __groups = get_group_info(__cred->group_info); \ 311 __groups = get_group_info(__cred->group_info); \
311 __groups; \ 312 __groups; \
312 }) 313 })
313 314
314 #define task_cred_xxx(task, xxx) \ 315 #define task_cred_xxx(task, xxx) \
315 ({ \ 316 ({ \
316 __typeof__(((struct cred *)NULL)->xxx) ___val; \ 317 __typeof__(((struct cred *)NULL)->xxx) ___val; \
317 rcu_read_lock(); \ 318 rcu_read_lock(); \
318 ___val = __task_cred((task))->xxx; \ 319 ___val = __task_cred((task))->xxx; \
319 rcu_read_unlock(); \ 320 rcu_read_unlock(); \
320 ___val; \ 321 ___val; \
321 }) 322 })
322 323
323 #define task_uid(task) (task_cred_xxx((task), uid)) 324 #define task_uid(task) (task_cred_xxx((task), uid))
324 #define task_euid(task) (task_cred_xxx((task), euid)) 325 #define task_euid(task) (task_cred_xxx((task), euid))
325 326
326 #define current_cred_xxx(xxx) \ 327 #define current_cred_xxx(xxx) \
327 ({ \ 328 ({ \
328 current_cred()->xxx; \ 329 current_cred()->xxx; \
329 }) 330 })
330 331
331 #define current_uid() (current_cred_xxx(uid)) 332 #define current_uid() (current_cred_xxx(uid))
332 #define current_gid() (current_cred_xxx(gid)) 333 #define current_gid() (current_cred_xxx(gid))
333 #define current_euid() (current_cred_xxx(euid)) 334 #define current_euid() (current_cred_xxx(euid))
334 #define current_egid() (current_cred_xxx(egid)) 335 #define current_egid() (current_cred_xxx(egid))
335 #define current_suid() (current_cred_xxx(suid)) 336 #define current_suid() (current_cred_xxx(suid))
336 #define current_sgid() (current_cred_xxx(sgid)) 337 #define current_sgid() (current_cred_xxx(sgid))
337 #define current_fsuid() (current_cred_xxx(fsuid)) 338 #define current_fsuid() (current_cred_xxx(fsuid))
338 #define current_fsgid() (current_cred_xxx(fsgid)) 339 #define current_fsgid() (current_cred_xxx(fsgid))
339 #define current_cap() (current_cred_xxx(cap_effective)) 340 #define current_cap() (current_cred_xxx(cap_effective))
340 #define current_user() (current_cred_xxx(user)) 341 #define current_user() (current_cred_xxx(user))
341 #define current_security() (current_cred_xxx(security)) 342 #define current_security() (current_cred_xxx(security))
342 343
343 extern struct user_namespace init_user_ns; 344 extern struct user_namespace init_user_ns;
344 #ifdef CONFIG_USER_NS 345 #ifdef CONFIG_USER_NS
345 #define current_user_ns() (current_cred_xxx(user_ns)) 346 #define current_user_ns() (current_cred_xxx(user_ns))
346 #else 347 #else
347 #define current_user_ns() (&init_user_ns) 348 #define current_user_ns() (&init_user_ns)
348 #endif 349 #endif
349 350
350 351
351 #define current_uid_gid(_uid, _gid) \ 352 #define current_uid_gid(_uid, _gid) \
352 do { \ 353 do { \
353 const struct cred *__cred; \ 354 const struct cred *__cred; \
354 __cred = current_cred(); \ 355 __cred = current_cred(); \
355 *(_uid) = __cred->uid; \ 356 *(_uid) = __cred->uid; \
356 *(_gid) = __cred->gid; \ 357 *(_gid) = __cred->gid; \
357 } while(0) 358 } while(0)
358 359
359 #define current_euid_egid(_euid, _egid) \ 360 #define current_euid_egid(_euid, _egid) \
360 do { \ 361 do { \
361 const struct cred *__cred; \ 362 const struct cred *__cred; \
362 __cred = current_cred(); \ 363 __cred = current_cred(); \
363 *(_euid) = __cred->euid; \ 364 *(_euid) = __cred->euid; \
364 *(_egid) = __cred->egid; \ 365 *(_egid) = __cred->egid; \
365 } while(0) 366 } while(0)
366 367
367 #define current_fsuid_fsgid(_fsuid, _fsgid) \ 368 #define current_fsuid_fsgid(_fsuid, _fsgid) \
368 do { \ 369 do { \
369 const struct cred *__cred; \ 370 const struct cred *__cred; \
370 __cred = current_cred(); \ 371 __cred = current_cred(); \
371 *(_fsuid) = __cred->fsuid; \ 372 *(_fsuid) = __cred->fsuid; \
372 *(_fsgid) = __cred->fsgid; \ 373 *(_fsgid) = __cred->fsgid; \
373 } while(0) 374 } while(0)
374 375
375 #endif /* _LINUX_CRED_H */ 376 #endif /* _LINUX_CRED_H */
376 377
1 /* 1 /*
2 * Supplementary group IDs 2 * Supplementary group IDs
3 */ 3 */
4 #include <linux/cred.h> 4 #include <linux/cred.h>
5 #include <linux/export.h> 5 #include <linux/export.h>
6 #include <linux/slab.h> 6 #include <linux/slab.h>
7 #include <linux/security.h> 7 #include <linux/security.h>
8 #include <linux/syscalls.h> 8 #include <linux/syscalls.h>
9 #include <asm/uaccess.h> 9 #include <asm/uaccess.h>
10 10
11 /* init to 2 - one for init_task, one to ensure it is never freed */ 11 /* init to 2 - one for init_task, one to ensure it is never freed */
12 struct group_info init_groups = { .usage = ATOMIC_INIT(2) }; 12 struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
13 13
14 struct group_info *groups_alloc(int gidsetsize) 14 struct group_info *groups_alloc(int gidsetsize)
15 { 15 {
16 struct group_info *group_info; 16 struct group_info *group_info;
17 int nblocks; 17 int nblocks;
18 int i; 18 int i;
19 19
20 nblocks = (gidsetsize + NGROUPS_PER_BLOCK - 1) / NGROUPS_PER_BLOCK; 20 nblocks = (gidsetsize + NGROUPS_PER_BLOCK - 1) / NGROUPS_PER_BLOCK;
21 /* Make sure we always allocate at least one indirect block pointer */ 21 /* Make sure we always allocate at least one indirect block pointer */
22 nblocks = nblocks ? : 1; 22 nblocks = nblocks ? : 1;
23 group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *), GFP_USER); 23 group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *), GFP_USER);
24 if (!group_info) 24 if (!group_info)
25 return NULL; 25 return NULL;
26 group_info->ngroups = gidsetsize; 26 group_info->ngroups = gidsetsize;
27 group_info->nblocks = nblocks; 27 group_info->nblocks = nblocks;
28 atomic_set(&group_info->usage, 1); 28 atomic_set(&group_info->usage, 1);
29 29
30 if (gidsetsize <= NGROUPS_SMALL) 30 if (gidsetsize <= NGROUPS_SMALL)
31 group_info->blocks[0] = group_info->small_block; 31 group_info->blocks[0] = group_info->small_block;
32 else { 32 else {
33 for (i = 0; i < nblocks; i++) { 33 for (i = 0; i < nblocks; i++) {
34 kgid_t *b; 34 kgid_t *b;
35 b = (void *)__get_free_page(GFP_USER); 35 b = (void *)__get_free_page(GFP_USER);
36 if (!b) 36 if (!b)
37 goto out_undo_partial_alloc; 37 goto out_undo_partial_alloc;
38 group_info->blocks[i] = b; 38 group_info->blocks[i] = b;
39 } 39 }
40 } 40 }
41 return group_info; 41 return group_info;
42 42
43 out_undo_partial_alloc: 43 out_undo_partial_alloc:
44 while (--i >= 0) { 44 while (--i >= 0) {
45 free_page((unsigned long)group_info->blocks[i]); 45 free_page((unsigned long)group_info->blocks[i]);
46 } 46 }
47 kfree(group_info); 47 kfree(group_info);
48 return NULL; 48 return NULL;
49 } 49 }
50 50
51 EXPORT_SYMBOL(groups_alloc); 51 EXPORT_SYMBOL(groups_alloc);
52 52
53 void groups_free(struct group_info *group_info) 53 void groups_free(struct group_info *group_info)
54 { 54 {
55 if (group_info->blocks[0] != group_info->small_block) { 55 if (group_info->blocks[0] != group_info->small_block) {
56 int i; 56 int i;
57 for (i = 0; i < group_info->nblocks; i++) 57 for (i = 0; i < group_info->nblocks; i++)
58 free_page((unsigned long)group_info->blocks[i]); 58 free_page((unsigned long)group_info->blocks[i]);
59 } 59 }
60 kfree(group_info); 60 kfree(group_info);
61 } 61 }
62 62
63 EXPORT_SYMBOL(groups_free); 63 EXPORT_SYMBOL(groups_free);
64 64
65 /* export the group_info to a user-space array */ 65 /* export the group_info to a user-space array */
66 static int groups_to_user(gid_t __user *grouplist, 66 static int groups_to_user(gid_t __user *grouplist,
67 const struct group_info *group_info) 67 const struct group_info *group_info)
68 { 68 {
69 struct user_namespace *user_ns = current_user_ns(); 69 struct user_namespace *user_ns = current_user_ns();
70 int i; 70 int i;
71 unsigned int count = group_info->ngroups; 71 unsigned int count = group_info->ngroups;
72 72
73 for (i = 0; i < count; i++) { 73 for (i = 0; i < count; i++) {
74 gid_t gid; 74 gid_t gid;
75 gid = from_kgid_munged(user_ns, GROUP_AT(group_info, i)); 75 gid = from_kgid_munged(user_ns, GROUP_AT(group_info, i));
76 if (put_user(gid, grouplist+i)) 76 if (put_user(gid, grouplist+i))
77 return -EFAULT; 77 return -EFAULT;
78 } 78 }
79 return 0; 79 return 0;
80 } 80 }
81 81
82 /* fill a group_info from a user-space array - it must be allocated already */ 82 /* fill a group_info from a user-space array - it must be allocated already */
83 static int groups_from_user(struct group_info *group_info, 83 static int groups_from_user(struct group_info *group_info,
84 gid_t __user *grouplist) 84 gid_t __user *grouplist)
85 { 85 {
86 struct user_namespace *user_ns = current_user_ns(); 86 struct user_namespace *user_ns = current_user_ns();
87 int i; 87 int i;
88 unsigned int count = group_info->ngroups; 88 unsigned int count = group_info->ngroups;
89 89
90 for (i = 0; i < count; i++) { 90 for (i = 0; i < count; i++) {
91 gid_t gid; 91 gid_t gid;
92 kgid_t kgid; 92 kgid_t kgid;
93 if (get_user(gid, grouplist+i)) 93 if (get_user(gid, grouplist+i))
94 return -EFAULT; 94 return -EFAULT;
95 95
96 kgid = make_kgid(user_ns, gid); 96 kgid = make_kgid(user_ns, gid);
97 if (!gid_valid(kgid)) 97 if (!gid_valid(kgid))
98 return -EINVAL; 98 return -EINVAL;
99 99
100 GROUP_AT(group_info, i) = kgid; 100 GROUP_AT(group_info, i) = kgid;
101 } 101 }
102 return 0; 102 return 0;
103 } 103 }
104 104
105 /* a simple Shell sort */ 105 /* a simple Shell sort */
106 static void groups_sort(struct group_info *group_info) 106 static void groups_sort(struct group_info *group_info)
107 { 107 {
108 int base, max, stride; 108 int base, max, stride;
109 int gidsetsize = group_info->ngroups; 109 int gidsetsize = group_info->ngroups;
110 110
111 for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1) 111 for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
112 ; /* nothing */ 112 ; /* nothing */
113 stride /= 3; 113 stride /= 3;
114 114
115 while (stride) { 115 while (stride) {
116 max = gidsetsize - stride; 116 max = gidsetsize - stride;
117 for (base = 0; base < max; base++) { 117 for (base = 0; base < max; base++) {
118 int left = base; 118 int left = base;
119 int right = left + stride; 119 int right = left + stride;
120 kgid_t tmp = GROUP_AT(group_info, right); 120 kgid_t tmp = GROUP_AT(group_info, right);
121 121
122 while (left >= 0 && gid_gt(GROUP_AT(group_info, left), tmp)) { 122 while (left >= 0 && gid_gt(GROUP_AT(group_info, left), tmp)) {
123 GROUP_AT(group_info, right) = 123 GROUP_AT(group_info, right) =
124 GROUP_AT(group_info, left); 124 GROUP_AT(group_info, left);
125 right = left; 125 right = left;
126 left -= stride; 126 left -= stride;
127 } 127 }
128 GROUP_AT(group_info, right) = tmp; 128 GROUP_AT(group_info, right) = tmp;
129 } 129 }
130 stride /= 3; 130 stride /= 3;
131 } 131 }
132 } 132 }
133 133
134 /* a simple bsearch */ 134 /* a simple bsearch */
135 int groups_search(const struct group_info *group_info, kgid_t grp) 135 int groups_search(const struct group_info *group_info, kgid_t grp)
136 { 136 {
137 unsigned int left, right; 137 unsigned int left, right;
138 138
139 if (!group_info) 139 if (!group_info)
140 return 0; 140 return 0;
141 141
142 left = 0; 142 left = 0;
143 right = group_info->ngroups; 143 right = group_info->ngroups;
144 while (left < right) { 144 while (left < right) {
145 unsigned int mid = (left+right)/2; 145 unsigned int mid = (left+right)/2;
146 if (gid_gt(grp, GROUP_AT(group_info, mid))) 146 if (gid_gt(grp, GROUP_AT(group_info, mid)))
147 left = mid + 1; 147 left = mid + 1;
148 else if (gid_lt(grp, GROUP_AT(group_info, mid))) 148 else if (gid_lt(grp, GROUP_AT(group_info, mid)))
149 right = mid; 149 right = mid;
150 else 150 else
151 return 1; 151 return 1;
152 } 152 }
153 return 0; 153 return 0;
154 } 154 }
155 155
156 /** 156 /**
157 * set_groups - Change a group subscription in a set of credentials 157 * set_groups - Change a group subscription in a set of credentials
158 * @new: The newly prepared set of credentials to alter 158 * @new: The newly prepared set of credentials to alter
159 * @group_info: The group list to install 159 * @group_info: The group list to install
160 * 160 *
161 * Validate a group subscription and, if valid, insert it into a set 161 * Validate a group subscription and, if valid, insert it into a set
162 * of credentials. 162 * of credentials.
163 */ 163 */
164 int set_groups(struct cred *new, struct group_info *group_info) 164 int set_groups(struct cred *new, struct group_info *group_info)
165 { 165 {
166 put_group_info(new->group_info); 166 put_group_info(new->group_info);
167 groups_sort(group_info); 167 groups_sort(group_info);
168 get_group_info(group_info); 168 get_group_info(group_info);
169 new->group_info = group_info; 169 new->group_info = group_info;
170 return 0; 170 return 0;
171 } 171 }
172 172
173 EXPORT_SYMBOL(set_groups); 173 EXPORT_SYMBOL(set_groups);
174 174
175 /** 175 /**
176 * set_current_groups - Change current's group subscription 176 * set_current_groups - Change current's group subscription
177 * @group_info: The group list to impose 177 * @group_info: The group list to impose
178 * 178 *
179 * Validate a group subscription and, if valid, impose it upon current's task 179 * Validate a group subscription and, if valid, impose it upon current's task
180 * security record. 180 * security record.
181 */ 181 */
182 int set_current_groups(struct group_info *group_info) 182 int set_current_groups(struct group_info *group_info)
183 { 183 {
184 struct cred *new; 184 struct cred *new;
185 int ret; 185 int ret;
186 186
187 new = prepare_creds(); 187 new = prepare_creds();
188 if (!new) 188 if (!new)
189 return -ENOMEM; 189 return -ENOMEM;
190 190
191 ret = set_groups(new, group_info); 191 ret = set_groups(new, group_info);
192 if (ret < 0) { 192 if (ret < 0) {
193 abort_creds(new); 193 abort_creds(new);
194 return ret; 194 return ret;
195 } 195 }
196 196
197 return commit_creds(new); 197 return commit_creds(new);
198 } 198 }
199 199
200 EXPORT_SYMBOL(set_current_groups); 200 EXPORT_SYMBOL(set_current_groups);
201 201
202 SYSCALL_DEFINE2(getgroups, int, gidsetsize, gid_t __user *, grouplist) 202 SYSCALL_DEFINE2(getgroups, int, gidsetsize, gid_t __user *, grouplist)
203 { 203 {
204 const struct cred *cred = current_cred(); 204 const struct cred *cred = current_cred();
205 int i; 205 int i;
206 206
207 if (gidsetsize < 0) 207 if (gidsetsize < 0)
208 return -EINVAL; 208 return -EINVAL;
209 209
210 /* no need to grab task_lock here; it cannot change */ 210 /* no need to grab task_lock here; it cannot change */
211 i = cred->group_info->ngroups; 211 i = cred->group_info->ngroups;
212 if (gidsetsize) { 212 if (gidsetsize) {
213 if (i > gidsetsize) { 213 if (i > gidsetsize) {
214 i = -EINVAL; 214 i = -EINVAL;
215 goto out; 215 goto out;
216 } 216 }
217 if (groups_to_user(grouplist, cred->group_info)) { 217 if (groups_to_user(grouplist, cred->group_info)) {
218 i = -EFAULT; 218 i = -EFAULT;
219 goto out; 219 goto out;
220 } 220 }
221 } 221 }
222 out: 222 out:
223 return i; 223 return i;
224 } 224 }
225 225
226 bool may_setgroups(void)
227 {
228 struct user_namespace *user_ns = current_user_ns();
229
230 return ns_capable(user_ns, CAP_SETGID);
231 }
232
226 /* 233 /*
227 * SMP: Our groups are copy-on-write. We can set them safely 234 * SMP: Our groups are copy-on-write. We can set them safely
228 * without another task interfering. 235 * without another task interfering.
229 */ 236 */
230 237
231 SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist) 238 SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist)
232 { 239 {
233 struct group_info *group_info; 240 struct group_info *group_info;
234 int retval; 241 int retval;
235 242
236 if (!ns_capable(current_user_ns(), CAP_SETGID)) 243 if (!may_setgroups())
237 return -EPERM; 244 return -EPERM;
238 if ((unsigned)gidsetsize > NGROUPS_MAX) 245 if ((unsigned)gidsetsize > NGROUPS_MAX)
239 return -EINVAL; 246 return -EINVAL;
240 247
241 group_info = groups_alloc(gidsetsize); 248 group_info = groups_alloc(gidsetsize);
242 if (!group_info) 249 if (!group_info)
243 return -ENOMEM; 250 return -ENOMEM;
244 retval = groups_from_user(group_info, grouplist); 251 retval = groups_from_user(group_info, grouplist);
245 if (retval) { 252 if (retval) {
246 put_group_info(group_info); 253 put_group_info(group_info);
247 return retval; 254 return retval;
248 } 255 }
249 256
250 retval = set_current_groups(group_info); 257 retval = set_current_groups(group_info);
251 put_group_info(group_info); 258 put_group_info(group_info);
252 259
253 return retval; 260 return retval;
254 } 261 }
255 262
256 /* 263 /*
257 * Check whether we're fsgid/egid or in the supplemental group.. 264 * Check whether we're fsgid/egid or in the supplemental group..
258 */ 265 */
259 int in_group_p(kgid_t grp) 266 int in_group_p(kgid_t grp)
260 { 267 {
261 const struct cred *cred = current_cred(); 268 const struct cred *cred = current_cred();
262 int retval = 1; 269 int retval = 1;
263 270
264 if (!gid_eq(grp, cred->fsgid)) 271 if (!gid_eq(grp, cred->fsgid))
265 retval = groups_search(cred->group_info, grp); 272 retval = groups_search(cred->group_info, grp);
266 return retval; 273 return retval;
267 } 274 }
268 275
269 EXPORT_SYMBOL(in_group_p); 276 EXPORT_SYMBOL(in_group_p);
270 277
271 int in_egroup_p(kgid_t grp) 278 int in_egroup_p(kgid_t grp)
272 { 279 {
273 const struct cred *cred = current_cred(); 280 const struct cred *cred = current_cred();
274 int retval = 1; 281 int retval = 1;
275 282
276 if (!gid_eq(grp, cred->egid)) 283 if (!gid_eq(grp, cred->egid))
277 retval = groups_search(cred->group_info, grp); 284 retval = groups_search(cred->group_info, grp);
278 return retval; 285 return retval;
279 } 286 }
280 287
281 EXPORT_SYMBOL(in_egroup_p); 288 EXPORT_SYMBOL(in_egroup_p);
282 289
1 /* 1 /*
2 * Wrapper functions for 16bit uid back compatibility. All nicely tied 2 * Wrapper functions for 16bit uid back compatibility. All nicely tied
3 * together in the faint hope we can take the out in five years time. 3 * together in the faint hope we can take the out in five years time.
4 */ 4 */
5 5
6 #include <linux/mm.h> 6 #include <linux/mm.h>
7 #include <linux/mman.h> 7 #include <linux/mman.h>
8 #include <linux/notifier.h> 8 #include <linux/notifier.h>
9 #include <linux/reboot.h> 9 #include <linux/reboot.h>
10 #include <linux/prctl.h> 10 #include <linux/prctl.h>
11 #include <linux/capability.h> 11 #include <linux/capability.h>
12 #include <linux/init.h> 12 #include <linux/init.h>
13 #include <linux/highuid.h> 13 #include <linux/highuid.h>
14 #include <linux/security.h> 14 #include <linux/security.h>
15 #include <linux/syscalls.h> 15 #include <linux/syscalls.h>
16 16
17 #include <asm/uaccess.h> 17 #include <asm/uaccess.h>
18 18
19 SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group) 19 SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
20 { 20 {
21 return sys_chown(filename, low2highuid(user), low2highgid(group)); 21 return sys_chown(filename, low2highuid(user), low2highgid(group));
22 } 22 }
23 23
24 SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group) 24 SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
25 { 25 {
26 return sys_lchown(filename, low2highuid(user), low2highgid(group)); 26 return sys_lchown(filename, low2highuid(user), low2highgid(group));
27 } 27 }
28 28
29 SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group) 29 SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group)
30 { 30 {
31 return sys_fchown(fd, low2highuid(user), low2highgid(group)); 31 return sys_fchown(fd, low2highuid(user), low2highgid(group));
32 } 32 }
33 33
34 SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid) 34 SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid)
35 { 35 {
36 return sys_setregid(low2highgid(rgid), low2highgid(egid)); 36 return sys_setregid(low2highgid(rgid), low2highgid(egid));
37 } 37 }
38 38
39 SYSCALL_DEFINE1(setgid16, old_gid_t, gid) 39 SYSCALL_DEFINE1(setgid16, old_gid_t, gid)
40 { 40 {
41 return sys_setgid(low2highgid(gid)); 41 return sys_setgid(low2highgid(gid));
42 } 42 }
43 43
44 SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid) 44 SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid)
45 { 45 {
46 return sys_setreuid(low2highuid(ruid), low2highuid(euid)); 46 return sys_setreuid(low2highuid(ruid), low2highuid(euid));
47 } 47 }
48 48
49 SYSCALL_DEFINE1(setuid16, old_uid_t, uid) 49 SYSCALL_DEFINE1(setuid16, old_uid_t, uid)
50 { 50 {
51 return sys_setuid(low2highuid(uid)); 51 return sys_setuid(low2highuid(uid));
52 } 52 }
53 53
54 SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid) 54 SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid)
55 { 55 {
56 return sys_setresuid(low2highuid(ruid), low2highuid(euid), 56 return sys_setresuid(low2highuid(ruid), low2highuid(euid),
57 low2highuid(suid)); 57 low2highuid(suid));
58 } 58 }
59 59
60 SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp) 60 SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp)
61 { 61 {
62 const struct cred *cred = current_cred(); 62 const struct cred *cred = current_cred();
63 int retval; 63 int retval;
64 old_uid_t ruid, euid, suid; 64 old_uid_t ruid, euid, suid;
65 65
66 ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid)); 66 ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid));
67 euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid)); 67 euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid));
68 suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid)); 68 suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid));
69 69
70 if (!(retval = put_user(ruid, ruidp)) && 70 if (!(retval = put_user(ruid, ruidp)) &&
71 !(retval = put_user(euid, euidp))) 71 !(retval = put_user(euid, euidp)))
72 retval = put_user(suid, suidp); 72 retval = put_user(suid, suidp);
73 73
74 return retval; 74 return retval;
75 } 75 }
76 76
77 SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid) 77 SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid)
78 { 78 {
79 return sys_setresgid(low2highgid(rgid), low2highgid(egid), 79 return sys_setresgid(low2highgid(rgid), low2highgid(egid),
80 low2highgid(sgid)); 80 low2highgid(sgid));
81 } 81 }
82 82
83 83
84 SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egidp, old_gid_t __user *, sgidp) 84 SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egidp, old_gid_t __user *, sgidp)
85 { 85 {
86 const struct cred *cred = current_cred(); 86 const struct cred *cred = current_cred();
87 int retval; 87 int retval;
88 old_gid_t rgid, egid, sgid; 88 old_gid_t rgid, egid, sgid;
89 89
90 rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid)); 90 rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid));
91 egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid)); 91 egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid));
92 sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid)); 92 sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid));
93 93
94 if (!(retval = put_user(rgid, rgidp)) && 94 if (!(retval = put_user(rgid, rgidp)) &&
95 !(retval = put_user(egid, egidp))) 95 !(retval = put_user(egid, egidp)))
96 retval = put_user(sgid, sgidp); 96 retval = put_user(sgid, sgidp);
97 97
98 return retval; 98 return retval;
99 } 99 }
100 100
101 SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid) 101 SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid)
102 { 102 {
103 return sys_setfsuid(low2highuid(uid)); 103 return sys_setfsuid(low2highuid(uid));
104 } 104 }
105 105
106 SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid) 106 SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid)
107 { 107 {
108 return sys_setfsgid(low2highgid(gid)); 108 return sys_setfsgid(low2highgid(gid));
109 } 109 }
110 110
111 static int groups16_to_user(old_gid_t __user *grouplist, 111 static int groups16_to_user(old_gid_t __user *grouplist,
112 struct group_info *group_info) 112 struct group_info *group_info)
113 { 113 {
114 struct user_namespace *user_ns = current_user_ns(); 114 struct user_namespace *user_ns = current_user_ns();
115 int i; 115 int i;
116 old_gid_t group; 116 old_gid_t group;
117 kgid_t kgid; 117 kgid_t kgid;
118 118
119 for (i = 0; i < group_info->ngroups; i++) { 119 for (i = 0; i < group_info->ngroups; i++) {
120 kgid = GROUP_AT(group_info, i); 120 kgid = GROUP_AT(group_info, i);
121 group = high2lowgid(from_kgid_munged(user_ns, kgid)); 121 group = high2lowgid(from_kgid_munged(user_ns, kgid));
122 if (put_user(group, grouplist+i)) 122 if (put_user(group, grouplist+i))
123 return -EFAULT; 123 return -EFAULT;
124 } 124 }
125 125
126 return 0; 126 return 0;
127 } 127 }
128 128
129 static int groups16_from_user(struct group_info *group_info, 129 static int groups16_from_user(struct group_info *group_info,
130 old_gid_t __user *grouplist) 130 old_gid_t __user *grouplist)
131 { 131 {
132 struct user_namespace *user_ns = current_user_ns(); 132 struct user_namespace *user_ns = current_user_ns();
133 int i; 133 int i;
134 old_gid_t group; 134 old_gid_t group;
135 kgid_t kgid; 135 kgid_t kgid;
136 136
137 for (i = 0; i < group_info->ngroups; i++) { 137 for (i = 0; i < group_info->ngroups; i++) {
138 if (get_user(group, grouplist+i)) 138 if (get_user(group, grouplist+i))
139 return -EFAULT; 139 return -EFAULT;
140 140
141 kgid = make_kgid(user_ns, low2highgid(group)); 141 kgid = make_kgid(user_ns, low2highgid(group));
142 if (!gid_valid(kgid)) 142 if (!gid_valid(kgid))
143 return -EINVAL; 143 return -EINVAL;
144 144
145 GROUP_AT(group_info, i) = kgid; 145 GROUP_AT(group_info, i) = kgid;
146 } 146 }
147 147
148 return 0; 148 return 0;
149 } 149 }
150 150
151 SYSCALL_DEFINE2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist) 151 SYSCALL_DEFINE2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
152 { 152 {
153 const struct cred *cred = current_cred(); 153 const struct cred *cred = current_cred();
154 int i; 154 int i;
155 155
156 if (gidsetsize < 0) 156 if (gidsetsize < 0)
157 return -EINVAL; 157 return -EINVAL;
158 158
159 i = cred->group_info->ngroups; 159 i = cred->group_info->ngroups;
160 if (gidsetsize) { 160 if (gidsetsize) {
161 if (i > gidsetsize) { 161 if (i > gidsetsize) {
162 i = -EINVAL; 162 i = -EINVAL;
163 goto out; 163 goto out;
164 } 164 }
165 if (groups16_to_user(grouplist, cred->group_info)) { 165 if (groups16_to_user(grouplist, cred->group_info)) {
166 i = -EFAULT; 166 i = -EFAULT;
167 goto out; 167 goto out;
168 } 168 }
169 } 169 }
170 out: 170 out:
171 return i; 171 return i;
172 } 172 }
173 173
174 SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) 174 SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
175 { 175 {
176 struct group_info *group_info; 176 struct group_info *group_info;
177 int retval; 177 int retval;
178 178
179 if (!ns_capable(current_user_ns(), CAP_SETGID)) 179 if (!may_setgroups())
180 return -EPERM; 180 return -EPERM;
181 if ((unsigned)gidsetsize > NGROUPS_MAX) 181 if ((unsigned)gidsetsize > NGROUPS_MAX)
182 return -EINVAL; 182 return -EINVAL;
183 183
184 group_info = groups_alloc(gidsetsize); 184 group_info = groups_alloc(gidsetsize);
185 if (!group_info) 185 if (!group_info)
186 return -ENOMEM; 186 return -ENOMEM;
187 retval = groups16_from_user(group_info, grouplist); 187 retval = groups16_from_user(group_info, grouplist);
188 if (retval) { 188 if (retval) {
189 put_group_info(group_info); 189 put_group_info(group_info);
190 return retval; 190 return retval;
191 } 191 }
192 192
193 retval = set_current_groups(group_info); 193 retval = set_current_groups(group_info);
194 put_group_info(group_info); 194 put_group_info(group_info);
195 195
196 return retval; 196 return retval;
197 } 197 }
198 198
199 SYSCALL_DEFINE0(getuid16) 199 SYSCALL_DEFINE0(getuid16)
200 { 200 {
201 return high2lowuid(from_kuid_munged(current_user_ns(), current_uid())); 201 return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
202 } 202 }
203 203
204 SYSCALL_DEFINE0(geteuid16) 204 SYSCALL_DEFINE0(geteuid16)
205 { 205 {
206 return high2lowuid(from_kuid_munged(current_user_ns(), current_euid())); 206 return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
207 } 207 }
208 208
209 SYSCALL_DEFINE0(getgid16) 209 SYSCALL_DEFINE0(getgid16)
210 { 210 {
211 return high2lowgid(from_kgid_munged(current_user_ns(), current_gid())); 211 return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));
212 } 212 }
213 213
214 SYSCALL_DEFINE0(getegid16) 214 SYSCALL_DEFINE0(getegid16)
215 { 215 {
216 return high2lowgid(from_kgid_munged(current_user_ns(), current_egid())); 216 return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
217 } 217 }
218 218