]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_persona.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / kern / kern_persona.c
CommitLineData
490019cf 1/*
f427ee49 2 * Copyright (c) 2015-2020 Apple Inc. All rights reserved.
490019cf
A
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
490019cf
A
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.
0a7de745 14 *
490019cf
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
490019cf
A
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.
0a7de745 25 *
490019cf
A
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#include <sys/kernel.h>
29#include <sys/kernel_types.h>
30#include <sys/persona.h>
cb323159 31#include <pexpert/pexpert.h>
490019cf
A
32
33#if CONFIG_PERSONAS
cb323159
A
34#include <machine/atomic.h>
35
490019cf
A
36#include <kern/assert.h>
37#include <kern/simple_lock.h>
38#include <kern/task.h>
39#include <kern/zalloc.h>
cb323159
A
40#include <mach/thread_act.h>
41#include <kern/thread.h>
490019cf
A
42
43#include <sys/param.h>
44#include <sys/proc_internal.h>
45#include <sys/kauth.h>
46#include <sys/proc_info.h>
47#include <sys/resourcevar.h>
48
d9a64523 49#include <os/log.h>
490019cf 50#define pna_err(fmt, ...) \
d9a64523 51 os_log_error(OS_LOG_DEFAULT, "ERROR: " fmt, ## __VA_ARGS__)
490019cf
A
52
53#define MAX_PERSONAS 512
54
55#define TEMP_PERSONA_ID 499
56
57#define FIRST_PERSONA_ID 501
58#define PERSONA_ID_STEP 10
59
d9a64523
A
60#define PERSONA_ALLOC_TOKEN (0x7a0000ae)
61#define PERSONA_INIT_TOKEN (0x7500005e)
490019cf 62#define PERSONA_MAGIC (0x0aa55aa0)
d9a64523 63#define persona_initialized(p) ((p)->pna_valid == PERSONA_MAGIC || (p)->pna_valid == PERSONA_INIT_TOKEN)
490019cf
A
64#define persona_valid(p) ((p)->pna_valid == PERSONA_MAGIC)
65#define persona_mkinvalid(p) ((p)->pna_valid = ~(PERSONA_MAGIC))
66
67static LIST_HEAD(personalist, persona) all_personas;
68static uint32_t g_total_personas;
f427ee49 69const uint32_t g_max_personas = MAX_PERSONAS;
cb323159
A
70struct persona *system_persona = NULL;
71struct persona *proxy_system_persona = NULL;
f427ee49 72#if !defined(XNU_TARGET_OS_OSX)
cb323159
A
73int unique_persona = 1;
74#else
75int unique_persona = 0;
76#endif
490019cf
A
77
78static uid_t g_next_persona_id;
79
f427ee49
A
80LCK_GRP_DECLARE(persona_lck_grp, "personas");
81LCK_MTX_DECLARE(all_personas_lock, &persona_lck_grp);
490019cf 82
d9a64523
A
83os_refgrp_decl(static, persona_refgrp, "persona", NULL);
84
f427ee49 85static ZONE_DECLARE(persona_zone, "personas", sizeof(struct persona), ZC_ZFREE_CLEARMEM);
490019cf
A
86
87kauth_cred_t g_default_persona_cred;
f427ee49 88extern struct auditinfo_addr * const audit_default_aia_p;
490019cf
A
89
90#define lock_personas() lck_mtx_lock(&all_personas_lock)
91#define unlock_personas() lck_mtx_unlock(&all_personas_lock)
92
490019cf
A
93extern void mach_kauth_cred_uthread_update(void);
94
cb323159
A
95extern kern_return_t bank_get_bank_ledger_thread_group_and_persona(void *voucher,
96 void *bankledger, void **banktg, uint32_t *persona_id);
97void
98ipc_voucher_release(void *voucher);
99
0a7de745
A
100void
101personas_bootstrap(void)
490019cf
A
102{
103 struct posix_cred pcred;
cb323159 104 int unique_persona_bootarg;
490019cf
A
105
106 persona_dbg("Initializing persona subsystem");
107 LIST_INIT(&all_personas);
108 g_total_personas = 0;
109
110 g_next_persona_id = FIRST_PERSONA_ID;
111
490019cf
A
112 /*
113 * setup the default credentials that a persona temporarily
114 * inherits (to work around kauth APIs)
115 */
116 bzero(&pcred, sizeof(pcred));
117 pcred.cr_uid = pcred.cr_ruid = pcred.cr_svuid = TEMP_PERSONA_ID;
118 pcred.cr_rgid = pcred.cr_svgid = TEMP_PERSONA_ID;
119 pcred.cr_groups[0] = TEMP_PERSONA_ID;
120 pcred.cr_ngroups = 1;
121 pcred.cr_flags = CRF_NOMEMBERD;
122 pcred.cr_gmuid = KAUTH_UID_NONE;
123
124 g_default_persona_cred = posix_cred_create(&pcred);
0a7de745 125 if (!g_default_persona_cred) {
490019cf 126 panic("couldn't create default persona credentials!");
0a7de745 127 }
cb323159
A
128#if CONFIG_AUDIT
129 /* posix_cred_create() sets this value to NULL */
130 g_default_persona_cred->cr_audit.as_aia_p = audit_default_aia_p;
131#endif
132 if (PE_parse_boot_argn("unique_persona", &unique_persona_bootarg, sizeof(unique_persona_bootarg))) {
133 unique_persona = !!unique_persona_bootarg;
134 }
490019cf
A
135}
136
0a7de745 137struct persona *
f427ee49 138persona_alloc(uid_t id, const char *login, persona_type_t type, char *path, int *error)
490019cf 139{
d9a64523 140 struct persona *persona;
490019cf 141 int err = 0;
490019cf
A
142
143 if (!login) {
144 pna_err("Must provide a login name for a new persona!");
0a7de745 145 if (error) {
490019cf 146 *error = EINVAL;
0a7de745 147 }
490019cf
A
148 return NULL;
149 }
150
151 if (type <= PERSONA_INVALID || type > PERSONA_TYPE_MAX) {
152 pna_err("Invalid type: %d", type);
0a7de745 153 if (error) {
490019cf 154 *error = EINVAL;
0a7de745 155 }
490019cf
A
156 return NULL;
157 }
158
159 persona = (struct persona *)zalloc(persona_zone);
160 if (!persona) {
0a7de745 161 if (error) {
490019cf 162 *error = ENOMEM;
0a7de745 163 }
490019cf
A
164 return NULL;
165 }
166
167 bzero(persona, sizeof(*persona));
168
cb323159 169 if (os_atomic_inc(&g_total_personas, relaxed) > MAX_PERSONAS) {
490019cf
A
170 /* too many personas! */
171 pna_err("too many active personas!");
172 err = EBUSY;
173 goto out_error;
174 }
175
0a7de745 176 strncpy(persona->pna_login, login, sizeof(persona->pna_login) - 1);
d9a64523 177 persona_dbg("Starting persona allocation for: '%s'", persona->pna_login);
490019cf
A
178
179 LIST_INIT(&persona->pna_members);
f427ee49 180 lck_mtx_init(&persona->pna_lock, &persona_lck_grp, LCK_ATTR_NULL);
d9a64523 181 os_ref_init(&persona->pna_refcount, &persona_refgrp);
490019cf
A
182
183 /*
184 * Setup initial (temporary) kauth_cred structure
185 * We need to do this here because all kauth calls require
186 * an existing cred structure.
187 */
188 persona->pna_cred = kauth_cred_create(g_default_persona_cred);
189 if (!persona->pna_cred) {
190 pna_err("could not copy initial credentials!");
191 err = EIO;
192 goto out_error;
193 }
194
d9a64523
A
195 persona->pna_type = type;
196 persona->pna_id = id;
197 persona->pna_valid = PERSONA_ALLOC_TOKEN;
cb323159 198 persona->pna_path = path;
d9a64523
A
199
200 /*
201 * NOTE: this persona has not been fully initialized. A subsequent
202 * call to persona_init_begin() followed by persona_init_end() will make
203 * the persona visible to the rest of the system.
204 */
205 if (error) {
206 *error = 0;
207 }
208 return persona;
209
210out_error:
cb323159 211 os_atomic_dec(&g_total_personas, relaxed);
d9a64523
A
212 zfree(persona_zone, persona);
213 if (error) {
214 *error = err;
215 }
216 return NULL;
217}
218
219/**
220 * persona_init_begin
221 *
222 * This function begins initialization of a persona. It first acquires the
223 * global persona list lock via lock_personas(), then selects an appropriate
224 * persona ID and sets up the persona's credentials. This function *must* be
225 * followed by a call to persona_init_end() which will mark the persona
226 * structure as valid
227 *
228 * Conditions:
0a7de745
A
229 * persona has been allocated via persona_alloc()
230 * nothing locked
d9a64523
A
231 *
232 * Returns:
0a7de745 233 * global persona list is locked (even on error)
d9a64523 234 */
0a7de745
A
235int
236persona_init_begin(struct persona *persona)
d9a64523
A
237{
238 struct persona *tmp;
239 int err = 0;
240 kauth_cred_t tmp_cred;
241 gid_t new_group;
242 uid_t id;
243
244 if (!persona || (persona->pna_valid != PERSONA_ALLOC_TOKEN)) {
245 return EINVAL;
246 }
247
248 id = persona->pna_id;
249
490019cf
A
250 lock_personas();
251try_again:
0a7de745 252 if (id == PERSONA_ID_NONE) {
490019cf 253 persona->pna_id = g_next_persona_id;
0a7de745 254 }
490019cf 255
d9a64523 256 persona_dbg("Beginning Initialization of %d:%d (%s)...", id, persona->pna_id, persona->pna_login);
490019cf
A
257
258 err = 0;
259 LIST_FOREACH(tmp, &all_personas, pna_list) {
d9a64523
A
260 persona_lock(tmp);
261 if (id == PERSONA_ID_NONE && tmp->pna_id == persona->pna_id) {
262 persona_unlock(tmp);
490019cf
A
263 /*
264 * someone else manually claimed this ID, and we're
265 * trying to allocate an ID for the caller: try again
266 */
267 g_next_persona_id += PERSONA_ID_STEP;
268 goto try_again;
269 }
d9a64523
A
270 if (strncmp(tmp->pna_login, persona->pna_login, sizeof(tmp->pna_login)) == 0 ||
271 tmp->pna_id == persona->pna_id) {
272 persona_unlock(tmp);
490019cf
A
273 /*
274 * Disallow use of identical login names and re-use
275 * of previously allocated persona IDs
276 */
277 err = EEXIST;
278 break;
279 }
d9a64523 280 persona_unlock(tmp);
490019cf 281 }
0a7de745 282 if (err) {
d9a64523 283 goto out;
0a7de745 284 }
490019cf
A
285
286 /* ensure the cred has proper UID/GID defaults */
287 kauth_cred_ref(persona->pna_cred);
288 tmp_cred = kauth_cred_setuidgid(persona->pna_cred,
0a7de745
A
289 persona->pna_id,
290 persona->pna_id);
490019cf 291 kauth_cred_unref(&persona->pna_cred);
0a7de745 292 if (tmp_cred != persona->pna_cred) {
490019cf 293 persona->pna_cred = tmp_cred;
0a7de745 294 }
490019cf
A
295
296 if (!persona->pna_cred) {
297 err = EACCES;
d9a64523 298 goto out;
490019cf
A
299 }
300
301 /* it should be a member of exactly 1 group (equal to its UID) */
302 new_group = (gid_t)persona->pna_id;
303
304 kauth_cred_ref(persona->pna_cred);
305 /* opt _out_ of memberd as a default */
306 tmp_cred = kauth_cred_setgroups(persona->pna_cred,
0a7de745 307 &new_group, 1, KAUTH_UID_NONE);
490019cf 308 kauth_cred_unref(&persona->pna_cred);
0a7de745 309 if (tmp_cred != persona->pna_cred) {
490019cf 310 persona->pna_cred = tmp_cred;
0a7de745 311 }
490019cf
A
312
313 if (!persona->pna_cred) {
314 err = EACCES;
d9a64523 315 goto out;
490019cf
A
316 }
317
490019cf 318 /* if the kernel supplied the persona ID, increment for next time */
0a7de745 319 if (id == PERSONA_ID_NONE) {
490019cf 320 g_next_persona_id += PERSONA_ID_STEP;
0a7de745 321 }
490019cf 322
d9a64523 323 persona->pna_valid = PERSONA_INIT_TOKEN;
490019cf 324
d9a64523
A
325out:
326 if (err != 0) {
327 persona_dbg("ERROR:%d while initializing %d:%d (%s)...", err, id, persona->pna_id, persona->pna_login);
328 /*
329 * mark the persona with an error so that persona_init_end()
330 * will *not* add it to the global list.
331 */
332 persona->pna_id = PERSONA_ID_NONE;
490019cf
A
333 }
334
d9a64523
A
335 /*
336 * leave the global persona list locked: it will be
337 * unlocked in a call to persona_init_end()
338 */
339 return err;
340}
490019cf 341
d9a64523
A
342/**
343 * persona_init_end
344 *
345 * This function finalizes the persona initialization by marking it valid and
346 * adding it to the global list of personas. After unlocking the global list,
347 * the persona will be visible to the reset of the system. The function will
348 * only mark the persona valid if the input parameter 'error' is 0.
349 *
350 * Conditions:
0a7de745
A
351 * persona is initialized via persona_init_begin()
352 * global persona list is locked via lock_personas()
d9a64523
A
353 *
354 * Returns:
0a7de745 355 * global persona list is unlocked
d9a64523 356 */
0a7de745
A
357void
358persona_init_end(struct persona *persona, int error)
d9a64523
A
359{
360 if (persona == NULL) {
361 return;
362 }
363
364 /*
365 * If the pna_valid member is set to the INIT_TOKEN value, then it has
366 * successfully gone through persona_init_begin(), and we can mark it
367 * valid and make it visible to the rest of the system. However, if
368 * there was an error either during initialization or otherwise, we
369 * need to decrement the global count of personas because this one
370 * will be disposed-of by the callers invocation of persona_put().
371 */
372 if (error != 0 || persona->pna_valid == PERSONA_ALLOC_TOKEN) {
373 persona_dbg("ERROR:%d after initialization of %d (%s)", error, persona->pna_id, persona->pna_login);
374 /* remove this persona from the global count */
cb323159 375 os_atomic_dec(&g_total_personas, relaxed);
d9a64523 376 } else if (error == 0 &&
0a7de745 377 persona->pna_valid == PERSONA_INIT_TOKEN) {
d9a64523
A
378 persona->pna_valid = PERSONA_MAGIC;
379 LIST_INSERT_HEAD(&all_personas, persona, pna_list);
380 persona_dbg("Initialization of %d (%s) Complete.", persona->pna_id, persona->pna_login);
381 }
382
383 unlock_personas();
490019cf
A
384}
385
cb323159
A
386/**
387 * persona_verify_and_set_uniqueness
388 *
389 * This function checks the persona, if the one being spawned is of type
390 * PERSONA_SYSTEM or PERSONA_SYSTEM_PROXY, is unique.
391 *
392 * Conditions:
393 * global persona list is locked on entry and return.
394 *
395 * Returns:
396 * EEXIST: if persona is system/system-proxy and is not unique.
397 * 0: Otherwise.
398 */
399int
400persona_verify_and_set_uniqueness(struct persona *persona)
401{
402 if (persona == NULL) {
403 return EINVAL;
404 }
405
406 if (!unique_persona) {
407 return 0;
408 }
409
410 if (persona->pna_type == PERSONA_SYSTEM) {
411 if (system_persona != NULL) {
412 return EEXIST;
413 }
414 system_persona = persona;
415 return 0;
416 }
417
418 if (persona->pna_type == PERSONA_SYSTEM_PROXY) {
419 if (proxy_system_persona != NULL) {
420 return EEXIST;
421 }
422 proxy_system_persona = persona;
423 return 0;
424 }
425 return 0;
426}
427
428/**
429 * persona_is_unique
430 *
431 * This function checks if the persona spawned is unique.
432 *
433 * Returns:
434 * TRUE: if unique.
435 * FALSE: otherwise.
436 */
437boolean_t
438persona_is_unique(struct persona *persona)
439{
440 if (persona == NULL) {
441 return FALSE;
442 }
443
444 if (!unique_persona) {
445 return FALSE;
446 }
447
448 if (persona->pna_type == PERSONA_SYSTEM ||
449 persona->pna_type == PERSONA_SYSTEM_PROXY) {
450 return TRUE;
451 }
452
453 return FALSE;
454}
455
0a7de745
A
456static struct persona *
457persona_get_locked(struct persona *persona)
490019cf 458{
d9a64523
A
459 os_ref_retain_locked(&persona->pna_refcount);
460 return persona;
490019cf
A
461}
462
0a7de745
A
463struct persona *
464persona_get(struct persona *persona)
490019cf
A
465{
466 struct persona *ret;
0a7de745 467 if (!persona) {
490019cf 468 return NULL;
0a7de745 469 }
490019cf
A
470 persona_lock(persona);
471 ret = persona_get_locked(persona);
472 persona_unlock(persona);
473
474 return ret;
475}
476
0a7de745
A
477void
478persona_put(struct persona *persona)
490019cf
A
479{
480 int destroy = 0;
481
0a7de745 482 if (!persona) {
490019cf 483 return;
0a7de745 484 }
490019cf
A
485
486 persona_lock(persona);
d9a64523
A
487 if (os_ref_release_locked(&persona->pna_refcount) == 0) {
488 destroy = 1;
490019cf
A
489 }
490 persona_unlock(persona);
491
0a7de745 492 if (!destroy) {
490019cf 493 return;
0a7de745 494 }
490019cf
A
495
496 persona_dbg("Destroying persona %s", persona_desc(persona, 0));
497
498 /* release our credential reference */
0a7de745 499 if (persona->pna_cred) {
490019cf 500 kauth_cred_unref(&persona->pna_cred);
0a7de745 501 }
490019cf
A
502
503 /* remove it from the global list and decrement the count */
504 lock_personas();
a39ff7e2 505 persona_lock(persona);
490019cf
A
506 if (persona_valid(persona)) {
507 LIST_REMOVE(persona, pna_list);
cb323159 508 if (os_atomic_dec_orig(&g_total_personas, relaxed) == 0) {
490019cf 509 panic("persona count underflow!\n");
0a7de745 510 }
490019cf
A
511 persona_mkinvalid(persona);
512 }
cb323159 513 if (persona->pna_path != NULL) {
f427ee49 514 zfree(ZV_NAMEI, persona->pna_path);
cb323159 515 }
a39ff7e2 516 persona_unlock(persona);
490019cf
A
517 unlock_personas();
518
519 assert(LIST_EMPTY(&persona->pna_members));
520 memset(persona, 0, sizeof(*persona));
521 zfree(persona_zone, persona);
522}
523
0a7de745
A
524uid_t
525persona_get_id(struct persona *persona)
490019cf 526{
0a7de745 527 if (persona) {
490019cf 528 return persona->pna_id;
0a7de745 529 }
490019cf
A
530 return PERSONA_ID_NONE;
531}
532
0a7de745
A
533struct persona *
534persona_lookup(uid_t id)
490019cf
A
535{
536 struct persona *persona, *tmp;
537
538 persona = NULL;
539
540 /*
541 * simple, linear lookup for now: there shouldn't be too many
542 * of these in memory at any given time.
543 */
544 lock_personas();
545 LIST_FOREACH(tmp, &all_personas, pna_list) {
546 persona_lock(tmp);
547 if (tmp->pna_id == id && persona_valid(tmp)) {
548 persona = persona_get_locked(tmp);
549 persona_unlock(tmp);
550 break;
551 }
552 persona_unlock(tmp);
553 }
554 unlock_personas();
555
556 return persona;
557}
558
0a7de745
A
559struct persona *
560persona_lookup_and_invalidate(uid_t id)
a39ff7e2
A
561{
562 struct persona *persona, *entry, *tmp;
563
564 persona = NULL;
565
566 lock_personas();
567 LIST_FOREACH_SAFE(entry, &all_personas, pna_list, tmp) {
568 persona_lock(entry);
569 if (entry->pna_id == id) {
cb323159 570 if (persona_valid(entry) && !persona_is_unique(entry)) {
a39ff7e2
A
571 persona = persona_get_locked(entry);
572 assert(persona != NULL);
573 LIST_REMOVE(persona, pna_list);
cb323159 574 if (os_atomic_dec_orig(&g_total_personas, relaxed) == 0) {
a39ff7e2 575 panic("persona ref count underflow!\n");
0a7de745 576 }
a39ff7e2
A
577 persona_mkinvalid(persona);
578 }
579 persona_unlock(entry);
580 break;
581 }
582 persona_unlock(entry);
583 }
584 unlock_personas();
585
586 return persona;
587}
588
cb323159 589int
f427ee49 590persona_find_by_type(persona_type_t persona_type, struct persona **persona, size_t *plen)
cb323159
A
591{
592 return persona_find_all(NULL, PERSONA_ID_NONE, persona_type, persona, plen);
593}
594
0a7de745
A
595int
596persona_find(const char *login, uid_t uid,
597 struct persona **persona, size_t *plen)
cb323159
A
598{
599 return persona_find_all(login, uid, PERSONA_INVALID, persona, plen);
600}
601
602int
f427ee49 603persona_find_all(const char *login, uid_t uid, persona_type_t persona_type,
cb323159 604 struct persona **persona, size_t *plen)
490019cf
A
605{
606 struct persona *tmp;
607 int match = 0;
608 size_t found = 0;
609
0a7de745 610 if (login) {
490019cf 611 match++;
0a7de745
A
612 }
613 if (uid != PERSONA_ID_NONE) {
490019cf 614 match++;
0a7de745 615 }
cb323159
A
616 if ((persona_type > PERSONA_INVALID) && (persona_type <= PERSONA_TYPE_MAX)) {
617 match++;
618 } else if (persona_type != PERSONA_INVALID) {
619 return EINVAL;
620 }
490019cf 621
0a7de745 622 if (match == 0) {
490019cf 623 return EINVAL;
0a7de745 624 }
490019cf
A
625
626 persona_dbg("Searching with %d parameters (l:\"%s\", u:%d)",
0a7de745 627 match, login, uid);
490019cf
A
628
629 lock_personas();
630 LIST_FOREACH(tmp, &all_personas, pna_list) {
631 int m = 0;
632 persona_lock(tmp);
0a7de745 633 if (login && strncmp(tmp->pna_login, login, sizeof(tmp->pna_login)) == 0) {
490019cf 634 m++;
0a7de745
A
635 }
636 if (uid != PERSONA_ID_NONE && uid == tmp->pna_id) {
490019cf 637 m++;
0a7de745 638 }
cb323159
A
639 if (persona_type != PERSONA_INVALID && persona_type == tmp->pna_type) {
640 m++;
641 }
490019cf 642 if (m == match) {
0a7de745 643 if (persona && *plen > found) {
490019cf 644 persona[found] = persona_get_locked(tmp);
0a7de745 645 }
490019cf
A
646 found++;
647 }
648#ifdef PERSONA_DEBUG
0a7de745 649 if (m > 0) {
490019cf 650 persona_dbg("ID:%d Matched %d/%d, found:%d, *plen:%d",
0a7de745
A
651 tmp->pna_id, m, match, (int)found, (int)*plen);
652 }
490019cf
A
653#endif
654 persona_unlock(tmp);
655 }
656 unlock_personas();
657
658 *plen = found;
0a7de745 659 if (!found) {
490019cf 660 return ESRCH;
0a7de745 661 }
490019cf
A
662 return 0;
663}
664
0a7de745
A
665struct persona *
666persona_proc_get(pid_t pid)
490019cf
A
667{
668 struct persona *persona;
669 proc_t p = proc_find(pid);
670
0a7de745 671 if (!p) {
490019cf 672 return NULL;
0a7de745 673 }
490019cf
A
674
675 proc_lock(p);
676 persona = persona_get(p->p_persona);
677 proc_unlock(p);
678
679 proc_rele(p);
680
681 return persona;
682}
683
0a7de745
A
684struct persona *
685current_persona_get(void)
490019cf 686{
cb323159
A
687 struct persona *persona = NULL;
688 uid_t current_persona_id = PERSONA_ID_NONE;
689 ipc_voucher_t voucher;
490019cf 690
cb323159
A
691 thread_get_mach_voucher(current_thread(), 0, &voucher);
692 /* returns a voucher ref */
693 if (voucher != IPC_VOUCHER_NULL) {
694 /*
695 * If the voucher doesn't contain a bank attribute, it uses
696 * the default bank task value to determine the persona id
697 * which is the same as the proc's persona id
698 */
699 bank_get_bank_ledger_thread_group_and_persona(voucher, NULL,
700 NULL, &current_persona_id);
701 ipc_voucher_release(voucher);
702 persona = persona_lookup(current_persona_id);
703 } else {
704 /* Fallback - get the proc's persona */
705 proc_t p = current_proc();
706 proc_lock(p);
707 persona = persona_get(p->p_persona);
708 proc_unlock(p);
709 }
490019cf
A
710 return persona;
711}
712
713/**
714 * inherit a persona from parent to child
715 */
0a7de745
A
716int
717persona_proc_inherit(proc_t child, proc_t parent)
490019cf
A
718{
719 if (child->p_persona != NULL) {
720 persona_dbg("proc_inherit: child already in persona: %s",
0a7de745 721 persona_desc(child->p_persona, 0));
490019cf
A
722 return -1;
723 }
724
725 /* no persona to inherit */
0a7de745 726 if (parent->p_persona == NULL) {
490019cf 727 return 0;
0a7de745 728 }
490019cf
A
729
730 return persona_proc_adopt(child, parent->p_persona, parent->p_ucred);
731}
732
0a7de745
A
733int
734persona_proc_adopt_id(proc_t p, uid_t id, kauth_cred_t auth_override)
490019cf
A
735{
736 int ret;
737 struct persona *persona;
738
739 persona = persona_lookup(id);
0a7de745 740 if (!persona) {
490019cf 741 return ESRCH;
0a7de745 742 }
490019cf
A
743
744 ret = persona_proc_adopt(p, persona, auth_override);
745
746 /* put the reference from the lookup() */
747 persona_put(persona);
748
749 return ret;
750}
751
752
753typedef enum e_persona_reset_op {
754 PROC_REMOVE_PERSONA = 1,
755 PROC_RESET_OLD_PERSONA = 2,
756} persona_reset_op_t;
757
758/*
759 * internal cleanup routine for proc_set_cred_internal
760 *
761 */
0a7de745
A
762static struct persona *
763proc_reset_persona_internal(proc_t p, persona_reset_op_t op,
764 struct persona *old_persona,
765 struct persona *new_persona)
490019cf
A
766{
767#if (DEVELOPMENT || DEBUG)
768 persona_lock_assert_held(new_persona);
769#endif
770
771 switch (op) {
772 case PROC_REMOVE_PERSONA:
773 old_persona = p->p_persona;
f427ee49 774 OS_FALLTHROUGH;
490019cf
A
775 case PROC_RESET_OLD_PERSONA:
776 break;
777 default:
778 /* invalid arguments */
779 return NULL;
780 }
781
782 /* unlock the new persona (locked on entry) */
783 persona_unlock(new_persona);
784 /* lock the old persona and the process */
f427ee49 785 assert(old_persona != NULL);
490019cf
A
786 persona_lock(old_persona);
787 proc_lock(p);
788
789 switch (op) {
790 case PROC_REMOVE_PERSONA:
791 LIST_REMOVE(p, p_persona_list);
792 p->p_persona = NULL;
793 break;
794 case PROC_RESET_OLD_PERSONA:
795 p->p_persona = old_persona;
796 LIST_INSERT_HEAD(&old_persona->pna_members, p, p_persona_list);
797 break;
798 }
799
800 proc_unlock(p);
801 persona_unlock(old_persona);
802
803 /* re-lock the new persona */
804 persona_lock(new_persona);
805 return old_persona;
806}
807
808/*
809 * Assumes persona is locked.
810 * On success, takes a reference to 'persona' and returns the
811 * previous persona the process had adopted. The caller is
812 * responsible to release the reference.
813 */
0a7de745
A
814static struct persona *
815proc_set_cred_internal(proc_t p, struct persona *persona,
816 kauth_cred_t auth_override, int *rlim_error)
490019cf
A
817{
818 struct persona *old_persona = NULL;
819 kauth_cred_t my_cred, my_new_cred;
820 uid_t old_uid, new_uid;
f427ee49
A
821 size_t count;
822 rlim_t nproc = proc_limitgetcur(p, RLIMIT_NPROC, TRUE);
490019cf
A
823
824 /*
825 * This operation must be done under the proc trans lock
826 * by the thread which took the trans lock!
827 */
828 assert(((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) &&
0a7de745 829 p->p_transholder == current_thread());
490019cf
A
830 assert(persona != NULL);
831
832 /* no work to do if we "re-adopt" the same persona */
0a7de745 833 if (p->p_persona == persona) {
490019cf 834 return NULL;
0a7de745 835 }
490019cf
A
836
837 /*
838 * If p is in a persona, then we need to remove 'p' from the list of
839 * processes in that persona. To do this, we need to drop the lock
840 * held on the incoming (new) persona and lock the old one.
841 */
842 if (p->p_persona) {
843 old_persona = proc_reset_persona_internal(p, PROC_REMOVE_PERSONA,
0a7de745 844 NULL, persona);
490019cf
A
845 }
846
0a7de745 847 if (auth_override) {
490019cf 848 my_new_cred = auth_override;
0a7de745 849 } else {
490019cf 850 my_new_cred = persona->pna_cred;
0a7de745 851 }
490019cf 852
0a7de745 853 if (!my_new_cred) {
490019cf 854 panic("NULL credentials (persona:%p)", persona);
0a7de745 855 }
490019cf
A
856
857 *rlim_error = 0;
858
859 kauth_cred_ref(my_new_cred);
860
861 new_uid = persona->pna_id;
862
863 /*
864 * Check to see if we will hit a proc rlimit by moving the process
865 * into the persona. If so, we'll bail early before actually moving
866 * the process or changing its credentials.
867 */
868 if (new_uid != 0 &&
f427ee49 869 (rlim_t)chgproccnt(new_uid, 0) > nproc) {
490019cf 870 pna_err("PID:%d hit proc rlimit in new persona(%d): %s",
0a7de745 871 p->p_pid, new_uid, persona_desc(persona, 1));
490019cf 872 *rlim_error = EACCES;
f427ee49
A
873 if (old_persona) {
874 (void)proc_reset_persona_internal(p, PROC_RESET_OLD_PERSONA,
875 old_persona, persona);
876 }
490019cf
A
877 kauth_cred_unref(&my_new_cred);
878 return NULL;
879 }
880
881 /*
882 * Set the new credentials on the proc
883 */
884set_proc_cred:
885 my_cred = kauth_cred_proc_ref(p);
886 persona_dbg("proc_adopt PID:%d, %s -> %s",
0a7de745
A
887 p->p_pid,
888 persona_desc(old_persona, 1),
889 persona_desc(persona, 1));
490019cf
A
890
891 old_uid = kauth_cred_getruid(my_cred);
892
893 if (my_cred != my_new_cred) {
894 kauth_cred_t old_cred = my_cred;
895
896 proc_ucred_lock(p);
897 /*
898 * We need to protect against a race where another thread
899 * also changed the credential after we took our
900 * reference. If p_ucred has changed then we should
901 * restart this again with the new cred.
902 */
903 if (p->p_ucred != my_cred) {
904 proc_ucred_unlock(p);
905 kauth_cred_unref(&my_cred);
906 /* try again */
907 goto set_proc_cred;
908 }
909
910 /* update the credential and take a ref for the proc */
911 kauth_cred_ref(my_new_cred);
912 p->p_ucred = my_new_cred;
913
914 /* update cred on proc (and current thread) */
915 mach_kauth_cred_uthread_update();
916 PROC_UPDATE_CREDS_ONPROC(p);
917
918 /* drop the proc's old ref on the credential */
919 kauth_cred_unref(&old_cred);
920 proc_ucred_unlock(p);
921 }
922
923 /* drop this function's reference to the old cred */
924 kauth_cred_unref(&my_cred);
925
926 /*
927 * Update the proc count.
928 * If the UIDs are the same, then there is no work to do.
929 */
0a7de745 930 if (old_persona) {
490019cf 931 old_uid = old_persona->pna_id;
0a7de745 932 }
490019cf
A
933
934 if (new_uid != old_uid) {
935 count = chgproccnt(old_uid, -1);
f427ee49 936 persona_dbg("Decrement %s:%d proc_count to: %lu",
0a7de745 937 old_persona ? "Persona" : "UID", old_uid, count);
490019cf
A
938
939 /*
940 * Increment the proc count on the UID associated with
941 * the new persona. Enforce the resource limit just
942 * as in fork1()
943 */
944 count = chgproccnt(new_uid, 1);
f427ee49 945 persona_dbg("Increment Persona:%d (UID:%d) proc_count to: %lu",
0a7de745 946 new_uid, kauth_cred_getuid(my_new_cred), count);
490019cf
A
947 }
948
949 OSBitOrAtomic(P_ADOPTPERSONA, &p->p_flag);
950
951 proc_lock(p);
952 p->p_persona = persona_get_locked(persona);
953 LIST_INSERT_HEAD(&persona->pna_members, p, p_persona_list);
954 proc_unlock(p);
955
956 kauth_cred_unref(&my_new_cred);
957
958 return old_persona;
959}
960
0a7de745
A
961int
962persona_proc_adopt(proc_t p, struct persona *persona, kauth_cred_t auth_override)
490019cf
A
963{
964 int error;
965 struct persona *old_persona;
490019cf 966
0a7de745 967 if (!persona) {
490019cf 968 return EINVAL;
0a7de745 969 }
490019cf
A
970
971 persona_dbg("%d adopting Persona %d (%s)", proc_pid(p),
0a7de745 972 persona->pna_id, persona_desc(persona, 0));
490019cf
A
973
974 persona_lock(persona);
975 if (!persona->pna_cred || !persona_valid(persona)) {
976 persona_dbg("Invalid persona (%s): NULL credentials!", persona_desc(persona, 1));
977 persona_unlock(persona);
978 return EINVAL;
979 }
980
981 /* the persona credentials can no longer be adjusted */
982 persona->pna_cred_locked = 1;
983
984 /*
985 * assume the persona: this may drop and re-acquire the persona lock!
986 */
987 error = 0;
988 old_persona = proc_set_cred_internal(p, persona, auth_override, &error);
989
990 /* join the process group associated with the persona */
991 if (persona->pna_pgid) {
992 uid_t uid = kauth_cred_getuid(persona->pna_cred);
993 persona_dbg(" PID:%d, pgid:%d%s",
0a7de745
A
994 p->p_pid, persona->pna_pgid,
995 persona->pna_pgid == uid ? ", new_session" : ".");
490019cf
A
996 enterpgrp(p, persona->pna_pgid, persona->pna_pgid == uid);
997 }
998
cb323159
A
999 /* Only Multiuser Mode needs to update the session login name to the persona name */
1000#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
c3c9b80d 1001 uint32_t multiuser_flags = COMM_PAGE_READ(uint32_t, MULTIUSER_CONFIG);
490019cf 1002 /* set the login name of the session */
cb323159
A
1003 if (multiuser_flags) {
1004 struct session * sessp = proc_session(p);
1005 if (sessp != SESSION_NULL) {
1006 session_lock(sessp);
1007 bcopy(persona->pna_login, sessp->s_login, MAXLOGNAME);
1008 session_unlock(sessp);
1009 session_rele(sessp);
1010 }
490019cf 1011 }
cb323159 1012#endif
490019cf
A
1013 persona_unlock(persona);
1014
1015 set_security_token(p);
1016
1017 /*
1018 * Drop the reference to the old persona.
1019 */
0a7de745 1020 if (old_persona) {
490019cf 1021 persona_put(old_persona);
0a7de745 1022 }
490019cf
A
1023
1024 persona_dbg("%s", error == 0 ? "SUCCESS" : "FAILED");
1025 return error;
1026}
1027
0a7de745
A
1028int
1029persona_proc_drop(proc_t p)
490019cf
A
1030{
1031 struct persona *persona = NULL;
1032
1033 persona_dbg("PID:%d, %s -> <none>", p->p_pid, persona_desc(p->p_persona, 0));
1034
1035 /*
1036 * There are really no other credentials for us to assume,
1037 * so we'll just continue running with the credentials
1038 * we got from the persona.
1039 */
1040
1041 /*
1042 * the locks must be taken in reverse order here, so
1043 * we have to be careful not to cause deadlock
1044 */
1045try_again:
1046 proc_lock(p);
1047 if (p->p_persona) {
1048 uid_t puid, ruid;
1049 if (!persona_try_lock(p->p_persona)) {
1050 proc_unlock(p);
1051 mutex_pause(0); /* back-off time */
1052 goto try_again;
1053 }
1054 persona = p->p_persona;
1055 LIST_REMOVE(p, p_persona_list);
1056 p->p_persona = NULL;
1057
1058 ruid = kauth_cred_getruid(p->p_ucred);
1059 puid = kauth_cred_getuid(persona->pna_cred);
1060 proc_unlock(p);
1061 (void)chgproccnt(ruid, 1);
1062 (void)chgproccnt(puid, -1);
1063 } else {
1064 proc_unlock(p);
1065 }
1066
1067 /*
1068 * if the proc had a persona, then it is still locked here
1069 * (preserving proper lock ordering)
1070 */
1071
1072 if (persona) {
1073 persona_unlock(persona);
1074 persona_put(persona);
1075 }
1076
1077 return 0;
1078}
1079
0a7de745
A
1080int
1081persona_get_type(struct persona *persona)
490019cf
A
1082{
1083 int type;
1084
0a7de745 1085 if (!persona) {
490019cf 1086 return PERSONA_INVALID;
0a7de745 1087 }
490019cf
A
1088
1089 persona_lock(persona);
1090 if (!persona_valid(persona)) {
1091 persona_unlock(persona);
1092 return PERSONA_INVALID;
1093 }
1094 type = persona->pna_type;
1095 persona_unlock(persona);
1096
1097 return type;
1098}
1099
0a7de745
A
1100int
1101persona_set_cred(struct persona *persona, kauth_cred_t cred)
490019cf
A
1102{
1103 int ret = 0;
1104 kauth_cred_t my_cred;
0a7de745 1105 if (!persona || !cred) {
490019cf 1106 return EINVAL;
0a7de745 1107 }
490019cf
A
1108
1109 persona_lock(persona);
d9a64523 1110 if (!persona_initialized(persona)) {
490019cf
A
1111 ret = EINVAL;
1112 goto out_unlock;
1113 }
1114 if (persona->pna_cred_locked) {
1115 ret = EPERM;
1116 goto out_unlock;
1117 }
1118
1119 /* create a new cred from the passed-in cred */
1120 my_cred = kauth_cred_create(cred);
1121
1122 /* ensure that the UID matches the persona ID */
1123 my_cred = kauth_cred_setresuid(my_cred, persona->pna_id,
0a7de745
A
1124 persona->pna_id, persona->pna_id,
1125 KAUTH_UID_NONE);
490019cf
A
1126
1127 /* TODO: clear the saved GID?! */
1128
1129 /* replace the persona's cred with the new one */
0a7de745 1130 if (persona->pna_cred) {
490019cf 1131 kauth_cred_unref(&persona->pna_cred);
0a7de745 1132 }
490019cf
A
1133 persona->pna_cred = my_cred;
1134
1135out_unlock:
1136 persona_unlock(persona);
1137 return ret;
1138}
1139
0a7de745
A
1140int
1141persona_set_cred_from_proc(struct persona *persona, proc_t proc)
490019cf
A
1142{
1143 int ret = 0;
1144 kauth_cred_t parent_cred, my_cred;
0a7de745 1145 if (!persona || !proc) {
490019cf 1146 return EINVAL;
0a7de745 1147 }
490019cf
A
1148
1149 persona_lock(persona);
d9a64523 1150 if (!persona_initialized(persona)) {
490019cf
A
1151 ret = EINVAL;
1152 goto out_unlock;
1153 }
1154 if (persona->pna_cred_locked) {
1155 ret = EPERM;
1156 goto out_unlock;
1157 }
1158
1159 parent_cred = kauth_cred_proc_ref(proc);
1160
1161 /* TODO: clear the saved UID/GID! */
1162
1163 /* create a new cred from the proc's cred */
1164 my_cred = kauth_cred_create(parent_cred);
1165
1166 /* ensure that the UID matches the persona ID */
1167 my_cred = kauth_cred_setresuid(my_cred, persona->pna_id,
0a7de745
A
1168 persona->pna_id, persona->pna_id,
1169 KAUTH_UID_NONE);
490019cf
A
1170
1171 /* replace the persona's cred with the new one */
0a7de745 1172 if (persona->pna_cred) {
490019cf 1173 kauth_cred_unref(&persona->pna_cred);
0a7de745 1174 }
490019cf
A
1175 persona->pna_cred = my_cred;
1176
1177 kauth_cred_unref(&parent_cred);
1178
1179out_unlock:
1180 persona_unlock(persona);
1181 return ret;
1182}
1183
0a7de745
A
1184kauth_cred_t
1185persona_get_cred(struct persona *persona)
490019cf
A
1186{
1187 kauth_cred_t cred = NULL;
1188
0a7de745 1189 if (!persona) {
490019cf 1190 return NULL;
0a7de745 1191 }
490019cf
A
1192
1193 persona_lock(persona);
0a7de745 1194 if (!persona_valid(persona)) {
490019cf 1195 goto out_unlock;
0a7de745 1196 }
490019cf
A
1197
1198 if (persona->pna_cred) {
1199 kauth_cred_ref(persona->pna_cred);
1200 cred = persona->pna_cred;
1201 }
1202
1203out_unlock:
1204 persona_unlock(persona);
1205
1206 return cred;
1207}
1208
0a7de745
A
1209uid_t
1210persona_get_uid(struct persona *persona)
490019cf
A
1211{
1212 uid_t uid = UID_MAX;
1213
0a7de745 1214 if (!persona || !persona->pna_cred) {
490019cf 1215 return UID_MAX;
0a7de745 1216 }
490019cf
A
1217
1218 persona_lock(persona);
1219 if (persona_valid(persona)) {
1220 uid = kauth_cred_getuid(persona->pna_cred);
1221 assert(uid == persona->pna_id);
1222 }
1223 persona_unlock(persona);
1224
1225 return uid;
1226}
1227
0a7de745
A
1228int
1229persona_set_gid(struct persona *persona, gid_t gid)
490019cf
A
1230{
1231 int ret = 0;
1232 kauth_cred_t my_cred, new_cred;
1233
0a7de745 1234 if (!persona || !persona->pna_cred) {
490019cf 1235 return EINVAL;
0a7de745 1236 }
490019cf
A
1237
1238 persona_lock(persona);
d9a64523 1239 if (!persona_initialized(persona)) {
490019cf
A
1240 ret = EINVAL;
1241 goto out_unlock;
1242 }
1243 if (persona->pna_cred_locked) {
1244 ret = EPERM;
1245 goto out_unlock;
1246 }
1247
1248 my_cred = persona->pna_cred;
1249 kauth_cred_ref(my_cred);
1250 new_cred = kauth_cred_setresgid(my_cred, gid, gid, gid);
0a7de745 1251 if (new_cred != my_cred) {
490019cf 1252 persona->pna_cred = new_cred;
0a7de745 1253 }
490019cf
A
1254 kauth_cred_unref(&my_cred);
1255
1256out_unlock:
1257 persona_unlock(persona);
1258 return ret;
1259}
1260
0a7de745
A
1261gid_t
1262persona_get_gid(struct persona *persona)
490019cf
A
1263{
1264 gid_t gid = GID_MAX;
1265
0a7de745 1266 if (!persona || !persona->pna_cred) {
490019cf 1267 return GID_MAX;
0a7de745 1268 }
490019cf
A
1269
1270 persona_lock(persona);
0a7de745 1271 if (persona_valid(persona)) {
490019cf 1272 gid = kauth_cred_getgid(persona->pna_cred);
0a7de745 1273 }
490019cf
A
1274 persona_unlock(persona);
1275
1276 return gid;
1277}
1278
0a7de745 1279int
f427ee49 1280persona_set_groups(struct persona *persona, gid_t *groups, size_t ngroups, uid_t gmuid)
490019cf
A
1281{
1282 int ret = 0;
1283 kauth_cred_t my_cred, new_cred;
1284
0a7de745 1285 if (!persona || !persona->pna_cred) {
490019cf 1286 return EINVAL;
0a7de745
A
1287 }
1288 if (ngroups > NGROUPS_MAX) {
490019cf 1289 return EINVAL;
0a7de745 1290 }
490019cf
A
1291
1292 persona_lock(persona);
d9a64523 1293 if (!persona_initialized(persona)) {
490019cf
A
1294 ret = EINVAL;
1295 goto out_unlock;
1296 }
1297 if (persona->pna_cred_locked) {
1298 ret = EPERM;
1299 goto out_unlock;
1300 }
1301
1302 my_cred = persona->pna_cred;
1303 kauth_cred_ref(my_cred);
f427ee49 1304 new_cred = kauth_cred_setgroups(my_cred, groups, ngroups, gmuid);
0a7de745 1305 if (new_cred != my_cred) {
490019cf 1306 persona->pna_cred = new_cred;
0a7de745 1307 }
490019cf
A
1308 kauth_cred_unref(&my_cred);
1309
1310out_unlock:
1311 persona_unlock(persona);
1312 return ret;
1313}
1314
0a7de745 1315int
f427ee49 1316persona_get_groups(struct persona *persona, size_t *ngroups, gid_t *groups, size_t groups_sz)
490019cf
A
1317{
1318 int ret = EINVAL;
0a7de745 1319 if (!persona || !persona->pna_cred || !groups || !ngroups || groups_sz > NGROUPS) {
490019cf 1320 return EINVAL;
0a7de745 1321 }
490019cf
A
1322
1323 *ngroups = groups_sz;
1324
1325 persona_lock(persona);
1326 if (persona_valid(persona)) {
f427ee49 1327 size_t kauth_ngroups = groups_sz;
527f9951 1328 kauth_cred_getgroups(persona->pna_cred, groups, &kauth_ngroups);
f427ee49 1329 *ngroups = (uint32_t)kauth_ngroups;
490019cf
A
1330 ret = 0;
1331 }
1332 persona_unlock(persona);
1333
1334 return ret;
1335}
1336
0a7de745
A
1337uid_t
1338persona_get_gmuid(struct persona *persona)
490019cf
A
1339{
1340 uid_t gmuid = KAUTH_UID_NONE;
1341
0a7de745 1342 if (!persona || !persona->pna_cred) {
490019cf 1343 return gmuid;
0a7de745 1344 }
490019cf
A
1345
1346 persona_lock(persona);
0a7de745 1347 if (!persona_valid(persona)) {
490019cf 1348 goto out_unlock;
0a7de745 1349 }
490019cf
A
1350
1351 posix_cred_t pcred = posix_cred_get(persona->pna_cred);
1352 gmuid = pcred->cr_gmuid;
1353
1354out_unlock:
1355 persona_unlock(persona);
1356 return gmuid;
1357}
1358
0a7de745
A
1359int
1360persona_get_login(struct persona *persona, char login[MAXLOGNAME + 1])
490019cf
A
1361{
1362 int ret = EINVAL;
0a7de745 1363 if (!persona || !persona->pna_cred) {
490019cf 1364 return EINVAL;
0a7de745 1365 }
490019cf
A
1366
1367 persona_lock(persona);
0a7de745 1368 if (!persona_valid(persona)) {
490019cf 1369 goto out_unlock;
0a7de745 1370 }
490019cf
A
1371
1372 strlcpy(login, persona->pna_login, MAXLOGNAME);
1373 ret = 0;
1374
1375out_unlock:
1376 persona_unlock(persona);
490019cf
A
1377 return ret;
1378}
1379
1380#else /* !CONFIG_PERSONAS */
1381
1382/*
1383 * symbol exports for kext compatibility
1384 */
1385
cb323159
A
1386struct persona *system_persona = NULL;
1387struct persona *proxy_system_persona = NULL;
1388int unique_persona = 0;
1389
0a7de745
A
1390uid_t
1391persona_get_id(__unused struct persona *persona)
490019cf
A
1392{
1393 return PERSONA_ID_NONE;
1394}
1395
0a7de745
A
1396int
1397persona_get_type(__unused struct persona *persona)
490019cf
A
1398{
1399 return PERSONA_INVALID;
1400}
1401
0a7de745
A
1402kauth_cred_t
1403persona_get_cred(__unused struct persona *persona)
490019cf
A
1404{
1405 return NULL;
1406}
1407
0a7de745
A
1408struct persona *
1409persona_lookup(__unused uid_t id)
490019cf
A
1410{
1411 return NULL;
1412}
1413
0a7de745
A
1414int
1415persona_find(__unused const char *login,
1416 __unused uid_t uid,
1417 __unused struct persona **persona,
1418 __unused size_t *plen)
490019cf
A
1419{
1420 return ENOTSUP;
1421}
1422
cb323159
A
1423int
1424persona_find_by_type(__unused int persona_type,
1425 __unused struct persona **persona,
1426 __unused size_t *plen)
1427{
1428 return ENOTSUP;
1429}
1430
1431struct persona *
1432persona_proc_get(__unused pid_t pid)
1433{
1434 return NULL;
1435}
1436
0a7de745
A
1437struct persona *
1438current_persona_get(void)
490019cf
A
1439{
1440 return NULL;
1441}
1442
0a7de745
A
1443struct persona *
1444persona_get(struct persona *persona)
490019cf
A
1445{
1446 return persona;
1447}
1448
0a7de745
A
1449void
1450persona_put(__unused struct persona *persona)
490019cf
A
1451{
1452 return;
1453}
1454#endif