2 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 #ifndef _SYS_PERSONA_H_
29 #define _SYS_PERSONA_H_
32 #include <sys/param.h>
35 __enum_decl(persona_type_t
, int, {
45 PERSONA_SYSTEM_PROXY
= 6,
47 PERSONA_ENTERPRISE
= 8,
49 PERSONA_TYPE_MAX
= PERSONA_ENTERPRISE
,
56 #define PERSONA_ID_NONE ((uid_t)-1)
58 struct kpersona_info
{
59 uint32_t persona_info_version
;
61 uid_t persona_id
; /* overlaps with UID */
64 uint32_t persona_ngroups
;
65 gid_t persona_groups
[NGROUPS
];
67 char persona_name
[MAXLOGNAME
+ 1];
69 /* TODO: MAC policies?! */
72 #define PERSONA_INFO_V1 1
73 #define PERSONA_INFO_V1_SIZE (sizeof(struct kpersona_info))
76 #define PERSONA_OP_ALLOC 1
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
86 #define PERSONA_MGMT_ENTITLEMENT "com.apple.private.persona-mgmt"
90 * user space persona interface
94 * kpersona_alloc: Allocate a new in-kernel persona
97 * info: Pointer to persona info structure describing the
98 * attributes of the persona to create / allocate.
100 * id: output: set to the ID of the created persona
103 * The 'persona_id' field of the 'info' parameter is ignored.
109 int kpersona_alloc(struct kpersona_info
*info
, uid_t
*id
);
112 * kpersona_palloc: Allocate a new in-kernel persona with a directory
116 * info: Pointer to persona info structure describing the
117 * attributes of the persona to create / allocate.
119 * path: Pointer to directory name that stores persona specific
120 * data. Assumes path buffer length = MAXPATHLEN and is a
121 * null-terminated string.
123 * id: output: set to the ID of the created persona
126 * The 'persona_id' field of the 'info' parameter is ignored.
132 int kpersona_palloc(struct kpersona_info
*info
, uid_t
*id
, char path
[MAXPATHLEN
]);
135 * kpersona_dealloc: delete / destroy an in-kernel persona
138 * id: the ID of the persona to destroy
144 int kpersona_dealloc(uid_t id
);
147 * kpersona_get: retrieve the persona with which the current thread is running
149 * To find the proc's persona id use kpersona_pidinfo
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.
157 * < 0: Thread is not running under any persona
158 * 0: Success (uuid is filled with running persona UUID)
160 int kpersona_get(uid_t
*id
);
163 * kpersona_get_path: retrieve the given persona's path
166 * id: ID of the persona
168 * path: output: filled in with path on success.
169 * Assumes path buffer length = MAXPATHLEN
175 int kpersona_getpath(uid_t id
, char path
[MAXPATHLEN
]);
178 * kpersona_info: gather info about the given persona
181 * id: ID of the persona to investigate
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.
186 * info: output: filled in with persona attributes on success.
192 int kpersona_info(uid_t id
, struct kpersona_info
*info
);
195 * kpersona_pidinfo: gather persona info about the given PID
198 * pid: PID of the process whose persona info we're to return
200 * info: output: filled in with persona attributes on success.
206 int kpersona_pidinfo(pid_t pid
, struct kpersona_info
*info
);
209 * kpersona_find: lookup the kernel's UUID of a persona
212 * name: Local login name of the persona.
213 * Set this to NULL to find personas by 'uid'.
215 * uid: UID of the persona.
216 * Set this to -1 to find personas by 'name'
218 * id: output: the ID(s) matching the input parameters
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
225 * At least one of 'name' or 'uid' must be set.
229 * >= 0: The number of IDs found to match the input parameters
231 int kpersona_find(const char *name
, uid_t uid
, uid_t
*id
, size_t *idlen
);
234 * kpersona_find_by_type: lookup the persona ids by type
237 * persona_type: Type of persona id (see enum)
239 * id: output: the ID(s) matching the input parameters
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
247 * >= 0: The number of IDs found to match the input parameters
249 int kpersona_find_by_type(int persona_type
, uid_t
*id
, size_t *idlen
);
252 #ifdef KERNEL_PRIVATE
253 /* XNU + kext private interface */
254 #include <sys/cdefs.h>
255 #include <sys/kauth.h>
256 #include <libkern/libkern.h>
257 #include <os/refcnt.h>
261 #define persona_dbg(fmt, ...) \
262 os_log(OS_LOG_DEFAULT, "[%4d] %s: " fmt "\n", \
263 current_proc() ? current_proc()->p_pid : -1, \
264 __func__, ## __VA_ARGS__)
266 #define persona_dbg(fmt, ...) do { } while (0)
272 #ifdef XNU_KERNEL_PRIVATE
273 /* only XNU proper needs to see the persona structure */
275 os_refcnt_t pna_refcount
;
279 persona_type_t pna_type
;
280 char pna_login
[MAXLOGNAME
+ 1];
283 kauth_cred_t pna_cred
;
286 int pna_cred_locked
; /* set upon first adoption */
288 LIST_ENTRY(persona
) pna_list
;
290 /* this could go away if we used a coalition */
291 LIST_HEAD(, proc
) pna_members
;
296 * We can add things here such as PID maps, UID maps, etc.
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)
307 #define persona_lock_assert_held(persona) \
308 LCK_MTX_ASSERT(&(persona)->pna_lock, LCK_MTX_ASSERT_OWNED)
311 static inline const char *
312 persona_desc(struct persona
*persona
, int locked
)
318 if (persona
->pna_desc
[0] != 0) {
319 return persona
->pna_desc
;
323 persona_lock(persona
);
325 if (persona
->pna_desc
[0] != 0) {
329 char *p
= &persona
->pna_desc
[0];
330 char *end
= p
+ sizeof(persona
->pna_desc
) - 1;
333 p
+= scnprintf(p
, end
- p
, "%s/%d:%d",
335 kauth_cred_getuid(persona
->pna_cred
),
336 kauth_cred_getgid(persona
->pna_cred
));
343 persona_unlock(persona
);
346 return persona
->pna_desc
;
348 #else /* !PERSONA_DEBUG */
349 static inline const char *
350 persona_desc(struct persona
*persona
, int locked
)
358 #else /* !XNU_KERNEL_PRIVATE */
359 /* kexts should only see an opaque persona structure */
365 #ifndef _KAUTH_CRED_T
366 #define _KAUTH_CRED_T
367 typedef struct ucred
*kauth_cred_t
;
368 #endif /* !_KAUTH_CRED_T */
370 /* returns the persona ID for the given pesona structure */
371 uid_t
persona_get_id(struct persona
*persona
);
373 /* returns the type of the persona (see enum above: PERSONA_GUEST, etc.) */
374 int persona_get_type(struct persona
*persona
);
376 /* returns ref on kauth_cred_t that must be dropped via kauth_cred_unref() */
377 kauth_cred_t
persona_get_cred(struct persona
*persona
);
379 /* returns a reference that must be released with persona_put() */
380 struct persona
*persona_lookup(uid_t id
);
383 * Search for personas based on name or uid
386 * name: Local login name of the persona.
387 * Set this to NULL to find personas by 'uid'.
389 * uid: UID of the persona.
390 * Set this to -1 to find personas by 'name'
392 * persona: output - array of persona pointers. Each non-NULL value
393 * must* be released with persona_put. This can be NULL.
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)
400 * != 0: failure (BSD errno value ESRCH or EINVAL)
402 int persona_find(const char *login
, uid_t uid
,
403 struct persona
**persona
, size_t *plen
);
405 /* returns a reference that must be released with persona_put() */
406 struct persona
*persona_proc_get(pid_t pid
);
408 /* returns a reference to the persona tied to the current thread (also uses adopted voucher) */
409 struct persona
*current_persona_get(void);
411 /* get a reference to a persona structure */
412 struct persona
*persona_get(struct persona
*persona
);
414 /* release a reference to a persona structure */
415 void persona_put(struct persona
*persona
);
418 * Search for personas of a given type, 'persona_type'.
421 * persona_type: Type of persona (see enum)
423 * persona: output - array of persona pointers. Each non-NULL value
424 * must* be released with persona_put. This can be NULL.
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)
431 * != 0: failure (BSD errno value ESRCH or EINVAL)
433 int persona_find_by_type(persona_type_t persona_type
, struct persona
**persona
,
436 #ifdef XNU_KERNEL_PRIVATE
439 #include <sys/proc_internal.h>
442 * In-kernel persona API
444 extern const uint32_t g_max_personas
;
446 void personas_bootstrap(void);
448 struct persona
*persona_alloc(uid_t id
, const char *login
,
449 persona_type_t type
, char *path
, int *error
);
451 int persona_init_begin(struct persona
*persona
);
452 void persona_init_end(struct persona
*persona
, int error
);
454 struct persona
*persona_lookup_and_invalidate(uid_t id
);
455 int persona_verify_and_set_uniqueness(struct persona
*persona
);
456 boolean_t
persona_is_unique(struct persona
*persona
);
459 proc_has_persona(proc_t p
)
461 if (p
&& p
->p_persona
) {
468 persona_id_from_proc(proc_t p
)
470 if (p
&& p
->p_persona
) {
471 return p
->p_persona
->pna_id
;
473 return PERSONA_ID_NONE
;
476 int persona_proc_inherit(proc_t child
, proc_t parent
);
478 int persona_proc_adopt_id(proc_t p
, uid_t id
,
479 kauth_cred_t auth_override
);
480 int persona_proc_adopt(proc_t p
, struct persona
*persona
,
481 kauth_cred_t auth_override
);
482 int persona_proc_drop(proc_t p
);
484 int persona_set_cred(struct persona
*persona
, kauth_cred_t cred
);
485 int persona_set_cred_from_proc(struct persona
*persona
, proc_t proc
);
487 uid_t
persona_get_uid(struct persona
*persona
);
489 int persona_set_gid(struct persona
*persona
, gid_t gid
);
490 gid_t
persona_get_gid(struct persona
*persona
);
492 int persona_set_groups(struct persona
*persona
, gid_t
*groups
, size_t ngroups
, uid_t gmuid
);
493 int persona_get_groups(struct persona
*persona
, size_t *ngroups
, gid_t
*groups
, size_t groups_sz
);
495 uid_t
persona_get_gmuid(struct persona
*persona
);
497 int persona_get_login(struct persona
*persona
, char login
[MAXLOGNAME
+ 1]);
499 /* returns a reference that must be released with persona_put() */
500 struct persona
*persona_proc_get(pid_t pid
);
502 int persona_find_all(const char *login
, uid_t uid
, persona_type_t persona_type
,
503 struct persona
**persona
, size_t *plen
);
505 #else /* !CONFIG_PERSONAS */
508 proc_has_persona(__unused proc_t p
)
514 persona_id_from_proc(__unused proc_t p
)
516 return PERSONA_ID_NONE
;
519 #endif /* CONFIG_PERSONAS */
520 #endif /* XNU_KERNEL_PRIVATE */
523 #endif /* KERNEL_PRIVATE */
526 #endif /* _SYS_PERSONA_H_ */