/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/times.h>
#include <sys/malloc.h>
+#include <bsm/audit_kernel.h>
+
#include <sys/mount.h>
#include <mach/message.h>
+#include <mach/host_security.h>
+
#include <kern/host.h>
/*
register struct setprivexec_args *uap;
register_t *retval;
{
+ AUDIT_ARG(value, uap->flag);
*retval = p->p_debugger;
p->p_debugger = (uap->flag != 0);
return(0);
return (0);
}
+/* Get an arbitary pid's process group id */
+struct getpgid_args {
+ pid_t pid;
+};
+
+int
+getpgid(p, uap, retval)
+ 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.
+ */
+struct getsid_args {
+ pid_t pid;
+};
+
+int
+getsid(p, uap, retval)
+ 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 */
getuid(p, uap, retval)
struct proc *p;
register_t *retval;
{
- if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
+ 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);
uap->pgid = targp->p_pid;
else if (uap->pgid != targp->p_pid)
if ((pgrp = pgfind(uap->pgid)) == 0 ||
- pgrp->pg_session != curp->p_session)
+ pgrp->pg_session != curp->p_session)
return (EPERM);
return (enterpgrp(targp, uap->pgid, 0));
}
int error;
uid = uap->uid;
+ AUDIT_ARG(uid, uid, 0, 0, 0);
if (uid != pc->p_ruid &&
(error = suser(pc->pc_ucred, &p->p_acflag)))
return (error);
* 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);
pcred_writelock(p);
(void)chgproccnt(pc->p_ruid, -1);
(void)chgproccnt(uid, 1);
int error;
euid = uap->euid;
+ AUDIT_ARG(uid, 0, euid, 0, 0);
if (euid != pc->p_ruid && euid != pc->p_svuid &&
(error = suser(pc->pc_ucred, &p->p_acflag)))
return (error);
int error;
gid = uap->gid;
+ AUDIT_ARG(gid, gid, 0, 0, 0);
if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
return (error);
pcred_writelock(p);
int error;
egid = uap->egid;
+ AUDIT_ARG(gid, 0, egid, 0, 0);
if (egid != pc->p_rgid && egid != pc->p_svgid &&
(error = suser(pc->pc_ucred, &p->p_acflag)))
return (error);
if (error = suser(pc->pc_ucred, &p->p_acflag))
return (error);
ngrp = uap->gidsetsize;
- if (ngrp < 1 || ngrp > NGROUPS)
+ if (ngrp > NGROUPS)
return (EINVAL);
new = crget();
- error = copyin((caddr_t)uap->gidset,
- (caddr_t)new->cr_groups, ngrp * sizeof(gid_t));
- if (error) {
- crfree(new);
- return (error);
+
+ if ( ngrp < 1 ) {
+ ngrp = 1;
+ }
+ else {
+ error = copyin((caddr_t)uap->gidset,
+ (caddr_t)new->cr_groups, ngrp * sizeof(gid_t));
+ if (error) {
+ crfree(new);
+ return (error);
+ }
}
new->cr_ngroups = ngrp;
+ AUDIT_ARG(groupset, new->cr_groups, ngrp);
pcred_writelock(p);
old = pc->pc_ucred;
new->cr_uid = old->cr_uid;
return (newcr);
}
+/*
+ * compare two cred structs
+ */
+int
+crcmp(cr1, cr2)
+ struct ucred *cr1;
+ struct ucred *cr2;
+{
+ int i;
+
+ if (cr1 == cr2)
+ return 0;
+ if (cr1 == NOCRED || cr1 == FSCRED ||
+ cr2 == NOCRED || cr2 == FSCRED)
+ return 1;
+ if (cr1->cr_uid != cr2->cr_uid)
+ return 1;
+ if (cr1->cr_ngroups != cr2->cr_ngroups)
+ return 1;
+ // XXX assumes groups will always be listed in some order
+ for (i=0; i < cr1->cr_ngroups; i++)
+ if (cr1->cr_groups[i] != cr2->cr_groups[i])
+ return 1;
+ return (0);
+}
+
/*
* Get login name, if available.
*/
error = copyinstr((caddr_t) 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 == ENAMETOOLONG)
+ 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 */
-void
+kern_return_t
set_security_token(struct proc * p)
{
security_token_t sec_token;
+ audit_token_t audit_token;
sec_token.val[0] = p->p_ucred->cr_uid;
- sec_token.val[1] = p->p_ucred->cr_gid;
- (void)host_security_set_task_token(host_security_self(),
+ sec_token.val[1] = p->p_ucred->cr_gid;
+
+ /*
+ * 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_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_cred->p_ruid;
+ audit_token.val[4] = p->p_cred->p_rgid;
+ audit_token.val[5] = p->p_pid;
+ audit_token.val[6] = p->p_au->ai_asid;
+ audit_token.val[7] = p->p_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_NULL :
host_priv_self());
}
+
+
+/*
+ * Fill in a struct xucred based on a struct ucred.
+ */
+__private_extern__
+void
+cru2x(struct ucred *cr, struct xucred *xcr)
+{
+
+ bzero(xcr, sizeof(*xcr));
+ xcr->cr_version = XUCRED_VERSION;
+ xcr->cr_uid = cr->cr_uid;
+ xcr->cr_ngroups = cr->cr_ngroups;
+ bcopy(cr->cr_groups, xcr->cr_groups, sizeof(xcr->cr_groups));
+}