]> git.saurik.com Git - apple/xnu.git/blame - bsd/sys/persona.h
xnu-4570.71.2.tar.gz
[apple/xnu.git] / bsd / sys / persona.h
CommitLineData
490019cf
A
1/*
2 * Copyright (c) 2015 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#ifndef _SYS_PERSONA_H_
29#define _SYS_PERSONA_H_
30
31#ifdef PRIVATE
32#include <sys/param.h>
33
34enum {
35 PERSONA_INVALID = 0,
36 PERSONA_GUEST = 1,
37 PERSONA_MANAGED = 2,
38 PERSONA_PRIV = 3,
39 PERSONA_SYSTEM = 4,
40
41 PERSONA_TYPE_MAX = PERSONA_SYSTEM,
42};
43
44#define PERSONA_ID_NONE ((uid_t)-1)
45
46struct kpersona_info {
47 uint32_t persona_info_version;
48
49 uid_t persona_id; /* overlaps with UID */
50 int persona_type;
51 gid_t persona_gid;
52 uint32_t persona_ngroups;
53 gid_t persona_groups[NGROUPS];
54 uid_t persona_gmuid;
55 char persona_name[MAXLOGNAME+1];
56
57 /* TODO: MAC policies?! */
58};
59
60#define PERSONA_INFO_V1 1
61#define PERSONA_INFO_V1_SIZE (sizeof(struct kpersona_info))
62
63
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
70
71#ifndef KERNEL
72/*
73 * user space persona interface
74 */
75
76/*
77 * kpersona_alloc: Allocate a new in-kernel persona
78 *
79 * Parameters:
80 * info: Pointer to persona info structure describing the
81 * attributes of the persona to create / allocate.
82 *
83 * id: output: set to the ID of the created persona
84 *
85 * Note:
86 * The 'persona_id' field of the 'info' parameter is ignored.
87 *
88 * Return:
89 * != 0: ERROR
90 * == 0: Success
91 */
92int kpersona_alloc(struct kpersona_info *info, uid_t *id);
93
94/*
95 * kpersona_dealloc: delete / destroy an in-kernel persona
96 *
97 * Parameters:
98 * id: the ID of the persona to destroy
99 *
100 * Return:
101 * < 0: ERROR
102 * 0: Success
103 */
104int kpersona_dealloc(uid_t id);
105
106
107/*
108 * kpersona_get: retrieve the persona with which the current thread is running
109 *
110 * Parameters:
111 * id: output: will be filled with current thread's persona
112 * (or current processes persona) on success.
113 *
114 * Return:
115 * < 0: Thread is not running under any persona
116 * 0: Success (uuid is filled with running persona UUID)
117 */
118int kpersona_get(uid_t *id);
119
120
121/*
122 * kpersona_info: gather info about the given persona
123 *
124 * Parameters:
125 * id: ID of the persona to investigate
126 *
127 * info: output: filled in with persona attributes on success.
128 *
129 * Return:
130 * < 0: ERROR
131 * 0: Success
132 */
133int kpersona_info(uid_t id, struct kpersona_info *info);
134
135
136/*
137 * kpersona_pidinfo: gather persona info about the given PID
138 *
139 * Parameters:
140 * pid: PID of the process whose persona info we're to return
141 *
142 * info: output: filled in with persona attributes on success.
143 *
144 * Return:
145 * < 0: ERROR
146 * 0: Success
147 */
148int kpersona_pidinfo(pid_t pid, struct kpersona_info *info);
149
150
151/*
152 * kpersona_find: lookup the kernel's UUID of a persona
153 *
154 * Parameters:
155 * name: Local login name of the persona.
156 * Set this to NULL to find personas by 'uid'.
157 *
158 * uid: UID of the persona.
159 * Set this to -1 to find personas by 'name'
160 *
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
165 * Note:
166 * At least one of 'name' or 'uid' must be set.
167 *
168 * Return:
169 * < 0: ERROR
170 * >= 0: The number of IDs found to match the input parameters
171 */
172int kpersona_find(const char *name, uid_t uid, uid_t *id, size_t *idlen);
173#endif /* !KERNEL */
174
175#ifdef KERNEL_PRIVATE
176/* XNU + kext private interface */
177#include <sys/cdefs.h>
178#include <sys/kauth.h>
179#include <libkern/libkern.h>
180
181#ifdef PERSONA_DEBUG
182#define persona_dbg(fmt, ...) \
183 printf("[%4d] %s: " fmt "\n", \
184 current_proc() ? current_proc()->p_pid : -1, \
185 __func__, ## __VA_ARGS__)
186#else
187#define persona_dbg(fmt, ...) do { } while (0)
188#endif
189
190/*
191 * Persona
192 */
193#ifdef XNU_KERNEL_PRIVATE
194/* only XNU proper needs to see the persona structure */
195struct persona {
196 int32_t pna_refcount;
197 int32_t pna_valid;
198
199 uid_t pna_id;
200 int pna_type;
201 char pna_login[MAXLOGNAME+1];
202
203 kauth_cred_t pna_cred;
204 uid_t pna_pgid;
205
206 int pna_cred_locked; /* set upon first adoption */
207
208 LIST_ENTRY(persona) pna_list;
209
210 /* this could go away if we used a coalition */
211 LIST_HEAD(, proc) pna_members;
212
213 lck_mtx_t pna_lock;
214
215 /*
216 * We can add things here such as PID maps, UID maps, etc.
217 */
218#ifdef PERSONA_DEBUG
219 char pna_desc[128];
220#endif
221};
222
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)
226
227#define persona_lock_assert_held(persona) \
5ba3f43e 228 LCK_MTX_ASSERT(&(persona)->pna_lock, LCK_MTX_ASSERT_OWNED)
490019cf
A
229
230#ifdef PERSONA_DEBUG
231static inline const char *persona_desc(struct persona *persona, int locked)
232{
233 if (!persona)
234 return "<none>";
235
236 if (persona->pna_desc[0] != 0)
237 return persona->pna_desc;
238
239 if (!locked)
240 persona_lock(persona);
241 if (persona->pna_desc[0] != 0)
242 goto out_unlock;
243
244 char *p = &persona->pna_desc[0];
245 char *end = p + sizeof(persona->pna_desc) - 1;
246
247 *end = 0;
248 p += snprintf(p, end - p, "%s/%d:%d",
249 persona->pna_login,
250 kauth_cred_getuid(persona->pna_cred),
251 kauth_cred_getgid(persona->pna_cred));
252
253 if (p <= end)
254 *p = 0;
255out_unlock:
256 if (!locked)
257 persona_unlock(persona);
258
259 return persona->pna_desc;
260}
261#else /* !PERSONA_DEBUG */
262static inline const char *persona_desc(struct persona *persona, int locked)
263{
264 (void)persona;
265 (void)locked;
266 return "<persona>";
267}
268#endif
269
270#else /* !XNU_KERNEL_PRIVATE */
271/* kexts should only see an opaque persona structure */
272struct persona;
273#endif
274
275__BEGIN_DECLS
276
277#ifndef _KAUTH_CRED_T
278#define _KAUTH_CRED_T
279typedef struct ucred *kauth_cred_t;
280#endif /* !_KAUTH_CRED_T */
281
282/* returns the persona ID for the given pesona structure */
283uid_t persona_get_id(struct persona *persona);
284
285/* returns the type of the persona (see enum above: PERSONA_GUEST, etc.) */
286int persona_get_type(struct persona *persona);
287
288/* returns ref on kauth_cred_t that must be dropped via kauth_cred_unref() */
289kauth_cred_t persona_get_cred(struct persona *persona);
290
291/* returns a reference that must be released with persona_put() */
292struct persona *persona_lookup(uid_t id);
293
294/*
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')
297 */
298int persona_find(const char *login, uid_t uid,
299 struct persona **persona, size_t *plen);
300
301/* returns a reference to the persona tied to the current thread */
302struct persona *current_persona_get(void);
303
304/* get a reference to a persona structure */
305struct persona *persona_get(struct persona *persona);
306
307/* release a reference to a persona structure */
308void persona_put(struct persona *persona);
309
310#ifdef XNU_KERNEL_PRIVATE
311
312#if CONFIG_PERSONAS
313#include <sys/proc_internal.h>
314
315/*
316 * In-kernel persona API
317 */
318extern uint32_t g_max_personas;
319extern struct persona *g_system_persona;
320
321void personas_bootstrap(void);
322
323struct persona *persona_alloc(uid_t id, const char *login,
324 int type, int *error);
a39ff7e2
A
325
326struct persona *persona_lookup_and_invalidate(uid_t id);
490019cf
A
327
328static inline int proc_has_persona(proc_t p)
329{
330 if (p && p->p_persona)
331 return 1;
332 return 0;
333}
334
335static inline uid_t persona_id_from_proc(proc_t p)
336{
337 if (p && p->p_persona)
338 return p->p_persona->pna_id;
339 return PERSONA_ID_NONE;
340}
341
342int persona_proc_inherit(proc_t child, proc_t parent);
343
344int persona_proc_adopt_id(proc_t p, uid_t id,
345 kauth_cred_t auth_override);
346int persona_proc_adopt(proc_t p, struct persona *persona,
347 kauth_cred_t auth_override);
348int persona_proc_drop(proc_t p);
349
350int persona_set_cred(struct persona *persona, kauth_cred_t cred);
351int persona_set_cred_from_proc(struct persona *persona, proc_t proc);
352
353uid_t persona_get_uid(struct persona *persona);
354
355int persona_set_gid(struct persona *persona, gid_t gid);
356gid_t persona_get_gid(struct persona *persona);
357
527f9951
A
358int persona_set_groups(struct persona *persona, gid_t *groups, unsigned ngroups, uid_t gmuid);
359int persona_get_groups(struct persona *persona, unsigned *ngroups, gid_t *groups, unsigned groups_sz);
490019cf
A
360
361uid_t persona_get_gmuid(struct persona *persona);
362
363int persona_get_login(struct persona *persona, char login[MAXLOGNAME+1]);
364
365/* returns a reference that must be released with persona_put() */
366struct persona *persona_proc_get(pid_t pid);
367
368#else /* !CONFIG_PERSONAS */
369
370static inline int proc_has_persona(__unused proc_t p)
371{
372 return 0;
373}
374
375static inline uid_t persona_id_from_proc(__unused proc_t p)
376{
377 return PERSONA_ID_NONE;
378}
379
380#endif /* CONFIG_PERSONAS */
381#endif /* XNU_KERNEL_PRIVATE */
382__END_DECLS
383
384#endif /* KERNEL_PRIVATE */
385
386#endif /* PRIVATE */
387#endif /* _SYS_PERSONA_H_ */