]>
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,
47 static struct mgr_config
{
52 static int persona_op_create(struct kpersona_info
*ki
)
57 info("Creating persona...");
58 ki
->persona_info_version
= PERSONA_INFO_V1
;
59 ret
= kpersona_alloc(ki
, &persona_id
);
61 info("Created persona %d:", persona_id
);
62 dump_kpersona(NULL
, ki
);
64 err("kpersona_alloc return %d (errno:%d)", ret
, errno
);
70 static int persona_op_destroy(struct kpersona_info
*ki
)
74 info("Destroying Persona %d...", ki
->persona_id
);
75 ki
->persona_info_version
= PERSONA_INFO_V1
;
76 ret
= kpersona_dealloc(ki
->persona_id
);
78 err_print("destroy failed!");
83 static int persona_op_lookup(struct kpersona_info
*ki
, pid_t pid
, uid_t uid
)
87 info("Looking up persona (pid:%d, uid:%d)", pid
, uid
);
89 ki
->persona_info_version
= PERSONA_INFO_V1
;
90 ret
= kpersona_pidinfo(pid
, ki
);
92 err_print("pidinfo failed!");
94 dump_kpersona("Persona-for-pid:", ki
);
98 size_t npersonas
= ARRAY_SZ(personas
);
99 const char *name
= NULL
;
100 if (ki
->persona_name
[0] != 0)
101 name
= ki
->persona_name
;
103 np
= kpersona_find(name
, uid
, personas
, &npersonas
);
105 err("kpersona_find returned %d (errno:%d)", np
, errno
);
106 info("Found %zu persona%c", npersonas
, npersonas
!= 1 ? 's' : ' ');
109 info("\tpersona[%d]=%d...", np
, personas
[np
]);
110 ki
->persona_info_version
= PERSONA_INFO_V1
;
111 ret
= kpersona_info(personas
[np
], ki
);
113 err("kpersona_info failed (errno:%d) for persona[%d]", errno
, personas
[np
]);
114 dump_kpersona(NULL
, ki
);
122 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
126 * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
128 static void usage_main(const char *progname
, const char *msg
, int verbose
)
130 const char *nm
= basename((char *)progname
);
133 printf("%s\n\n", msg
);
135 printf("%s v%d.%d\n", PROG_NAME
, PROG_VMAJOR
, PROG_VMINOR
);
136 printf("usage: %s [op] [-v] [-i id] [-t type] [-p pid] [-u uid] [-g gid] [-l login] [-G {groupspec}] [-m gmuid]\n", nm
);
140 printf("\t%-15s\tOne of: create | destroy | lookup\n", "[op]");
141 printf("\t%-15s\tBe verbose\n", "-v");
143 printf("\t%-15s\tID of the persona\n", "-i id");
144 printf("\t%-15s\tType of the persona\n", "-t type");
145 printf("\t%-15s\tPID of the process whose persona info to lookup\n", "-p pid");
146 printf("\t%-15s\tUID to use in lookup\n", "-u uid");
147 printf("\t%-15s\tGID of the persona\n", "-g gid");
148 printf("\t%-15s\tLogin name of the persona\n", "-l login");
149 printf("\t%-15s\tGroups to which the persona will belong\n", "-G {groupspec}");
150 printf("\t%-15s\tgroupspec: G1{,G2,G3...}\n", " ");
151 printf("\t%-15s\tUID used for memberd lookup (opt-in to memberd)\n", "-m gmuid");
157 int main(int argc
, char **argv
)
162 const char *op_str
= NULL
;
164 struct kpersona_info kinfo
;
165 uid_t uid
= (uid_t
)-1;
166 pid_t pid
= (pid_t
)-1;
174 err("%s must be run as root", argv
[0] ? basename(argv
[0]) : PROG_NAME
);
177 usage_main(argv
[0], "Not enough arguments", 0);
181 if (strcmp(op_str
, "create") == 0)
182 persona_op
= PERSONA_OP_CREATE
;
183 else if (strcmp(op_str
, "destroy") == 0)
184 persona_op
= PERSONA_OP_DESTROY
;
185 else if (strcmp(op_str
, "lookup") == 0)
186 persona_op
= PERSONA_OP_LOOKUP
;
187 else if (strcmp(op_str
, "help") == 0 || strcmp(op_str
, "-h") == 0)
188 usage_main(argv
[0], NULL
, 1);
190 if (persona_op
<= 0 || persona_op
> PERSONA_OP_MAX
)
191 usage_main(argv
[0], "Invalid [op]", 0);
193 memset(&kinfo
, 0, sizeof(kinfo
));
194 kinfo
.persona_gmuid
= KAUTH_UID_NONE
;
200 while ((ch
= getopt(argc
, argv
, "vi:t:p:u:g:l:G:m:h")) != -1) {
205 err("Invalid Persona ID: %s", optarg
);
206 kinfo
.persona_id
= (uid_t
)ret
;
210 if (ret
<= PERSONA_INVALID
|| ret
> PERSONA_TYPE_MAX
)
211 err("Invalid type specification: %s", optarg
);
212 kinfo
.persona_type
= ret
;
217 err("Invalid PID: %s", optarg
);
223 err("Invalid UID: %s", optarg
);
227 kinfo
.persona_gid
= (gid_t
)atoi(optarg
);
228 if (kinfo
.persona_gid
<= 500)
229 err("Invalid GID: %d", kinfo
.persona_gid
);
232 strncpy(kinfo
.persona_name
, optarg
, MAXLOGNAME
);
235 ret
= parse_groupspec(&kinfo
, optarg
);
237 err("Invalid groupspec: \"%s\"", optarg
);
242 err("Invalid group membership ID: %s", optarg
);
243 kinfo
.persona_gmuid
= (uid_t
)ret
;
250 usage_main(argv
[0], NULL
, 1);
253 printf("Invalid option: '%c'\n", ch
);
254 usage_main(argv
[0], NULL
, 0);
258 if (uid
== (uid_t
)-1)
259 uid
= kinfo
.persona_id
;
261 if (kinfo
.persona_gmuid
&& kinfo
.persona_ngroups
== 0) {
263 * In order to set the group membership UID, we need to set at
264 * least one group: make it equal to either the GID or UID
266 kinfo
.persona_ngroups
= 1;
267 if (kinfo
.persona_gid
)
268 kinfo
.persona_groups
[0] = kinfo
.persona_gid
;
270 kinfo
.persona_groups
[0] = kinfo
.persona_id
;
274 dump_kpersona("Input persona:", &kinfo
);
276 switch (persona_op
) {
277 case PERSONA_OP_CREATE
:
278 ret
= persona_op_create(&kinfo
);
280 case PERSONA_OP_DESTROY
:
281 ret
= persona_op_destroy(&kinfo
);
283 case PERSONA_OP_LOOKUP
:
284 ret
= persona_op_lookup(&kinfo
, pid
, uid
);
287 err("Invalid persona op: %d", persona_op
);