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