]> git.saurik.com Git - apple/xnu.git/blob - bsd/sys/persona.h
xnu-6153.81.5.tar.gz
[apple/xnu.git] / bsd / sys / persona.h
1 /*
2 * Copyright (c) 2015 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 #ifndef _SYS_PERSONA_H_
29 #define _SYS_PERSONA_H_
30
31 #ifdef PRIVATE
32 #include <sys/param.h>
33
34 enum {
35 PERSONA_INVALID = 0,
36 PERSONA_GUEST = 1,
37 PERSONA_MANAGED = 2,
38 PERSONA_PRIV = 3,
39 PERSONA_SYSTEM = 4,
40 PERSONA_DEFAULT = 5,
41 PERSONA_SYSTEM_PROXY = 6,
42 PERSONA_SYS_EXT = 7,
43 PERSONA_ENTERPRISE = 8,
44
45 PERSONA_TYPE_MAX = PERSONA_ENTERPRISE,
46 };
47
48 #define PERSONA_ID_NONE ((uid_t)-1)
49
50 struct kpersona_info {
51 uint32_t persona_info_version;
52
53 uid_t persona_id; /* overlaps with UID */
54 int persona_type;
55 gid_t persona_gid;
56 uint32_t persona_ngroups;
57 gid_t persona_groups[NGROUPS];
58 uid_t persona_gmuid;
59 char persona_name[MAXLOGNAME + 1];
60
61 /* TODO: MAC policies?! */
62 };
63
64 #define PERSONA_INFO_V1 1
65 #define PERSONA_INFO_V1_SIZE (sizeof(struct kpersona_info))
66
67
68 #define PERSONA_OP_ALLOC 1
69 #define PERSONA_OP_PALLOC 2
70 #define PERSONA_OP_DEALLOC 3
71 #define PERSONA_OP_GET 4
72 #define PERSONA_OP_INFO 5
73 #define PERSONA_OP_PIDINFO 6
74 #define PERSONA_OP_FIND 7
75 #define PERSONA_OP_GETPATH 8
76 #define PERSONA_OP_FIND_BY_TYPE 9
77
78 #define PERSONA_MGMT_ENTITLEMENT "com.apple.private.persona-mgmt"
79
80 #ifndef KERNEL
81 /*
82 * user space persona interface
83 */
84
85 /*
86 * kpersona_alloc: Allocate a new in-kernel persona
87 *
88 * Parameters:
89 * info: Pointer to persona info structure describing the
90 * attributes of the persona to create / allocate.
91 *
92 * id: output: set to the ID of the created persona
93 *
94 * Note:
95 * The 'persona_id' field of the 'info' parameter is ignored.
96 *
97 * Return:
98 * != 0: ERROR
99 * == 0: Success
100 */
101 int kpersona_alloc(struct kpersona_info *info, uid_t *id);
102
103 /*
104 * kpersona_palloc: Allocate a new in-kernel persona with a directory
105 * pathname
106 *
107 * Parameters:
108 * info: Pointer to persona info structure describing the
109 * attributes of the persona to create / allocate.
110 *
111 * path: Pointer to directory name that stores persona specific
112 * data. Assumes path buffer length = MAXPATHLEN and is a
113 * null-terminated string.
114 *
115 * id: output: set to the ID of the created persona
116 *
117 * Note:
118 * The 'persona_id' field of the 'info' parameter is ignored.
119 *
120 * Return:
121 * != 0: ERROR
122 * == 0: Success
123 */
124 int kpersona_palloc(struct kpersona_info *info, uid_t *id, char path[MAXPATHLEN]);
125
126 /*
127 * kpersona_dealloc: delete / destroy an in-kernel persona
128 *
129 * Parameters:
130 * id: the ID of the persona to destroy
131 *
132 * Return:
133 * < 0: ERROR
134 * 0: Success
135 */
136 int kpersona_dealloc(uid_t id);
137
138 /*
139 * kpersona_get: retrieve the persona with which the current thread is running
140 *
141 * To find the proc's persona id use kpersona_pidinfo
142 *
143 * Parameters:
144 * id: output: will be filled with the persona id from the voucher adopted
145 * on the current thread. If that voucher contains no persona information
146 * or there is no such voucher, then it defaults to the proc's persona id.
147 *
148 * Return:
149 * < 0: Thread is not running under any persona
150 * 0: Success (uuid is filled with running persona UUID)
151 */
152 int kpersona_get(uid_t *id);
153
154 /*
155 * kpersona_get_path: retrieve the given persona's path
156 *
157 * Parameters:
158 * id: ID of the persona
159 *
160 * path: output: filled in with path on success.
161 * Assumes path buffer length = MAXPATHLEN
162 *
163 * Return:
164 * < 0: Error
165 * 0: Success
166 */
167 int kpersona_getpath(uid_t id, char path[MAXPATHLEN]);
168
169 /*
170 * kpersona_info: gather info about the given persona
171 *
172 * Parameters:
173 * id: ID of the persona to investigate
174 * If set to 0, it uses persona id from the voucher adopted on the current
175 * thread. If that voucher contains no persona information or there is no
176 * such voucher, then it defaults to the proc's persona id.
177 *
178 * info: output: filled in with persona attributes on success.
179 *
180 * Return:
181 * < 0: ERROR
182 * 0: Success
183 */
184 int kpersona_info(uid_t id, struct kpersona_info *info);
185
186 /*
187 * kpersona_pidinfo: gather persona info about the given PID
188 *
189 * Parameters:
190 * pid: PID of the process whose persona info we're to return
191 *
192 * info: output: filled in with persona attributes on success.
193 *
194 * Return:
195 * < 0: ERROR
196 * 0: Success
197 */
198 int kpersona_pidinfo(pid_t pid, struct kpersona_info *info);
199
200 /*
201 * kpersona_find: lookup the kernel's UUID of a persona
202 *
203 * Parameters:
204 * name: Local login name of the persona.
205 * Set this to NULL to find personas by 'uid'.
206 *
207 * uid: UID of the persona.
208 * Set this to -1 to find personas by 'name'
209 *
210 * id: output: the ID(s) matching the input parameters
211 * This can be NULL
212 *
213 * idlen: input - size of 'id' buffer (in number of IDs)
214 * output - the total required size of the 'id' buffer
215 * (in number of IDs) - may be larger than input size
216 * Note:
217 * At least one of 'name' or 'uid' must be set.
218 *
219 * Return:
220 * < 0: ERROR
221 * >= 0: The number of IDs found to match the input parameters
222 */
223 int kpersona_find(const char *name, uid_t uid, uid_t *id, size_t *idlen);
224
225 /*
226 * kpersona_find_by_type: lookup the persona ids by type
227 *
228 * Parameters:
229 * persona_type: Type of persona id (see enum)
230 *
231 * id: output: the ID(s) matching the input parameters
232 * This can be NULL
233 *
234 * idlen: input - size of 'id' buffer (in number of IDs)
235 * output - the total required size of the 'id' buffer
236 * (in number of IDs) - may be larger than input size
237 * Return:
238 * < 0: ERROR
239 * >= 0: The number of IDs found to match the input parameters
240 */
241 int kpersona_find_by_type(int persona_type, uid_t *id, size_t *idlen);
242 #endif /* !KERNEL */
243
244 #ifdef KERNEL_PRIVATE
245 /* XNU + kext private interface */
246 #include <sys/cdefs.h>
247 #include <sys/kauth.h>
248 #include <libkern/libkern.h>
249 #include <os/refcnt.h>
250
251 #ifdef PERSONA_DEBUG
252 #include <os/log.h>
253 #define persona_dbg(fmt, ...) \
254 os_log(OS_LOG_DEFAULT, "[%4d] %s: " fmt "\n", \
255 current_proc() ? current_proc()->p_pid : -1, \
256 __func__, ## __VA_ARGS__)
257 #else
258 #define persona_dbg(fmt, ...) do { } while (0)
259 #endif
260
261 /*
262 * Persona
263 */
264 #ifdef XNU_KERNEL_PRIVATE
265 /* only XNU proper needs to see the persona structure */
266 struct persona {
267 os_refcnt_t pna_refcount;
268 int32_t pna_valid;
269
270 uid_t pna_id;
271 int pna_type;
272 char pna_login[MAXLOGNAME + 1];
273 char *pna_path;
274
275 kauth_cred_t pna_cred;
276 uid_t pna_pgid;
277
278 int pna_cred_locked; /* set upon first adoption */
279
280 LIST_ENTRY(persona) pna_list;
281
282 /* this could go away if we used a coalition */
283 LIST_HEAD(, proc) pna_members;
284
285 lck_mtx_t pna_lock;
286
287 /*
288 * We can add things here such as PID maps, UID maps, etc.
289 */
290 #ifdef PERSONA_DEBUG
291 char pna_desc[128];
292 #endif
293 };
294
295 #define persona_lock(persona) lck_mtx_lock(&(persona)->pna_lock)
296 #define persona_unlock(persona) lck_mtx_unlock(&(persona)->pna_lock)
297 #define persona_try_lock(persona) lck_mtx_try_lock(&(persona)->pna_lock)
298
299 #define persona_lock_assert_held(persona) \
300 LCK_MTX_ASSERT(&(persona)->pna_lock, LCK_MTX_ASSERT_OWNED)
301
302 #ifdef PERSONA_DEBUG
303 static inline const char *
304 persona_desc(struct persona *persona, int locked)
305 {
306 if (!persona) {
307 return "<none>";
308 }
309
310 if (persona->pna_desc[0] != 0) {
311 return persona->pna_desc;
312 }
313
314 if (!locked) {
315 persona_lock(persona);
316 }
317 if (persona->pna_desc[0] != 0) {
318 goto out_unlock;
319 }
320
321 char *p = &persona->pna_desc[0];
322 char *end = p + sizeof(persona->pna_desc) - 1;
323
324 *end = 0;
325 p += scnprintf(p, end - p, "%s/%d:%d",
326 persona->pna_login,
327 kauth_cred_getuid(persona->pna_cred),
328 kauth_cred_getgid(persona->pna_cred));
329
330 if (p <= end) {
331 *p = 0;
332 }
333 out_unlock:
334 if (!locked) {
335 persona_unlock(persona);
336 }
337
338 return persona->pna_desc;
339 }
340 #else /* !PERSONA_DEBUG */
341 static inline const char *
342 persona_desc(struct persona *persona, int locked)
343 {
344 (void)persona;
345 (void)locked;
346 return "<persona>";
347 }
348 #endif
349
350 #else /* !XNU_KERNEL_PRIVATE */
351 /* kexts should only see an opaque persona structure */
352 struct persona;
353 #endif
354
355 __BEGIN_DECLS
356
357 #ifndef _KAUTH_CRED_T
358 #define _KAUTH_CRED_T
359 typedef struct ucred *kauth_cred_t;
360 #endif /* !_KAUTH_CRED_T */
361
362 /* returns the persona ID for the given pesona structure */
363 uid_t persona_get_id(struct persona *persona);
364
365 /* returns the type of the persona (see enum above: PERSONA_GUEST, etc.) */
366 int persona_get_type(struct persona *persona);
367
368 /* returns ref on kauth_cred_t that must be dropped via kauth_cred_unref() */
369 kauth_cred_t persona_get_cred(struct persona *persona);
370
371 /* returns a reference that must be released with persona_put() */
372 struct persona *persona_lookup(uid_t id);
373
374 /*
375 * Search for personas based on name or uid
376 *
377 * Parameters:
378 * name: Local login name of the persona.
379 * Set this to NULL to find personas by 'uid'.
380 *
381 * uid: UID of the persona.
382 * Set this to -1 to find personas by 'name'
383 *
384 * persona: output - array of persona pointers. Each non-NULL value
385 * must* be released with persona_put. This can be NULL.
386 *
387 * plen: input - size of 'persona' buffer (in number of pointers)
388 * output - the total required size of the 'persona' buffer (could be larger than input value)
389 *
390 * Return:
391 * 0: Success
392 * != 0: failure (BSD errno value ESRCH or EINVAL)
393 */
394 int persona_find(const char *login, uid_t uid,
395 struct persona **persona, size_t *plen);
396
397 /* returns a reference that must be released with persona_put() */
398 struct persona *persona_proc_get(pid_t pid);
399
400 /* returns a reference to the persona tied to the current thread (also uses adopted voucher) */
401 struct persona *current_persona_get(void);
402
403 /* get a reference to a persona structure */
404 struct persona *persona_get(struct persona *persona);
405
406 /* release a reference to a persona structure */
407 void persona_put(struct persona *persona);
408
409 /*
410 * Search for personas of a given type, 'persona_type'.
411 *
412 * Parameters:
413 * persona_type: Type of persona (see enum)
414 *
415 * persona: output - array of persona pointers. Each non-NULL value
416 * must* be released with persona_put. This can be NULL.
417 *
418 * plen: input - size of 'persona' buffer (in number of pointers)
419 * output - the total required size of the 'persona' buffer (could be larger than input value)
420 *
421 * Return:
422 * 0: Success
423 * != 0: failure (BSD errno value ESRCH or EINVAL)
424 */
425 int persona_find_by_type(int persona_type, struct persona **persona,
426 size_t *plen);
427
428 #ifdef XNU_KERNEL_PRIVATE
429
430 #if CONFIG_PERSONAS
431 #include <sys/proc_internal.h>
432
433 /*
434 * In-kernel persona API
435 */
436 extern uint32_t g_max_personas;
437
438 void personas_bootstrap(void);
439
440 struct persona *persona_alloc(uid_t id, const char *login,
441 int type, char *path, int *error);
442
443 int persona_init_begin(struct persona *persona);
444 void persona_init_end(struct persona *persona, int error);
445
446 struct persona *persona_lookup_and_invalidate(uid_t id);
447 int persona_verify_and_set_uniqueness(struct persona *persona);
448 boolean_t persona_is_unique(struct persona *persona);
449
450 static inline int
451 proc_has_persona(proc_t p)
452 {
453 if (p && p->p_persona) {
454 return 1;
455 }
456 return 0;
457 }
458
459 static inline uid_t
460 persona_id_from_proc(proc_t p)
461 {
462 if (p && p->p_persona) {
463 return p->p_persona->pna_id;
464 }
465 return PERSONA_ID_NONE;
466 }
467
468 int persona_proc_inherit(proc_t child, proc_t parent);
469
470 int persona_proc_adopt_id(proc_t p, uid_t id,
471 kauth_cred_t auth_override);
472 int persona_proc_adopt(proc_t p, struct persona *persona,
473 kauth_cred_t auth_override);
474 int persona_proc_drop(proc_t p);
475
476 int persona_set_cred(struct persona *persona, kauth_cred_t cred);
477 int persona_set_cred_from_proc(struct persona *persona, proc_t proc);
478
479 uid_t persona_get_uid(struct persona *persona);
480
481 int persona_set_gid(struct persona *persona, gid_t gid);
482 gid_t persona_get_gid(struct persona *persona);
483
484 int persona_set_groups(struct persona *persona, gid_t *groups, unsigned ngroups, uid_t gmuid);
485 int persona_get_groups(struct persona *persona, unsigned *ngroups, gid_t *groups, unsigned groups_sz);
486
487 uid_t persona_get_gmuid(struct persona *persona);
488
489 int persona_get_login(struct persona *persona, char login[MAXLOGNAME + 1]);
490
491 /* returns a reference that must be released with persona_put() */
492 struct persona *persona_proc_get(pid_t pid);
493
494 int persona_find_all(const char *login, uid_t uid, int persona_type,
495 struct persona **persona, size_t *plen);
496
497 #else /* !CONFIG_PERSONAS */
498
499 static inline int
500 proc_has_persona(__unused proc_t p)
501 {
502 return 0;
503 }
504
505 static inline uid_t
506 persona_id_from_proc(__unused proc_t p)
507 {
508 return PERSONA_ID_NONE;
509 }
510
511 #endif /* CONFIG_PERSONAS */
512 #endif /* XNU_KERNEL_PRIVATE */
513 __END_DECLS
514
515 #endif /* KERNEL_PRIVATE */
516
517 #endif /* PRIVATE */
518 #endif /* _SYS_PERSONA_H_ */