X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/a39ff7e25e19b3a8c3020042a3872ca9ec9659f1..f427ee49d309d8fc33ebf3042c3a775f2f530ded:/bsd/sys/persona.h diff --git a/bsd/sys/persona.h b/bsd/sys/persona.h index 4e3d71f46..9a3292fec 100644 --- a/bsd/sys/persona.h +++ b/bsd/sys/persona.h @@ -31,15 +31,27 @@ #ifdef PRIVATE #include +#ifdef KERNEL +__enum_decl(persona_type_t, int, { +#else /* !KERNEL */ enum { - PERSONA_INVALID = 0, - PERSONA_GUEST = 1, - PERSONA_MANAGED = 2, - PERSONA_PRIV = 3, - PERSONA_SYSTEM = 4, - - PERSONA_TYPE_MAX = PERSONA_SYSTEM, +#endif /* KERNEL */ + PERSONA_INVALID = 0, + PERSONA_GUEST = 1, + PERSONA_MANAGED = 2, + PERSONA_PRIV = 3, + PERSONA_SYSTEM = 4, + PERSONA_DEFAULT = 5, + PERSONA_SYSTEM_PROXY = 6, + PERSONA_SYS_EXT = 7, + PERSONA_ENTERPRISE = 8, + + PERSONA_TYPE_MAX = PERSONA_ENTERPRISE, +#ifdef KERNEL +}); +#else /* !KERNEL */ }; +#endif /* KERNEL */ #define PERSONA_ID_NONE ((uid_t)-1) @@ -52,7 +64,7 @@ struct kpersona_info { uint32_t persona_ngroups; gid_t persona_groups[NGROUPS]; uid_t persona_gmuid; - char persona_name[MAXLOGNAME+1]; + char persona_name[MAXLOGNAME + 1]; /* TODO: MAC policies?! */ }; @@ -62,11 +74,16 @@ struct kpersona_info { #define PERSONA_OP_ALLOC 1 -#define PERSONA_OP_DEALLOC 2 -#define PERSONA_OP_GET 3 -#define PERSONA_OP_INFO 4 -#define PERSONA_OP_PIDINFO 5 -#define PERSONA_OP_FIND 6 +#define PERSONA_OP_PALLOC 2 +#define PERSONA_OP_DEALLOC 3 +#define PERSONA_OP_GET 4 +#define PERSONA_OP_INFO 5 +#define PERSONA_OP_PIDINFO 6 +#define PERSONA_OP_FIND 7 +#define PERSONA_OP_GETPATH 8 +#define PERSONA_OP_FIND_BY_TYPE 9 + +#define PERSONA_MGMT_ENTITLEMENT "com.apple.private.persona-mgmt" #ifndef KERNEL /* @@ -91,6 +108,29 @@ struct kpersona_info { */ int kpersona_alloc(struct kpersona_info *info, uid_t *id); +/* + * kpersona_palloc: Allocate a new in-kernel persona with a directory + * pathname + * + * Parameters: + * info: Pointer to persona info structure describing the + * attributes of the persona to create / allocate. + * + * path: Pointer to directory name that stores persona specific + * data. Assumes path buffer length = MAXPATHLEN and is a + * null-terminated string. + * + * id: output: set to the ID of the created persona + * + * Note: + * The 'persona_id' field of the 'info' parameter is ignored. + * + * Return: + * != 0: ERROR + * == 0: Success + */ +int kpersona_palloc(struct kpersona_info *info, uid_t *id, char path[MAXPATHLEN]); + /* * kpersona_dealloc: delete / destroy an in-kernel persona * @@ -103,13 +143,15 @@ int kpersona_alloc(struct kpersona_info *info, uid_t *id); */ int kpersona_dealloc(uid_t id); - /* * kpersona_get: retrieve the persona with which the current thread is running * + * To find the proc's persona id use kpersona_pidinfo + * * Parameters: - * id: output: will be filled with current thread's persona - * (or current processes persona) on success. + * id: output: will be filled with the persona id from the voucher adopted + * on the current thread. If that voucher contains no persona information + * or there is no such voucher, then it defaults to the proc's persona id. * * Return: * < 0: Thread is not running under any persona @@ -117,12 +159,29 @@ int kpersona_dealloc(uid_t id); */ int kpersona_get(uid_t *id); +/* + * kpersona_get_path: retrieve the given persona's path + * + * Parameters: + * id: ID of the persona + * + * path: output: filled in with path on success. + * Assumes path buffer length = MAXPATHLEN + * + * Return: + * < 0: Error + * 0: Success + */ +int kpersona_getpath(uid_t id, char path[MAXPATHLEN]); /* * kpersona_info: gather info about the given persona * * Parameters: * id: ID of the persona to investigate + * If set to 0, it uses persona id from the voucher adopted on the current + * thread. If that voucher contains no persona information or there is no + * such voucher, then it defaults to the proc's persona id. * * info: output: filled in with persona attributes on success. * @@ -132,7 +191,6 @@ int kpersona_get(uid_t *id); */ int kpersona_info(uid_t id, struct kpersona_info *info); - /* * kpersona_pidinfo: gather persona info about the given PID * @@ -147,7 +205,6 @@ int kpersona_info(uid_t id, struct kpersona_info *info); */ int kpersona_pidinfo(pid_t pid, struct kpersona_info *info); - /* * kpersona_find: lookup the kernel's UUID of a persona * @@ -159,6 +216,8 @@ int kpersona_pidinfo(pid_t pid, struct kpersona_info *info); * Set this to -1 to find personas by 'name' * * id: output: the ID(s) matching the input parameters + * This can be NULL + * * idlen: input - size of 'id' buffer (in number of IDs) * output - the total required size of the 'id' buffer * (in number of IDs) - may be larger than input size @@ -170,6 +229,24 @@ int kpersona_pidinfo(pid_t pid, struct kpersona_info *info); * >= 0: The number of IDs found to match the input parameters */ int kpersona_find(const char *name, uid_t uid, uid_t *id, size_t *idlen); + +/* + * kpersona_find_by_type: lookup the persona ids by type + * + * Parameters: + * persona_type: Type of persona id (see enum) + * + * id: output: the ID(s) matching the input parameters + * This can be NULL + * + * idlen: input - size of 'id' buffer (in number of IDs) + * output - the total required size of the 'id' buffer + * (in number of IDs) - may be larger than input size + * Return: + * < 0: ERROR + * >= 0: The number of IDs found to match the input parameters + */ +int kpersona_find_by_type(int persona_type, uid_t *id, size_t *idlen); #endif /* !KERNEL */ #ifdef KERNEL_PRIVATE @@ -177,10 +254,12 @@ int kpersona_find(const char *name, uid_t uid, uid_t *id, size_t *idlen); #include #include #include +#include #ifdef PERSONA_DEBUG +#include #define persona_dbg(fmt, ...) \ - printf("[%4d] %s: " fmt "\n", \ + os_log(OS_LOG_DEFAULT, "[%4d] %s: " fmt "\n", \ current_proc() ? current_proc()->p_pid : -1, \ __func__, ## __VA_ARGS__) #else @@ -193,12 +272,13 @@ int kpersona_find(const char *name, uid_t uid, uid_t *id, size_t *idlen); #ifdef XNU_KERNEL_PRIVATE /* only XNU proper needs to see the persona structure */ struct persona { - int32_t pna_refcount; + os_refcnt_t pna_refcount; int32_t pna_valid; uid_t pna_id; - int pna_type; - char pna_login[MAXLOGNAME+1]; + persona_type_t pna_type; + char pna_login[MAXLOGNAME + 1]; + char *pna_path; kauth_cred_t pna_cred; uid_t pna_pgid; @@ -228,38 +308,46 @@ struct persona { LCK_MTX_ASSERT(&(persona)->pna_lock, LCK_MTX_ASSERT_OWNED) #ifdef PERSONA_DEBUG -static inline const char *persona_desc(struct persona *persona, int locked) +static inline const char * +persona_desc(struct persona *persona, int locked) { - if (!persona) + if (!persona) { return ""; + } - if (persona->pna_desc[0] != 0) + if (persona->pna_desc[0] != 0) { return persona->pna_desc; + } - if (!locked) + if (!locked) { persona_lock(persona); - if (persona->pna_desc[0] != 0) + } + if (persona->pna_desc[0] != 0) { goto out_unlock; + } char *p = &persona->pna_desc[0]; char *end = p + sizeof(persona->pna_desc) - 1; *end = 0; - p += snprintf(p, end - p, "%s/%d:%d", - persona->pna_login, - kauth_cred_getuid(persona->pna_cred), - kauth_cred_getgid(persona->pna_cred)); + p += scnprintf(p, end - p, "%s/%d:%d", + persona->pna_login, + kauth_cred_getuid(persona->pna_cred), + kauth_cred_getgid(persona->pna_cred)); - if (p <= end) + if (p <= end) { *p = 0; + } out_unlock: - if (!locked) + if (!locked) { persona_unlock(persona); + } return persona->pna_desc; } #else /* !PERSONA_DEBUG */ -static inline const char *persona_desc(struct persona *persona, int locked) +static inline const char * +persona_desc(struct persona *persona, int locked) { (void)persona; (void)locked; @@ -275,9 +363,9 @@ struct persona; __BEGIN_DECLS #ifndef _KAUTH_CRED_T -#define _KAUTH_CRED_T +#define _KAUTH_CRED_T typedef struct ucred *kauth_cred_t; -#endif /* !_KAUTH_CRED_T */ +#endif /* !_KAUTH_CRED_T */ /* returns the persona ID for the given pesona structure */ uid_t persona_get_id(struct persona *persona); @@ -292,13 +380,32 @@ kauth_cred_t persona_get_cred(struct persona *persona); struct persona *persona_lookup(uid_t id); /* - * returns non-zero on error, on success returns 0 and updates 'plen' to - * total found (could be more than original value of 'plen') + * Search for personas based on name or uid + * + * Parameters: + * name: Local login name of the persona. + * Set this to NULL to find personas by 'uid'. + * + * uid: UID of the persona. + * Set this to -1 to find personas by 'name' + * + * persona: output - array of persona pointers. Each non-NULL value + * must* be released with persona_put. This can be NULL. + * + * plen: input - size of 'persona' buffer (in number of pointers) + * output - the total required size of the 'persona' buffer (could be larger than input value) + * + * Return: + * 0: Success + * != 0: failure (BSD errno value ESRCH or EINVAL) */ int persona_find(const char *login, uid_t uid, - struct persona **persona, size_t *plen); + struct persona **persona, size_t *plen); -/* returns a reference to the persona tied to the current thread */ +/* returns a reference that must be released with persona_put() */ +struct persona *persona_proc_get(pid_t pid); + +/* returns a reference to the persona tied to the current thread (also uses adopted voucher) */ struct persona *current_persona_get(void); /* get a reference to a persona structure */ @@ -307,6 +414,25 @@ struct persona *persona_get(struct persona *persona); /* release a reference to a persona structure */ void persona_put(struct persona *persona); +/* + * Search for personas of a given type, 'persona_type'. + * + * Parameters: + * persona_type: Type of persona (see enum) + * + * persona: output - array of persona pointers. Each non-NULL value + * must* be released with persona_put. This can be NULL. + * + * plen: input - size of 'persona' buffer (in number of pointers) + * output - the total required size of the 'persona' buffer (could be larger than input value) + * + * Return: + * 0: Success + * != 0: failure (BSD errno value ESRCH or EINVAL) + */ +int persona_find_by_type(persona_type_t persona_type, struct persona **persona, + size_t *plen); + #ifdef XNU_KERNEL_PRIVATE #if CONFIG_PERSONAS @@ -315,36 +441,44 @@ void persona_put(struct persona *persona); /* * In-kernel persona API */ -extern uint32_t g_max_personas; -extern struct persona *g_system_persona; +extern const uint32_t g_max_personas; void personas_bootstrap(void); struct persona *persona_alloc(uid_t id, const char *login, - int type, int *error); + persona_type_t type, char *path, int *error); + +int persona_init_begin(struct persona *persona); +void persona_init_end(struct persona *persona, int error); struct persona *persona_lookup_and_invalidate(uid_t id); +int persona_verify_and_set_uniqueness(struct persona *persona); +boolean_t persona_is_unique(struct persona *persona); -static inline int proc_has_persona(proc_t p) +static inline int +proc_has_persona(proc_t p) { - if (p && p->p_persona) + if (p && p->p_persona) { return 1; + } return 0; } -static inline uid_t persona_id_from_proc(proc_t p) +static inline uid_t +persona_id_from_proc(proc_t p) { - if (p && p->p_persona) + if (p && p->p_persona) { return p->p_persona->pna_id; + } return PERSONA_ID_NONE; } int persona_proc_inherit(proc_t child, proc_t parent); int persona_proc_adopt_id(proc_t p, uid_t id, - kauth_cred_t auth_override); + kauth_cred_t auth_override); int persona_proc_adopt(proc_t p, struct persona *persona, - kauth_cred_t auth_override); + kauth_cred_t auth_override); int persona_proc_drop(proc_t p); int persona_set_cred(struct persona *persona, kauth_cred_t cred); @@ -355,24 +489,29 @@ uid_t persona_get_uid(struct persona *persona); int persona_set_gid(struct persona *persona, gid_t gid); gid_t persona_get_gid(struct persona *persona); -int persona_set_groups(struct persona *persona, gid_t *groups, unsigned ngroups, uid_t gmuid); -int persona_get_groups(struct persona *persona, unsigned *ngroups, gid_t *groups, unsigned groups_sz); +int persona_set_groups(struct persona *persona, gid_t *groups, size_t ngroups, uid_t gmuid); +int persona_get_groups(struct persona *persona, size_t *ngroups, gid_t *groups, size_t groups_sz); uid_t persona_get_gmuid(struct persona *persona); -int persona_get_login(struct persona *persona, char login[MAXLOGNAME+1]); +int persona_get_login(struct persona *persona, char login[MAXLOGNAME + 1]); /* returns a reference that must be released with persona_put() */ struct persona *persona_proc_get(pid_t pid); +int persona_find_all(const char *login, uid_t uid, persona_type_t persona_type, + struct persona **persona, size_t *plen); + #else /* !CONFIG_PERSONAS */ -static inline int proc_has_persona(__unused proc_t p) +static inline int +proc_has_persona(__unused proc_t p) { return 0; } -static inline uid_t persona_id_from_proc(__unused proc_t p) +static inline uid_t +persona_id_from_proc(__unused proc_t p) { return PERSONA_ID_NONE; }