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>
41 PERSONA_TYPE_MAX
= PERSONA_SYSTEM
,
44 #define PERSONA_ID_NONE ((uid_t)-1)
46 struct kpersona_info
{
47 uint32_t persona_info_version
;
49 uid_t persona_id
; /* overlaps with UID */
52 uint32_t persona_ngroups
;
53 gid_t persona_groups
[NGROUPS
];
55 char persona_name
[MAXLOGNAME
+1];
57 /* TODO: MAC policies?! */
60 #define PERSONA_INFO_V1 1
61 #define PERSONA_INFO_V1_SIZE (sizeof(struct kpersona_info))
64 #define PERSONA_OP_ALLOC 1
65 #define PERSONA_OP_DEALLOC 2
66 #define PERSONA_OP_GET 3
67 #define PERSONA_OP_INFO 4
68 #define PERSONA_OP_PIDINFO 5
69 #define PERSONA_OP_FIND 6
73 * user space persona interface
77 * kpersona_alloc: Allocate a new in-kernel persona
80 * info: Pointer to persona info structure describing the
81 * attributes of the persona to create / allocate.
83 * id: output: set to the ID of the created persona
86 * The 'persona_id' field of the 'info' parameter is ignored.
92 int kpersona_alloc(struct kpersona_info
*info
, uid_t
*id
);
95 * kpersona_dealloc: delete / destroy an in-kernel persona
98 * id: the ID of the persona to destroy
104 int kpersona_dealloc(uid_t id
);
108 * kpersona_get: retrieve the persona with which the current thread is running
111 * id: output: will be filled with current thread's persona
112 * (or current processes persona) on success.
115 * < 0: Thread is not running under any persona
116 * 0: Success (uuid is filled with running persona UUID)
118 int kpersona_get(uid_t
*id
);
122 * kpersona_info: gather info about the given persona
125 * id: ID of the persona to investigate
127 * info: output: filled in with persona attributes on success.
133 int kpersona_info(uid_t id
, struct kpersona_info
*info
);
137 * kpersona_pidinfo: gather persona info about the given PID
140 * pid: PID of the process whose persona info we're to return
142 * info: output: filled in with persona attributes on success.
148 int kpersona_pidinfo(pid_t pid
, struct kpersona_info
*info
);
152 * kpersona_find: lookup the kernel's UUID of a persona
155 * name: Local login name of the persona.
156 * Set this to NULL to find personas by 'uid'.
158 * uid: UID of the persona.
159 * Set this to -1 to find personas by 'name'
161 * id: output: the ID(s) matching the input parameters
162 * idlen: input - size of 'id' buffer (in number of IDs)
163 * output - the total required size of the 'id' buffer
164 * (in number of IDs) - may be larger than input size
166 * At least one of 'name' or 'uid' must be set.
170 * >= 0: The number of IDs found to match the input parameters
172 int kpersona_find(const char *name
, uid_t uid
, uid_t
*id
, size_t *idlen
);
175 #ifdef KERNEL_PRIVATE
176 /* XNU + kext private interface */
177 #include <sys/cdefs.h>
178 #include <sys/kauth.h>
179 #include <libkern/libkern.h>
182 #define persona_dbg(fmt, ...) \
183 printf("[%4d] %s: " fmt "\n", \
184 current_proc() ? current_proc()->p_pid : -1, \
185 __func__, ## __VA_ARGS__)
187 #define persona_dbg(fmt, ...) do { } while (0)
193 #ifdef XNU_KERNEL_PRIVATE
194 /* only XNU proper needs to see the persona structure */
196 int32_t pna_refcount
;
201 char pna_login
[MAXLOGNAME
+1];
203 kauth_cred_t pna_cred
;
206 int pna_cred_locked
; /* set upon first adoption */
208 LIST_ENTRY(persona
) pna_list
;
210 /* this could go away if we used a coalition */
211 LIST_HEAD(, proc
) pna_members
;
216 * We can add things here such as PID maps, UID maps, etc.
223 #define persona_lock(persona) lck_mtx_lock(&(persona)->pna_lock)
224 #define persona_unlock(persona) lck_mtx_unlock(&(persona)->pna_lock)
225 #define persona_try_lock(persona) lck_mtx_try_lock(&(persona)->pna_lock)
227 #define persona_lock_assert_held(persona) \
228 LCK_MTX_ASSERT(&(persona)->pna_lock, LCK_MTX_ASSERT_OWNED)
231 static inline const char *persona_desc(struct persona
*persona
, int locked
)
236 if (persona
->pna_desc
[0] != 0)
237 return persona
->pna_desc
;
240 persona_lock(persona
);
241 if (persona
->pna_desc
[0] != 0)
244 char *p
= &persona
->pna_desc
[0];
245 char *end
= p
+ sizeof(persona
->pna_desc
) - 1;
248 p
+= snprintf(p
, end
- p
, "%s/%d:%d",
250 kauth_cred_getuid(persona
->pna_cred
),
251 kauth_cred_getgid(persona
->pna_cred
));
257 persona_unlock(persona
);
259 return persona
->pna_desc
;
261 #else /* !PERSONA_DEBUG */
262 static inline const char *persona_desc(struct persona
*persona
, int locked
)
270 #else /* !XNU_KERNEL_PRIVATE */
271 /* kexts should only see an opaque persona structure */
277 #ifndef _KAUTH_CRED_T
278 #define _KAUTH_CRED_T
279 typedef struct ucred
*kauth_cred_t
;
280 #endif /* !_KAUTH_CRED_T */
282 /* returns the persona ID for the given pesona structure */
283 uid_t
persona_get_id(struct persona
*persona
);
285 /* returns the type of the persona (see enum above: PERSONA_GUEST, etc.) */
286 int persona_get_type(struct persona
*persona
);
288 /* returns ref on kauth_cred_t that must be dropped via kauth_cred_unref() */
289 kauth_cred_t
persona_get_cred(struct persona
*persona
);
291 /* returns a reference that must be released with persona_put() */
292 struct persona
*persona_lookup(uid_t id
);
295 * returns non-zero on error, on success returns 0 and updates 'plen' to
296 * total found (could be more than original value of 'plen')
298 int persona_find(const char *login
, uid_t uid
,
299 struct persona
**persona
, size_t *plen
);
301 /* returns a reference to the persona tied to the current thread */
302 struct persona
*current_persona_get(void);
304 /* get a reference to a persona structure */
305 struct persona
*persona_get(struct persona
*persona
);
307 /* release a reference to a persona structure */
308 void persona_put(struct persona
*persona
);
310 #ifdef XNU_KERNEL_PRIVATE
313 #include <sys/proc_internal.h>
316 * In-kernel persona API
318 extern uint32_t g_max_personas
;
319 extern struct persona
*g_system_persona
;
321 void personas_bootstrap(void);
323 struct persona
*persona_alloc(uid_t id
, const char *login
,
324 int type
, int *error
);
326 struct persona
*persona_lookup_and_invalidate(uid_t id
);
328 static inline int proc_has_persona(proc_t p
)
330 if (p
&& p
->p_persona
)
335 static inline uid_t
persona_id_from_proc(proc_t p
)
337 if (p
&& p
->p_persona
)
338 return p
->p_persona
->pna_id
;
339 return PERSONA_ID_NONE
;
342 int persona_proc_inherit(proc_t child
, proc_t parent
);
344 int persona_proc_adopt_id(proc_t p
, uid_t id
,
345 kauth_cred_t auth_override
);
346 int persona_proc_adopt(proc_t p
, struct persona
*persona
,
347 kauth_cred_t auth_override
);
348 int persona_proc_drop(proc_t p
);
350 int persona_set_cred(struct persona
*persona
, kauth_cred_t cred
);
351 int persona_set_cred_from_proc(struct persona
*persona
, proc_t proc
);
353 uid_t
persona_get_uid(struct persona
*persona
);
355 int persona_set_gid(struct persona
*persona
, gid_t gid
);
356 gid_t
persona_get_gid(struct persona
*persona
);
358 int persona_set_groups(struct persona
*persona
, gid_t
*groups
, unsigned ngroups
, uid_t gmuid
);
359 int persona_get_groups(struct persona
*persona
, unsigned *ngroups
, gid_t
*groups
, unsigned groups_sz
);
361 uid_t
persona_get_gmuid(struct persona
*persona
);
363 int persona_get_login(struct persona
*persona
, char login
[MAXLOGNAME
+1]);
365 /* returns a reference that must be released with persona_put() */
366 struct persona
*persona_proc_get(pid_t pid
);
368 #else /* !CONFIG_PERSONAS */
370 static inline int proc_has_persona(__unused proc_t p
)
375 static inline uid_t
persona_id_from_proc(__unused proc_t p
)
377 return PERSONA_ID_NONE
;
380 #endif /* CONFIG_PERSONAS */
381 #endif /* XNU_KERNEL_PRIVATE */
384 #endif /* KERNEL_PRIVATE */
387 #endif /* _SYS_PERSONA_H_ */