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