/* * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ /* * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_prot.c 8.9 (Berkeley) 2/14/95 */ /* * System calls related to processes and protection */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int groupmember(gid_t gid, kauth_cred_t cred); int is_suser(void); int is_suser1(void); extern int prepare_profile_database(int user); /* * setprivexec: (dis)allow this process to hold * task, thread, or execption ports of processes about to exec. */ int setprivexec(struct proc *p, struct setprivexec_args *uap, register_t *retval) { AUDIT_ARG(value, uap->flag); *retval = p->p_debugger; p->p_debugger = (uap->flag != 0); return(0); } /* ARGSUSED */ int getpid(struct proc *p, __unused struct getpid_args *uap, register_t *retval) { *retval = p->p_pid; return (0); } /* ARGSUSED */ int getppid(struct proc *p, __unused struct getppid_args *uap, register_t *retval) { *retval = p->p_pptr->p_pid; return (0); } /* Get process group ID; note that POSIX getpgrp takes no parameter */ int getpgrp(struct proc *p, __unused struct getpgrp_args *uap, register_t *retval) { *retval = p->p_pgrp->pg_id; return (0); } /* Get an arbitary pid's process group id */ int getpgid(struct proc *p, struct getpgid_args *uap, register_t *retval) { struct proc *pt; pt = p; if (uap->pid == 0) goto found; if ((pt = pfind(uap->pid)) == 0) return (ESRCH); found: *retval = pt->p_pgrp->pg_id; return (0); } /* * Get an arbitary pid's session id. */ int getsid(struct proc *p, struct getsid_args *uap, register_t *retval) { struct proc *pt; pt = p; if (uap->pid == 0) goto found; if ((pt = pfind(uap->pid)) == 0) return (ESRCH); found: *retval = pt->p_session->s_sid; return (0); } /* ARGSUSED */ int getuid(__unused struct proc *p, __unused struct getuid_args *uap, register_t *retval) { *retval = kauth_getruid(); return (0); } /* ARGSUSED */ int geteuid(__unused struct proc *p, __unused struct geteuid_args *uap, register_t *retval) { *retval = kauth_getuid(); return (0); } /* * Return the per-thread override identity. */ int gettid(__unused struct proc *p, struct gettid_args *uap, register_t *retval) { struct uthread *uthread = get_bsdthread_info(current_thread()); int error; /* * If this thread is not running with an override identity, we can't * return one to the caller, so return an error instead. */ if (!(uthread->uu_flag & UT_SETUID)) return (ESRCH); if ((error = suword(uap->uidp, uthread->uu_ucred->cr_ruid))) return (error); if ((error = suword(uap->gidp, uthread->uu_ucred->cr_rgid))) return (error); *retval = 0; return (0); } /* ARGSUSED */ int getgid(__unused struct proc *p, __unused struct getgid_args *uap, register_t *retval) { *retval = kauth_getrgid(); return (0); } /* * Get effective group ID. The "egid" is groups[0], and could be obtained * via getgroups. This syscall exists because it is somewhat painful to do * correctly in a library function. */ /* ARGSUSED */ int getegid(struct proc *p, __unused struct getegid_args *uap, register_t *retval) { *retval = kauth_getgid(); return (0); } int getgroups(__unused struct proc *p, struct getgroups_args *uap, register_t *retval) { register int ngrp; int error; kauth_cred_t cred; /* grab reference while we muck around with the credential */ cred = kauth_cred_get_with_ref(); if ((ngrp = uap->gidsetsize) == 0) { *retval = cred->cr_ngroups; kauth_cred_rele(cred); return (0); } if (ngrp < cred->cr_ngroups) { kauth_cred_rele(cred); return (EINVAL); } ngrp = cred->cr_ngroups; if ((error = copyout((caddr_t)cred->cr_groups, uap->gidset, ngrp * sizeof(gid_t)))) { kauth_cred_rele(cred); return (error); } kauth_cred_rele(cred); *retval = ngrp; return (0); } /* * Return the per-thread/per-process supplementary groups list. */ #warning XXX implement int getsgroups(__unused struct proc *p, __unused struct getsgroups_args *uap, __unused register_t *retval) { /* XXX implement */ return(ENOTSUP); } /* * Return the per-thread/per-process whiteout groups list. */ #warning XXX implement int getwgroups(__unused struct proc *p, __unused struct getwgroups_args *uap, __unused register_t *retval) { /* XXX implement */ return(ENOTSUP); } /* ARGSUSED */ int setsid(struct proc *p, __unused struct setsid_args *uap, register_t *retval) { if (p->p_pgid == p->p_pid || pgfind(p->p_pid) || p->p_flag & P_INVFORK) { return (EPERM); } else { (void)enterpgrp(p, p->p_pid, 1); *retval = p->p_pid; return (0); } } /* * set process group (setpgid/old setpgrp) * * caller does setpgid(targpid, targpgid) * * pid must be caller or child of caller (ESRCH) * if a child * pid must be in same session (EPERM) * pid can't have done an exec (EACCES) * ig pgid is -ve return EINVAL (as per SUV spec) * if pgid != pid * there must exist some pid in same session having pgid (EPERM) * pid must not be session leader (EPERM) */ /* ARGSUSED */ int setpgid(struct proc *curp, register struct setpgid_args *uap, __unused register_t *retval) { register struct proc *targp; /* target process */ register struct pgrp *pgrp; /* target pgrp */ if (uap->pid != 0 && uap->pid != curp->p_pid) { if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) return (ESRCH); if (targp->p_session != curp->p_session) return (EPERM); if (targp->p_flag & P_EXEC) return (EACCES); } else targp = curp; if (SESS_LEADER(targp)) return (EPERM); if (uap->pgid < 0) return(EINVAL); if (uap->pgid == 0) uap->pgid = targp->p_pid; else if (uap->pgid != targp->p_pid) if ((pgrp = pgfind(uap->pgid)) == 0 || pgrp->pg_session != curp->p_session) return (EPERM); return (enterpgrp(targp, uap->pgid, 0)); } int issetugid(struct proc *p, __unused struct issetugid_args *uap, register_t *retval) { /* * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, * we use P_SUGID because we consider changing the owners as * "tainting" as well. * This is significant for procs that start as root and "become" * a user without an exec - programs cannot know *everything* * that libc *might* have put in their data segment. */ *retval = (p->p_flag & P_SUGID) ? 1 : 0; return (0); } /* ARGSUSED */ int setuid(struct proc *p, struct setuid_args *uap, __unused register_t *retval) { register uid_t uid; int error; kauth_cred_t my_cred, my_new_cred; uid = uap->uid; AUDIT_ARG(uid, uid, 0, 0, 0); if (uid != p->p_ucred->cr_ruid && (error = suser(p->p_ucred, &p->p_acflag))) return (error); /* * Everything's okay, do it. * Transfer proc count to new user. * Copy credentials so other references do not see our changes. */ /* prepare app access profile files */ prepare_profile_database(uap->uid); (void)chgproccnt(kauth_getruid(), -1); (void)chgproccnt(uid, 1); /* get current credential and take a reference while we muck with it */ for (;;) { my_cred = kauth_cred_proc_ref(p); /* * set the credential with new info. If there is no change we get back * the same credential we passed in. */ my_new_cred = kauth_cred_setuid(my_cred, uid); if (my_cred != my_new_cred) { proc_lock(p); /* need to protect for a race where another thread also changed * the credential after we took our reference. If p_ucred has * changed then we should restart this again with the new cred. */ if (p->p_ucred != my_cred) { proc_unlock(p); kauth_cred_rele(my_cred); kauth_cred_rele(my_new_cred); /* try again */ continue; } p->p_ucred = my_new_cred; p->p_flag |= P_SUGID; proc_unlock(p); } /* drop our extra reference */ kauth_cred_rele(my_cred); break; } set_security_token(p); return (0); } /* ARGSUSED */ int seteuid(struct proc *p, struct seteuid_args *uap, __unused register_t *retval) { register uid_t euid; int error; kauth_cred_t my_cred, my_new_cred; euid = uap->euid; AUDIT_ARG(uid, 0, euid, 0, 0); if (euid != p->p_ucred->cr_ruid && euid != p->p_ucred->cr_svuid && (error = suser(p->p_ucred, &p->p_acflag))) return (error); /* * Everything's okay, do it. Copy credentials so other references do * not see our changes. get current credential and take a reference * while we muck with it */ for (;;) { my_cred = kauth_cred_proc_ref(p); /* * set the credential with new info. If there is no change we get back * the same credential we passed in. */ my_new_cred = kauth_cred_seteuid(p->p_ucred, euid); if (my_cred != my_new_cred) { proc_lock(p); /* need to protect for a race where another thread also changed * the credential after we took our reference. If p_ucred has * changed then we should restart this again with the new cred. */ if (p->p_ucred != my_cred) { proc_unlock(p); kauth_cred_rele(my_cred); kauth_cred_rele(my_new_cred); /* try again */ continue; } p->p_ucred = my_new_cred; p->p_flag |= P_SUGID; proc_unlock(p); } /* drop our extra reference */ kauth_cred_rele(my_cred); break; } set_security_token(p); return (0); } /* ARGSUSED */ int setgid(struct proc *p, struct setgid_args *uap, __unused register_t *retval) { register gid_t gid; int error; kauth_cred_t my_cred, my_new_cred; gid = uap->gid; AUDIT_ARG(gid, gid, 0, 0, 0); if (gid != p->p_ucred->cr_rgid && (error = suser(p->p_ucred, &p->p_acflag))) return (error); /* get current credential and take a reference while we muck with it */ for (;;) { my_cred = kauth_cred_proc_ref(p); /* * set the credential with new info. If there is no change we get back * the same credential we passed in. */ my_new_cred = kauth_cred_setgid(p->p_ucred, gid); if (my_cred != my_new_cred) { proc_lock(p); /* need to protect for a race where another thread also changed * the credential after we took our reference. If p_ucred has * changed then we should restart this again with the new cred. */ if (p->p_ucred != my_cred) { proc_unlock(p); kauth_cred_rele(my_cred); kauth_cred_rele(my_new_cred); /* try again */ continue; } p->p_ucred = my_new_cred; p->p_flag |= P_SUGID; proc_unlock(p); } /* drop our extra reference */ kauth_cred_rele(my_cred); break; } set_security_token(p); return (0); } /* ARGSUSED */ int setegid(struct proc *p, struct setegid_args *uap, __unused register_t *retval) { register gid_t egid; int error; kauth_cred_t my_cred, my_new_cred; egid = uap->egid; AUDIT_ARG(gid, 0, egid, 0, 0); if (egid != p->p_ucred->cr_rgid && egid != p->p_ucred->cr_svgid && (error = suser(p->p_ucred, &p->p_acflag))) return (error); /* get current credential and take a reference while we muck with it */ for (;;) { my_cred = kauth_cred_proc_ref(p); /* * set the credential with new info. If there is no change we get back * the same credential we passed in. */ my_new_cred = kauth_cred_setegid(p->p_ucred, egid); if (my_cred != my_new_cred) { proc_lock(p); /* need to protect for a race where another thread also changed * the credential after we took our reference. If p_ucred has * changed then we should restart this again with the new cred. */ if (p->p_ucred != my_cred) { proc_unlock(p); kauth_cred_rele(my_cred); kauth_cred_rele(my_new_cred); /* try again */ continue; } p->p_ucred = my_new_cred; p->p_flag |= P_SUGID; proc_unlock(p); } /* drop our extra reference */ kauth_cred_rele(my_cred); break; } set_security_token(p); return (0); } /* * Set the per-thread override identity. The first parameter can be the * current real UID, KAUTH_UID_NONE, or, if the caller is priviledged, it * can be any UID. If it is KAUTH_UID_NONE, then as a special case, this * means "revert to the per process credential"; otherwise, if permitted, * it changes the effective, real, and saved UIDs and GIDs for the current * thread to the requested UID and single GID, and clears all other GIDs. */ int settid(struct proc *p, struct settid_args *uap, __unused register_t *retval) { kauth_cred_t uc; struct uthread *uthread = get_bsdthread_info(current_thread()); register uid_t uid; register gid_t gid; uid = uap->uid; gid = uap->gid; AUDIT_ARG(uid, uid, gid, gid, 0); if (suser(p->p_ucred, &p->p_acflag) != 0) { return (EPERM); } if (uid == KAUTH_UID_NONE) { /* must already be assuming another identity in order to revert back */ if ((uthread->uu_flag & UT_SETUID) == 0) return (EPERM); /* revert to delayed binding of process credential */ uc = kauth_cred_proc_ref(p); kauth_cred_rele(uthread->uu_ucred); uthread->uu_ucred = uc; uthread->uu_flag &= ~UT_SETUID; } else { kauth_cred_t my_cred, my_new_cred; /* cannot already be assuming another identity */ if ((uthread->uu_flag & UT_SETUID) != 0) { return (EPERM); } /* * get a new credential instance from the old if this one changes else * kauth_cred_setuidgid returns the same credential. we take an extra * reference on the current credential while we muck wit it here. */ kauth_cred_ref(uthread->uu_ucred); my_cred = uthread->uu_ucred; my_new_cred = kauth_cred_setuidgid(my_cred, uid, gid); if (my_cred != my_new_cred) uthread->uu_ucred = my_new_cred; uthread->uu_flag |= UT_SETUID; /* drop our extra reference */ kauth_cred_rele(my_cred); } /* * XXX should potentially set per thread security token (there is * XXX none). * XXX it is unclear whether P_SUGID should be st at this point; * XXX in theory, it is being deprecated. */ return (0); } /* * Set the per-thread override identity. Use this system call for a thread to * assume the identity of another process or to revert back to normal identity * of the current process. * When the "assume" argument is non zero the current thread will assume the * identity of the process represented by the pid argument. * When the assume argument is zero we revert back to our normal identity. */ int settid_with_pid(struct proc *p, struct settid_with_pid_args *uap, __unused register_t *retval) { proc_t target_proc; struct uthread *uthread = get_bsdthread_info(current_thread()); kauth_cred_t my_cred, my_target_cred, my_new_cred; AUDIT_ARG(pid, uap->pid); AUDIT_ARG(value, uap->assume); if (suser(p->p_ucred, &p->p_acflag) != 0) { return (EPERM); } /* * XXX should potentially set per thread security token (there is * XXX none). * XXX it is unclear whether P_SUGID should be st at this point; * XXX in theory, it is being deprecated. */ /* * assume argument tells us to assume the identity of the process with the * id passed in the pid argument. */ if (uap->assume != 0) { /* can't do this if we have already assumed an identity */ if ((uthread->uu_flag & UT_SETUID) != 0) return (EPERM); target_proc = pfind(uap->pid); /* can't assume the identity of the kernel process */ if (target_proc == NULL || target_proc == kernproc) { return (ESRCH); } /* * take a reference on the credential used in our target process then use * it as the identity for our current thread. */ kauth_cred_ref(uthread->uu_ucred); my_cred = uthread->uu_ucred; my_target_cred = kauth_cred_proc_ref(target_proc); my_new_cred = kauth_cred_setuidgid(my_cred, my_target_cred->cr_uid, my_target_cred->cr_gid); if (my_cred != my_new_cred) uthread->uu_ucred = my_new_cred; uthread->uu_flag |= UT_SETUID; /* drop our extra references */ kauth_cred_rele(my_cred); kauth_cred_rele(my_target_cred); return (0); } /* we are reverting back to normal mode of operation where delayed binding * of the process credential sets the credential in the thread (uu_ucred) */ if ((uthread->uu_flag & UT_SETUID) == 0) return (EPERM); /* revert to delayed binding of process credential */ my_new_cred = kauth_cred_proc_ref(p); kauth_cred_rele(uthread->uu_ucred); uthread->uu_ucred = my_new_cred; uthread->uu_flag &= ~UT_SETUID; return (0); } /* ARGSUSED */ static int setgroups1(struct proc *p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __unused register_t *retval) { register u_int ngrp; gid_t newgroups[NGROUPS] = { 0 }; int error; kauth_cred_t my_cred, my_new_cred; if ((error = suser(p->p_ucred, &p->p_acflag))) return (error); ngrp = gidsetsize; if (ngrp > NGROUPS) return (EINVAL); if ( ngrp < 1 ) { ngrp = 1; } else { error = copyin(gidset, (caddr_t)newgroups, ngrp * sizeof(gid_t)); if (error) { return (error); } } /* get current credential and take a reference while we muck with it */ for (;;) { my_cred = kauth_cred_proc_ref(p); /* * set the credential with new info. If there is no change we get back * the same credential we passed in. */ my_new_cred = kauth_cred_setgroups(p->p_ucred, &newgroups[0], ngrp, gmuid); if (my_cred != my_new_cred) { proc_lock(p); /* need to protect for a race where another thread also changed * the credential after we took our reference. If p_ucred has * changed then we should restart this again with the new cred. */ if (p->p_ucred != my_cred) { proc_unlock(p); kauth_cred_rele(my_cred); kauth_cred_rele(my_new_cred); /* try again */ continue; } p->p_ucred = my_new_cred; p->p_flag |= P_SUGID; proc_unlock(p); } /* drop our extra reference */ kauth_cred_rele(my_cred); break; } AUDIT_ARG(groupset, p->p_ucred->cr_groups, ngrp); set_security_token(p); return (0); } int initgroups(struct proc *p, struct initgroups_args *uap, __unused register_t *retval) { return(setgroups1(p, uap->gidsetsize, uap->gidset, uap->gmuid, retval)); } int setgroups(struct proc *p, struct setgroups_args *uap, __unused register_t *retval) { return(setgroups1(p, uap->gidsetsize, uap->gidset, KAUTH_UID_NONE, retval)); } /* * Set the per-thread/per-process supplementary groups list. */ #warning XXX implement int setsgroups(__unused struct proc *p, __unused struct setsgroups_args *uap, __unused register_t *retval) { return(ENOTSUP); } /* * Set the per-thread/per-process whiteout groups list. */ #warning XXX implement int setwgroups(__unused struct proc *p, __unused struct setwgroups_args *uap, __unused register_t *retval) { return(ENOTSUP); } /* * Check if gid is a member of the group set. * * XXX This interface is going away */ int groupmember(gid_t gid, kauth_cred_t cred) { int is_member; if (kauth_cred_ismember_gid(cred, gid, &is_member) == 0 && is_member) return (1); return (0); } /* * Test whether the specified credentials imply "super-user" * privilege; if so, and we have accounting info, set the flag * indicating use of super-powers. * Returns 0 or error. * * XXX This interface is going away */ int suser(kauth_cred_t cred, u_short *acflag) { #if DIAGNOSTIC if (cred == NOCRED || cred == FSCRED) panic("suser"); #endif if (kauth_cred_getuid(cred) == 0) { if (acflag) *acflag |= ASU; return (0); } return (EPERM); } int is_suser(void) { struct proc *p = current_proc(); if (!p) return (0); return (suser(p->p_ucred, &p->p_acflag) == 0); } int is_suser1(void) { struct proc *p = current_proc(); if (!p) return (0); return (suser(p->p_ucred, &p->p_acflag) == 0 || p->p_ucred->cr_ruid == 0 || p->p_ucred->cr_svuid == 0); } /* * Get login name, if available. */ /* ARGSUSED */ int getlogin(struct proc *p, struct getlogin_args *uap, __unused register_t *retval) { if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login)) uap->namelen = sizeof (p->p_pgrp->pg_session->s_login); return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, uap->namebuf, uap->namelen)); } /* * Set login name. */ /* ARGSUSED */ int setlogin(struct proc *p, struct setlogin_args *uap, __unused register_t *retval) { int error; int dummy=0; if ((error = suser(p->p_ucred, &p->p_acflag))) return (error); error = copyinstr(uap->namebuf, (caddr_t) p->p_pgrp->pg_session->s_login, sizeof (p->p_pgrp->pg_session->s_login) - 1, (size_t *)&dummy); if (!error) AUDIT_ARG(text, p->p_pgrp->pg_session->s_login); else if (error == ENAMETOOLONG) error = EINVAL; return (error); } /* Set the secrity token of the task with current euid and eguid */ /* * XXX This needs to change to give the task a reference and/or an opaque * XXX identifier. */ int set_security_token(struct proc * p) { security_token_t sec_token; audit_token_t audit_token; /* * Don't allow a vfork child to override the parent's token settings * (since they share a task). Instead, the child will just have to * suffer along using the parent's token until the exec(). It's all * undefined behavior anyway, right? */ if (p->task == current_task()) { uthread_t uthread; uthread = (uthread_t)get_bsdthread_info(current_thread()); if (uthread->uu_flag & UT_VFORK) return (1); } /* XXX mach_init doesn't have a p_ucred when it calls this function */ if (p->p_ucred != NOCRED && p->p_ucred != FSCRED) { sec_token.val[0] = kauth_cred_getuid(p->p_ucred); sec_token.val[1] = p->p_ucred->cr_gid; } else { sec_token.val[0] = 0; sec_token.val[1] = 0; } /* * The current layout of the Mach audit token explicitly * adds these fields. But nobody should rely on such * a literal representation. Instead, the BSM library * provides a function to convert an audit token into * a BSM subject. Use of that mechanism will isolate * the user of the trailer from future representation * changes. */ audit_token.val[0] = p->p_ucred->cr_au.ai_auid; audit_token.val[1] = p->p_ucred->cr_uid; audit_token.val[2] = p->p_ucred->cr_gid; audit_token.val[3] = p->p_ucred->cr_ruid; audit_token.val[4] = p->p_ucred->cr_rgid; audit_token.val[5] = p->p_pid; audit_token.val[6] = p->p_ucred->cr_au.ai_asid; audit_token.val[7] = p->p_ucred->cr_au.ai_termid.port; return (host_security_set_task_token(host_security_self(), p->task, sec_token, audit_token, (sec_token.val[0]) ? HOST_PRIV_NULL : host_priv_self()) != KERN_SUCCESS); } /* * Fill in a struct xucred based on a kauth_cred_t. */ __private_extern__ void cru2x(kauth_cred_t cr, struct xucred *xcr) { bzero(xcr, sizeof(*xcr)); xcr->cr_version = XUCRED_VERSION; xcr->cr_uid = kauth_cred_getuid(cr); xcr->cr_ngroups = cr->cr_ngroups; bcopy(cr->cr_groups, xcr->cr_groups, sizeof(xcr->cr_groups)); }