]>
git.saurik.com Git - apple/xnu.git/blob - tools/tests/personas/persona_mgr.c
3 * Tool to manage personas
5 * Jeremy C. Andrus <jeremy_andrus@apple.com>
19 #include <mach/mach.h>
20 #include <mach/task.h>
21 #include <mach/vm_param.h>
22 #include <sys/kauth.h>
23 #include <sys/queue.h>
24 #include <sys/sysctl.h>
25 #include <sys/types.h>
27 #include "persona_test.h"
31 #include <spawn_private.h>
32 #include <sys/persona.h>
33 #include <sys/proc_info.h>
34 #include <sys/spawn_internal.h>
36 #define PROG_NAME "Persona Manager"
41 PERSONA_OP_CREATE
= 1,
42 PERSONA_OP_DESTROY
= 2,
43 PERSONA_OP_LOOKUP
= 3,
44 PERSONA_OP_SUPPORT
= 4,
48 static struct mgr_config
{
54 persona_op_create(struct kpersona_info
*ki
)
59 info("Creating persona...");
60 ki
->persona_info_version
= PERSONA_INFO_V1
;
61 ret
= kpersona_alloc(ki
, &persona_id
);
63 info("Created persona %d:", persona_id
);
64 dump_kpersona(NULL
, ki
);
66 err("kpersona_alloc return %d (errno:%d)", ret
, errno
);
73 persona_op_destroy(struct kpersona_info
*ki
)
77 info("Destroying Persona %d...", ki
->persona_id
);
78 ki
->persona_info_version
= PERSONA_INFO_V1
;
79 ret
= kpersona_dealloc(ki
->persona_id
);
81 err_print("destroy failed!");
88 persona_op_lookup(struct kpersona_info
*ki
, pid_t pid
, uid_t uid
)
92 info("Looking up persona (login:%s, pid:%d, uid:%d)", ki
->persona_name
, pid
, uid
);
94 ki
->persona_info_version
= PERSONA_INFO_V1
;
95 ret
= kpersona_pidinfo(pid
, ki
);
97 err_print("pidinfo failed!");
99 dump_kpersona("Persona-for-pid:", ki
);
104 size_t npersonas
= ARRAY_SZ(personas
);
105 const char *name
= NULL
;
106 if (ki
->persona_name
[0] != 0) {
107 name
= ki
->persona_name
;
110 np
= kpersona_find(name
, uid
, personas
, &npersonas
);
112 err("kpersona_find returned %d (errno:%d)", np
, errno
);
114 info("Found %zu persona%c", npersonas
, npersonas
!= 1 ? 's' : ' ');
117 info("\tpersona[%d]=%d...", np
, personas
[np
]);
118 ki
->persona_info_version
= PERSONA_INFO_V1
;
119 ret
= kpersona_info(personas
[np
], ki
);
121 err("kpersona_info failed (errno:%d) for persona[%d]", errno
, personas
[np
]);
123 dump_kpersona(NULL
, ki
);
131 persona_op_support(void)
134 int ret
= kpersona_get(&pna_id
);
135 if (ret
== 0 || errno
!= ENOSYS
) {
136 info("Persona subsystem is supported (id=%d)", pna_id
);
140 info("Persona subsystem is not supported");
145 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
149 * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
152 usage_main(const char *progname
, const char *msg
, int verbose
)
154 const char *nm
= basename((char *)progname
);
157 printf("%s\n\n", msg
);
160 printf("%s v%d.%d\n", PROG_NAME
, PROG_VMAJOR
, PROG_VMINOR
);
161 printf("usage: %s [op] [-v] [-i id] [-t type] [-p pid] [-u uid] [-g gid] [-l login] [-G {groupspec}] [-m gmuid]\n", nm
);
166 printf("\t%-15s\tOne of: create | destroy | lookup | support\n", "[op]");
167 printf("\t%-15s\tBe verbose\n", "-v");
169 printf("\t%-15s\tID of the persona\n", "-i id");
170 printf("\t%-15s\tType of the persona\n", "-t type");
171 printf("\t%-15s\tPID of the process whose persona info to lookup\n", "-p pid");
172 printf("\t%-15s\tUID to use in lookup\n", "-u uid");
173 printf("\t%-15s\tGID of the persona\n", "-g gid");
174 printf("\t%-15s\tLogin name of the persona\n", "-l login");
175 printf("\t%-15s\tGroups to which the persona will belong\n", "-G {groupspec}");
176 printf("\t%-15s\tgroupspec: G1{,G2,G3...}\n", " ");
177 printf("\t%-15s\tUID used for memberd lookup (opt-in to memberd)\n", "-m gmuid");
184 main(int argc
, char **argv
)
189 const char *op_str
= NULL
;
191 struct kpersona_info kinfo
;
192 uid_t uid
= (uid_t
)-1;
193 pid_t pid
= (pid_t
)-1;
200 if (geteuid() != 0) {
201 err("%s must be run as root", argv
[0] ? basename(argv
[0]) : PROG_NAME
);
205 usage_main(argv
[0], "Not enough arguments", 0);
210 if (strcmp(op_str
, "create") == 0) {
211 persona_op
= PERSONA_OP_CREATE
;
212 } else if (strcmp(op_str
, "destroy") == 0) {
213 persona_op
= PERSONA_OP_DESTROY
;
214 } else if (strcmp(op_str
, "lookup") == 0) {
215 persona_op
= PERSONA_OP_LOOKUP
;
216 } else if (strcmp(op_str
, "support") == 0) {
217 persona_op
= PERSONA_OP_SUPPORT
;
218 } else if (strcmp(op_str
, "help") == 0 || strcmp(op_str
, "-h") == 0) {
219 usage_main(argv
[0], NULL
, 1);
222 if (persona_op
<= 0 || persona_op
> PERSONA_OP_MAX
) {
223 usage_main(argv
[0], "Invalid [op]", 0);
226 memset(&kinfo
, 0, sizeof(kinfo
));
227 kinfo
.persona_gmuid
= KAUTH_UID_NONE
;
233 while ((ch
= getopt(argc
, argv
, "vi:t:p:u:g:l:G:m:h")) != -1) {
238 ret
= PERSONA_ID_NONE
;
240 kinfo
.persona_id
= (uid_t
)ret
;
243 if (strncmp(optarg
, "guest", 6) == 0) {
244 kinfo
.persona_type
= PERSONA_GUEST
;
245 } else if (strncmp(optarg
, "managed", 8) == 0) {
246 kinfo
.persona_type
= PERSONA_MANAGED
;
247 } else if (strncmp(optarg
, "priv", 4) == 0) { /* shortcut... */
248 kinfo
.persona_type
= PERSONA_PRIV
;
249 } else if (strncmp(optarg
, "system", 7) == 0) {
250 kinfo
.persona_type
= PERSONA_SYSTEM
;
253 if (ret
<= PERSONA_INVALID
|| ret
> PERSONA_TYPE_MAX
) {
254 err("Invalid type specification: %s", optarg
);
256 kinfo
.persona_type
= ret
;
262 err("Invalid PID: %s", optarg
);
268 /* allow invalid / -1 as a wildcard for lookup */
269 if (ret
< 0 && persona_op
!= PERSONA_OP_LOOKUP
) {
270 err("Invalid UID:%s (%d)", optarg
, ret
);
275 kinfo
.persona_gid
= (gid_t
)atoi(optarg
);
276 if (kinfo
.persona_gid
<= 500) {
277 err("Invalid GID: %d", kinfo
.persona_gid
);
281 strncpy(kinfo
.persona_name
, optarg
, MAXLOGNAME
);
284 ret
= parse_groupspec(&kinfo
, optarg
);
286 err("Invalid groupspec: \"%s\"", optarg
);
292 err("Invalid group membership ID: %s", optarg
);
294 kinfo
.persona_gmuid
= (uid_t
)ret
;
301 usage_main(argv
[0], NULL
, 1);
304 printf("Invalid option: '%c'\n", ch
);
305 usage_main(argv
[0], NULL
, 0);
309 if (uid
== (uid_t
)-1 && persona_op
!= PERSONA_OP_LOOKUP
) {
310 uid
= kinfo
.persona_id
;
313 if (kinfo
.persona_gmuid
!= KAUTH_UID_NONE
&& kinfo
.persona_ngroups
== 0) {
315 * In order to set the group membership UID, we need to set at
316 * least one group: make it equal to either the GID or UID
318 kinfo
.persona_ngroups
= 1;
319 if (kinfo
.persona_gid
) {
320 kinfo
.persona_groups
[0] = kinfo
.persona_gid
;
322 kinfo
.persona_groups
[0] = kinfo
.persona_id
;
327 dump_kpersona("Input persona:", &kinfo
);
330 switch (persona_op
) {
331 case PERSONA_OP_CREATE
:
332 ret
= persona_op_create(&kinfo
);
334 case PERSONA_OP_DESTROY
:
335 ret
= persona_op_destroy(&kinfo
);
337 case PERSONA_OP_LOOKUP
:
338 ret
= persona_op_lookup(&kinfo
, pid
, uid
);
340 case PERSONA_OP_SUPPORT
:
341 ret
= persona_op_support();
344 err("Invalid persona op: %d", persona_op
);