Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 12 May 2001 23:41:51 -0400 (EDT)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        audit@FreeBSD.org
Subject:   RE: Patch to eliminate struct pcred (fwd)
Message-ID:  <Pine.NEB.3.96L.1010512233942.49820B-100000@fledge.watson.org>
In-Reply-To: <Pine.NEB.3.96L.1010509132551.11741x-100000@fledge.watson.org>

next in thread | previous in thread | raw e-mail | index | archive | help

Attached, please find revision 4 of the pcred merge into ucred patch.
Differences from pcred.3.diff are:

- add alpha/osf1 support to pcred patch, missed in previous iterations
- fix bug in newcred/oldcred handling introduced in kern_exec in
  pcred.3.diff

Otherwise the changes remain the same.  I notice that one of the comments
I added about the saved uid behavior is consistent with the concerns
expressed by Ruslan, and I think we should revisit these after I finish
the pcred merge.  For now, I'm attempting to maintain consistent behavior
with the pre-pcred-merge, but we should discuss this in detail and figure
out whether current behavior is "right", and document it properly if so,
and fix it if not.

Robert N M Watson             FreeBSD Core Team, TrustedBSD Project
robert@fledge.watson.org      NAI Labs, Safeport Network Services

? compile/GENERIC
? compile/LINT
? i386/conf/LINT
Index: alpha/osf1/osf1_misc.c
===================================================================
RCS file: /home/ncvs/src/sys/alpha/osf1/osf1_misc.c,v
retrieving revision 1.13
diff -u -r1.13 osf1_misc.c
--- alpha/osf1/osf1_misc.c	2001/05/01 08:11:49	1.13
+++ alpha/osf1/osf1_misc.c	2001/05/13 03:23:41
@@ -1054,29 +1054,32 @@
 {
 	int error;
 	uid_t uid;
-	register struct pcred *pc;
+	struct ucred *oldcred, *newcred;
 
 	uid = SCARG(uap, uid);
-	pc = p->p_cred;
+	oldcred = p->p_ucred;
 
 	if ((error = suser(p)) != 0 &&
-	    uid != pc->p_ruid && uid != pc->p_svuid)
+	    uid != oldcred->cr_ruid && uid != oldcred->cr_svuid)
 		return (error);
 
+	newcred = crdup(oldcred);
 	if (error == 0) {
-		if (uid != pc->p_ruid) {
-			change_ruid(p, uid);
+		if (uid != oldcred->cr_ruid) {
+			change_ruid(newcred, uid);
 			setsugid(p);
 		}
-		if (pc->p_svuid != uid) {
-			pc->p_svuid = uid;
+		if (oldcred->cr_svuid != uid) {
+			change_svuid(newcred, uid);
 			setsugid(p);
 		}
 	}
-	if (pc->pc_ucred->cr_uid != uid) {
-		change_euid(p, uid);
+	if (newcred->cr_uid != uid) {
+		change_euid(newcred, uid);
 		setsugid(p);
 	}
+	p->p_ucred = newcred;
+	crfree(oldcred);
 	return (0);
 }
 
@@ -1095,22 +1098,32 @@
 {
 	int error;
 	gid_t gid;
-	register struct pcred *pc;
+	struct ucred *oldcred, *newcred;
 
 	gid = SCARG(uap, gid);
-	pc = p->p_cred;
+	oldcred = p->p_ucred;
 
 	if (((error = suser(p)) != 0 ) &&
-		gid != pc->p_rgid && gid != pc->p_svgid)
+		gid != oldcred->cr_rgid && gid != oldcred->cr_svgid)
 		return (error);
 
-	pc->pc_ucred = crcopy(pc->pc_ucred);
-	pc->pc_ucred->cr_gid = gid;
+	newcred = crdup(oldcred);
 	if (error == 0) {
-		pc->p_rgid = gid;
-		pc->p_svgid = gid;
+		if (gid != oldcred->cr_rgid) {
+			change_rgid(newcred, gid);
+			setsugid(p);
+		}
+		if (oldcred->cr_svgid != gid) {
+			change_svgid(newcred, gid);
+			setsugid(p);
+		}
+	}
+	if (newcred->cr_groups[0] != gid) {
+		change_egid(newcred, gid);
+		setsugid(p);
 	}
-	setsugid(p);
+	p->p_ucred = newcred;
+	crfree(oldcred);
 	return (0);
 }
 
Index: compat/linprocfs/linprocfs_misc.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linprocfs/linprocfs_misc.c,v
retrieving revision 1.24
diff -u -r1.24 linprocfs_misc.c
--- compat/linprocfs/linprocfs_misc.c	2001/05/01 08:11:51	1.24
+++ compat/linprocfs/linprocfs_misc.c	2001/05/13 03:23:46
@@ -444,14 +444,14 @@
 	PROC_LOCK(p);
 	sbuf_printf(&sb, "PPid:\t%d\n",		p->p_pptr ?
 						p->p_pptr->p_pid : 0);
-	sbuf_printf(&sb, "Uid:\t%d %d %d %d\n", p->p_cred->p_ruid,
+	sbuf_printf(&sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
 			                        p->p_ucred->cr_uid,
-			                        p->p_cred->p_svuid,
+			                        p->p_ucred->cr_svuid,
 			                        /* FreeBSD doesn't have fsuid */
 				                p->p_ucred->cr_uid);
-	sbuf_printf(&sb, "Gid:\t%d %d %d %d\n", p->p_cred->p_rgid,
+	sbuf_printf(&sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
 			                        p->p_ucred->cr_gid,
-			                        p->p_cred->p_svgid,
+			                        p->p_ucred->cr_svgid,
 			                        /* FreeBSD doesn't have fsgid */
 				                p->p_ucred->cr_gid);
 	sbuf_cat(&sb, "Groups:\t");
@@ -543,7 +543,7 @@
 	char *freepath = NULL;
 
 	p = PFIND(pfs->pfs_pid);
-	if (p == NULL || p->p_cred == NULL || p->p_ucred == NULL) {
+	if (p == NULL || p->p_ucred == NULL) {
 		if (p != NULL)
 			PROC_UNLOCK(p);
 		printf("doexelink: pid %d disappeared\n", pfs->pfs_pid);
Index: compat/linprocfs/linprocfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linprocfs/linprocfs_vnops.c,v
retrieving revision 1.23
diff -u -r1.23 linprocfs_vnops.c
--- compat/linprocfs/linprocfs_vnops.c	2001/05/04 05:19:22	1.23
+++ compat/linprocfs/linprocfs_vnops.c	2001/05/13 03:23:46
@@ -432,7 +432,7 @@
 		procp = PFIND(pfs->pfs_pid);
 		if (procp == NULL)
 			return (ENOENT);
-		if (procp->p_cred == NULL || procp->p_ucred == NULL) {
+		if (procp->p_ucred == NULL) {
 			PROC_UNLOCK(procp);
 			return (ENOENT);
 		}
Index: compat/linux/linux_misc.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_misc.c,v
retrieving revision 1.101
diff -u -r1.101 linux_misc.c
--- compat/linux/linux_misc.c	2001/05/01 08:11:51	1.101
+++ compat/linux/linux_misc.c	2001/05/13 03:23:47
@@ -958,12 +958,11 @@
 	struct proc *p;
 	struct linux_setgroups_args *uap;
 {
-	struct pcred *pc;
+	struct ucred *newcred, *oldcred = p->p_ucred;
 	linux_gid_t linux_gidset[NGROUPS];
 	gid_t *bsd_gidset;
 	int ngrp, error;
 
-	pc = p->p_cred;
 	ngrp = uap->gidsetsize;
 
 	/*
@@ -972,22 +971,22 @@
 	 * Keep cr_groups[0] unchanged to prevent that.
 	 */
 
-	if ((error = suser_xxx(NULL, p, PRISON_ROOT)) != 0)
+	if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
 		return (error);
 
 	if (ngrp >= NGROUPS)
 		return (EINVAL);
 
-	pc->pc_ucred = crcopy(pc->pc_ucred);
+	newcred = crdup(oldcred);
 	if (ngrp > 0) {
 		error = copyin((caddr_t)uap->gidset, (caddr_t)linux_gidset,
 			       ngrp * sizeof(linux_gid_t));
 		if (error)
 			return (error);
 
-		pc->pc_ucred->cr_ngroups = ngrp + 1;
+		newcred->cr_ngroups = ngrp + 1;
 
-		bsd_gidset = pc->pc_ucred->cr_groups;
+		bsd_gidset = newcred->cr_groups;
 		ngrp--;
 		while (ngrp >= 0) {
 			bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
@@ -995,9 +994,13 @@
 		}
 	}
 	else
-		pc->pc_ucred->cr_ngroups = 1;
+		newcred->cr_ngroups = 1;
 
 	setsugid(p);
+
+	p->p_ucred = newcred;
+	crfree(oldcred);
+
 	return (0);
 }
 
@@ -1006,14 +1009,14 @@
 	struct proc *p;
 	struct linux_getgroups_args *uap;
 {
-	struct pcred *pc;
+	struct ucred *cred;
 	linux_gid_t linux_gidset[NGROUPS];
 	gid_t *bsd_gidset;
 	int bsd_gidsetsz, ngrp, error;
 
-	pc = p->p_cred;
-	bsd_gidset = pc->pc_ucred->cr_groups;
-	bsd_gidsetsz = pc->pc_ucred->cr_ngroups - 1;
+	cred = p->p_ucred;
+	bsd_gidset = cred->cr_groups;
+	bsd_gidsetsz = cred->cr_ngroups - 1;
 
 	/*
 	 * cr_groups[0] holds egid. Returning the whole set
Index: compat/svr4/svr4_misc.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/svr4/svr4_misc.c,v
retrieving revision 1.30
diff -u -r1.30 svr4_misc.c
--- compat/svr4/svr4_misc.c	2001/05/01 08:11:52	1.30
+++ compat/svr4/svr4_misc.c	2001/05/13 03:23:48
@@ -1283,7 +1283,7 @@
 			/*
 			 * Decrement the count of procs running with this uid.
 			 */
-			(void)chgproccnt(q->p_cred->p_uidinfo, -1, 0);
+			(void)chgproccnt(q->p_ucred->cr_ruidinfo, -1, 0);
 
 			/*
 			 * Release reference to text vnode.
@@ -1294,13 +1294,8 @@
 			/*
 			 * Free up credentials.
 			 */
-			PROC_LOCK(q);
-			if (--q->p_cred->p_refcnt == 0) {
-				crfree(q->p_ucred);
-				uifree(q->p_cred->p_uidinfo);
-				FREE(q->p_cred, M_SUBPROC);
-				q->p_cred = NULL;
-			}
+			crfree(q->p_ucred);
+			q->p_ucred = NULL;
 
 			/*
 			 * Remove unused arguments
Index: compat/svr4/svr4_sysvec.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/svr4/svr4_sysvec.c,v
retrieving revision 1.20
diff -u -r1.20 svr4_sysvec.c
--- compat/svr4/svr4_sysvec.c	2001/02/24 22:20:02	1.20
+++ compat/svr4/svr4_sysvec.c	2001/05/13 03:23:48
@@ -213,10 +213,10 @@
 	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
 	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
 	AUXARGS_ENTRY(pos, AT_BASE, args->base);
-	AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid);
-	AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid);
-	AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid);
-	AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid);
+	AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
+	AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
+	AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
+	AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
 	AUXARGS_ENTRY(pos, AT_NULL, 0);
 	
 	free(imgp->auxargs, M_TEMP);      
Index: ddb/db_ps.c
===================================================================
RCS file: /home/ncvs/src/sys/ddb/db_ps.c,v
retrieving revision 1.22
diff -u -r1.22 db_ps.c
--- ddb/db_ps.c	2001/03/28 09:17:49	1.22
+++ ddb/db_ps.c	2001/05/13 03:23:50
@@ -95,7 +95,7 @@
 
 		db_printf("%5d %8p %8p %4d %5d %5d %06x  %d",
 		    p->p_pid, (volatile void *)p, (void *)p->p_addr,
-		    p->p_cred ? p->p_cred->p_ruid : 0, pp->p_pid,
+		    p->p_ucred ? p->p_ucred->cr_ruid : 0, pp->p_pid,
 		    p->p_pgrp ? p->p_pgrp->pg_id : 0, p->p_flag, p->p_stat);
 		if (p->p_wchan) {
 			db_printf("  %6s %8p", p->p_wmesg, (void *)p->p_wchan);
Index: i386/linux/linux_sysvec.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/linux/linux_sysvec.c,v
retrieving revision 1.78
diff -u -r1.78 linux_sysvec.c
--- i386/linux/linux_sysvec.c	2001/05/01 08:12:52	1.78
+++ i386/linux/linux_sysvec.c	2001/05/13 03:24:04
@@ -186,10 +186,10 @@
 	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
 	AUXARGS_ENTRY(pos, AT_BASE, args->base);
 	PROC_LOCK(imgp->proc);
-	AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid);
-	AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid);
-	AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid);
-	AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid);
+	AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
+	AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
+	AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
+	AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
 	PROC_UNLOCK(imgp->proc);
 	AUXARGS_ENTRY(pos, AT_NULL, 0);
 	
Index: kern/init_main.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/init_main.c,v
retrieving revision 1.168
diff -u -r1.168 init_main.c
--- kern/init_main.c	2001/04/29 02:44:48	1.168
+++ kern/init_main.c	2001/05/13 03:24:05
@@ -85,7 +85,6 @@
 static struct session session0;
 static struct pgrp pgrp0;
 struct	proc proc0;
-static struct pcred cred0;
 static struct procsig procsig0;
 static struct filedesc0 filedesc0;
 static struct plimit limit0;
@@ -321,12 +320,10 @@
 	callout_init(&p->p_slpcallout, 1);
 
 	/* Create credentials. */
-	cred0.p_refcnt = 1;
-	cred0.p_uidinfo = uifind(0);
-	p->p_cred = &cred0;
 	p->p_ucred = crget();
 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
 	p->p_ucred->cr_uidinfo = uifind(0);
+	p->p_ucred->cr_ruidinfo = uifind(0);
 	p->p_ucred->cr_prison = NULL;	/* Don't jail it. */
 
 	/* Create procsig. */
@@ -380,7 +377,7 @@
 	/*
 	 * Charge root for one process.
 	 */
-	(void)chgproccnt(cred0.p_uidinfo, 1, 0);
+	(void)chgproccnt(p->p_ucred->cr_ruidinfo, 1, 0);
 }
 SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL)
 
Index: kern/kern_acct.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_acct.c,v
retrieving revision 1.33
diff -u -r1.33 kern_acct.c
--- kern/kern_acct.c	2001/05/01 08:12:55	1.33
+++ kern/kern_acct.c	2001/05/13 03:24:05
@@ -222,8 +222,8 @@
 	acct.ac_io = encode_comp_t(r->ru_inblock + r->ru_oublock, 0);
 
 	/* (6) The UID and GID of the process */
-	acct.ac_uid = p->p_cred->p_ruid;
-	acct.ac_gid = p->p_cred->p_rgid;
+	acct.ac_uid = p->p_ucred->cr_ruid;
+	acct.ac_gid = p->p_ucred->cr_rgid;
 
 	/* (7) The terminal from which the process was started */
 	if ((p->p_flag & P_CONTROLT) && p->p_pgrp->pg_session->s_ttyp)
Index: kern/kern_descrip.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.100
diff -u -r1.100 kern_descrip.c
--- kern/kern_descrip.c	2001/05/01 08:12:55	1.100
+++ kern/kern_descrip.c	2001/05/13 03:24:06
@@ -525,8 +525,6 @@
 	sigio->sio_pgid = pgid;
 	crhold(curproc->p_ucred);
 	sigio->sio_ucred = curproc->p_ucred;
-	/* It would be convenient if p_ruid was in ucred. */
-	sigio->sio_ruid = curproc->p_cred->p_ruid;
 	sigio->sio_myref = sigiop;
 	s = splhigh();
 	*sigiop = sigio;
Index: kern/kern_exec.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.126
diff -u -r1.126 kern_exec.c
--- kern/kern_exec.c	2001/05/01 08:12:56	1.126
+++ kern/kern_exec.c	2001/05/13 03:24:06
@@ -104,6 +104,7 @@
 	register struct execve_args *uap;
 {
 	struct nameidata nd, *ndp;
+	struct ucred *oldcred = p->p_ucred, *newcred;
 	register_t *stack_base;
 	int error, len, i;
 	struct image_params image_params, *imgp;
@@ -274,13 +275,23 @@
 	}
 
 	/*
+	 * XXX: Note, the whole execve() is incredibly racey right now
+	 * with regards to debugging and privilege/credential management.
+	 * In particular, it's possible to race during exec() to attach
+	 * debugging to a process that will gain privilege.
+	 *
+	 * This MUST be fixed prior to any release.
+	 */
+
+	/*
 	 * Implement image setuid/setgid.
 	 *
 	 * Don't honor setuid/setgid if the filesystem prohibits it or if
 	 * the process is being traced.
 	 */
-	if ((((attr.va_mode & VSUID) && p->p_ucred->cr_uid != attr.va_uid) ||
-	     ((attr.va_mode & VSGID) && p->p_ucred->cr_gid != attr.va_gid)) &&
+	newcred = NULL;
+	if ((((attr.va_mode & VSUID) && oldcred->cr_uid != attr.va_uid) ||
+	     ((attr.va_mode & VSGID) && oldcred->cr_gid != attr.va_gid)) &&
 	    (imgp->vp->v_mount->mnt_flag & MNT_NOSUID) == 0 &&
 	    (p->p_flag & P_TRACED) == 0) {
 		PROC_UNLOCK(p);
@@ -288,7 +299,7 @@
 		 * Turn off syscall tracing for set-id programs, except for
 		 * root.
 		 */
-		if (p->p_tracep && suser(p)) {
+		if (p->p_tracep && suser_xxx(oldcred, NULL, PRISON_ROOT)) {
 			p->p_traceflag = 0;
 			vrele(p->p_tracep);
 			p->p_tracep = NULL;
@@ -296,25 +307,64 @@
 		/*
 		 * Set the new credentials.
 		 */
-		p->p_ucred = crcopy(p->p_ucred);
+		newcred = crdup(oldcred);
 		if (attr.va_mode & VSUID)
-			change_euid(p, attr.va_uid);
+			change_euid(newcred, attr.va_uid);
 		if (attr.va_mode & VSGID)
-			p->p_ucred->cr_gid = attr.va_gid;
+			change_egid(newcred, attr.va_gid);
 		setsugid(p);
 		setugidsafety(p);
 	} else {
-		if (p->p_ucred->cr_uid == p->p_cred->p_ruid &&
-		    p->p_ucred->cr_gid == p->p_cred->p_rgid)
+		if (oldcred->cr_uid == oldcred->cr_ruid &&
+		    oldcred->cr_gid == oldcred->cr_rgid)
 			p->p_flag &= ~P_SUGID;
 		PROC_UNLOCK(p);
 	}
 
 	/*
 	 * Implement correct POSIX saved-id behavior.
-	 */
-	p->p_cred->p_svuid = p->p_ucred->cr_uid;
-	p->p_cred->p_svgid = p->p_ucred->cr_gid;
+	 *
+	 * XXX: It's not clear that the existing behavior is
+	 * POSIX-compliant.  A number of courses indicate that the saved
+	 * uid/gid should only be updated if the new ruid is not equal to
+	 * the old ruid, or the new euid is not equal to the old euid and
+	 * the new euid is not equal to the old ruid.  The FreeBSD code
+	 * always updates the saved uid/gid.  Also, this code uses the new
+	 * (replaced) euid and egid as the source, which may or may not be
+	 * the right ones to use.
+	 */
+	if (newcred != NULL) {
+		change_svuid(newcred, newcred->cr_uid);
+		change_svgid(newcred, newcred->cr_gid);
+	} else {
+		/*
+		 * Avoid allocated a newcred if we don't have one yet and
+		 * update would be a noop.
+		 */
+		if (oldcred->cr_svuid != oldcred->cr_uid ||
+		    oldcred->cr_svgid != oldcred->cr_gid) {
+			newcred = crdup(oldcred);
+			change_svuid(newcred, newcred->cr_uid);
+			change_svgid(newcred, newcred->cr_gid);
+		}
+
+	}
+
+	if (newcred != NULL) {
+		/*
+		 * If the credential was updated, replace it with the
+		 * new credential.
+		 *
+		 * XXX: should setsugid() be called here?
+		 */
+		struct ucred *oldcred;
+
+		oldcred = p->p_ucred;
+		PROC_LOCK(p);
+		p->p_ucred = newcred;
+		PROC_UNLOCK(p);
+		crfree(oldcred);
+	}
 
 	/*
 	 * Store the vp for use in procfs
Index: kern/kern_exit.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_exit.c,v
retrieving revision 1.126
diff -u -r1.126 kern_exit.c
--- kern/kern_exit.c	2001/05/04 16:13:28	1.126
+++ kern/kern_exit.c	2001/05/13 03:24:07
@@ -514,7 +514,7 @@
 			/*
 			 * Decrement the count of procs running with this uid.
 			 */
-			(void)chgproccnt(p->p_cred->p_uidinfo, -1, 0);
+			(void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0);
 
 			/*
 			 * Release reference to text vnode
@@ -539,12 +539,8 @@
 			/*
 			 * Free up credentials.
 			 */
-			if (--p->p_cred->p_refcnt == 0) {
-				crfree(p->p_ucred);
-				uifree(p->p_cred->p_uidinfo);
-				FREE(p->p_cred, M_SUBPROC);
-				p->p_cred = NULL;
-			}
+			crfree(p->p_ucred);
+			p->p_ucred = NULL;
 
 			/*
 			 * Remove unused arguments
Index: kern/kern_fork.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_fork.c,v
retrieving revision 1.111
diff -u -r1.111 kern_fork.c
--- kern/kern_fork.c	2001/05/07 18:07:29	1.111
+++ kern/kern_fork.c	2001/05/13 03:24:07
@@ -257,7 +257,7 @@
 	 * exceed the limit. The variable nprocs is the current number of
 	 * processes, maxproc is the limit.
 	 */
-	uid = p1->p_cred->p_ruid;
+	uid = p1->p_ucred->cr_ruid;
 	if ((nprocs >= maxproc - 1 && uid != 0) || nprocs >= maxproc) {
 		tablefull("proc");
 		return (EAGAIN);
@@ -272,7 +272,7 @@
 	 * Increment the count of procs running with this uid. Don't allow
 	 * a nonprivileged user to exceed their current limit.
 	 */
-	ok = chgproccnt(p1->p_cred->p_uidinfo, 1,
+	ok = chgproccnt(p1->p_ucred->cr_ruidinfo, 1,
 		(uid != 0) ? p1->p_rlimit[RLIMIT_NPROC].rlim_cur : 0);
 	if (!ok) {
 		/*
@@ -408,15 +408,9 @@
 	 * We start off holding one spinlock after fork: sched_lock.
 	 */
 	p2->p_spinlocks = 1;
-	PROC_UNLOCK(p2);
-	MALLOC(p2->p_cred, struct pcred *, sizeof(struct pcred),
-	    M_SUBPROC, M_WAITOK);
-	PROC_LOCK(p2);
 	PROC_LOCK(p1);
-	bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred));
-	p2->p_cred->p_refcnt = 1;
 	crhold(p1->p_ucred);
-	uihold(p1->p_cred->p_uidinfo);
+	p2->p_ucred = p1->p_ucred;
 
 	if (p2->p_args)
 		p2->p_args->ar_ref++;
Index: kern/kern_ktrace.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_ktrace.c,v
retrieving revision 1.52
diff -u -r1.52 kern_ktrace.c
--- kern/kern_ktrace.c	2001/05/01 08:12:56	1.52
+++ kern/kern_ktrace.c	2001/05/13 03:24:08
@@ -531,17 +531,17 @@
 ktrcanset(callp, targetp)
 	struct proc *callp, *targetp;
 {
-	register struct pcred *caller = callp->p_cred;
-	register struct pcred *target = targetp->p_cred;
+	struct ucred *callcr = callp->p_ucred;
+	struct ucred *targetcr = targetp->p_ucred;
 
-	if (prison_check(callp->p_ucred, targetp->p_ucred))
+	if (prison_check(callcr, targetcr))
 		return (0);
-	if ((caller->pc_ucred->cr_uid == target->p_ruid &&
-	     target->p_ruid == target->p_svuid &&
-	     caller->p_rgid == target->p_rgid &&	/* XXX */
-	     target->p_rgid == target->p_svgid &&
+	if ((callcr->cr_uid == targetcr->cr_ruid &&
+	     targetcr->cr_ruid == targetcr->cr_svuid &&
+	     callcr->cr_rgid == targetcr->cr_rgid &&	/* XXX */
+	     targetcr->cr_rgid == targetcr->cr_svgid &&
 	     (targetp->p_traceflag & KTRFAC_ROOT) == 0) ||
-	     caller->pc_ucred->cr_uid == 0)
+	     !suser_xxx(callcr, NULL, PRISON_ROOT))
 		return (1);
 
 	return (0);
Index: kern/kern_proc.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_proc.c,v
retrieving revision 1.93
diff -u -r1.93 kern_proc.c
--- kern/kern_proc.c	2001/05/01 08:12:57	1.93
+++ kern/kern_proc.c	2001/05/13 03:24:08
@@ -424,15 +424,15 @@
 	kp->ki_textvp = p->p_textvp;
 	kp->ki_fd = p->p_fd;
 	kp->ki_vmspace = p->p_vmspace;
-	if (p->p_cred) {
-		kp->ki_uid = p->p_cred->pc_ucred->cr_uid;
-		kp->ki_ruid = p->p_cred->p_ruid;
-		kp->ki_svuid = p->p_cred->p_svuid;
-		kp->ki_ngroups = p->p_cred->pc_ucred->cr_ngroups;
-		bcopy(p->p_cred->pc_ucred->cr_groups, kp->ki_groups,
+	if (p->p_ucred) {
+		kp->ki_uid = p->p_ucred->cr_uid;
+		kp->ki_ruid = p->p_ucred->cr_ruid;
+		kp->ki_svuid = p->p_ucred->cr_svuid;
+		kp->ki_ngroups = p->p_ucred->cr_ngroups;
+		bcopy(p->p_ucred->cr_groups, kp->ki_groups,
 		    NGROUPS * sizeof(gid_t));
-		kp->ki_rgid = p->p_cred->p_rgid;
-		kp->ki_svgid = p->p_cred->p_svgid;
+		kp->ki_rgid = p->p_ucred->cr_rgid;
+		kp->ki_svgid = p->p_ucred->cr_svgid;
 	}
 	if (p->p_procsig) {
 		kp->ki_sigignore = p->p_procsig->ps_sigignore;
@@ -653,7 +653,7 @@
 
 			case KERN_PROC_RUID:
 				if (p->p_ucred == NULL || 
-				    p->p_cred->p_ruid != (uid_t)name[0])
+				    p->p_ucred->cr_ruid != (uid_t)name[0])
 					continue;
 				break;
 			}
Index: kern/kern_prot.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_prot.c,v
retrieving revision 1.89
diff -u -r1.89 kern_prot.c
--- kern/kern_prot.c	2001/05/01 08:12:57	1.89
+++ kern/kern_prot.c	2001/05/13 03:24:09
@@ -210,7 +210,7 @@
 	struct getuid_args *uap;
 {
 
-	p->p_retval[0] = p->p_cred->p_ruid;
+	p->p_retval[0] = p->p_ucred->cr_ruid;
 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 	p->p_retval[1] = p->p_ucred->cr_uid;
 #endif
@@ -253,7 +253,7 @@
 	struct getgid_args *uap;
 {
 
-	p->p_retval[0] = p->p_cred->p_rgid;
+	p->p_retval[0] = p->p_ucred->cr_rgid;
 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 	p->p_retval[1] = p->p_ucred->cr_groups[0];
 #endif
@@ -293,18 +293,18 @@
 	struct proc *p;
 	register struct	getgroups_args *uap;
 {
-	register struct pcred *pc = p->p_cred;
-	register u_int ngrp;
+	struct ucred *cred = p->p_ucred;
+	u_int ngrp;
 	int error;
 
 	if ((ngrp = uap->gidsetsize) == 0) {
-		p->p_retval[0] = pc->pc_ucred->cr_ngroups;
+		p->p_retval[0] = cred->cr_ngroups;
 		return (0);
 	}
-	if (ngrp < pc->pc_ucred->cr_ngroups)
+	if (ngrp < cred->cr_ngroups)
 		return (EINVAL);
-	ngrp = pc->pc_ucred->cr_ngroups;
-	if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
+	ngrp = cred->cr_ngroups;
+	if ((error = copyout((caddr_t)cred->cr_groups,
 	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
 		return (error);
 	p->p_retval[0] = ngrp;
@@ -427,7 +427,7 @@
 	struct proc *p;
 	struct setuid_args *uap;
 {
-	register struct pcred *pc = p->p_cred;
+	struct ucred *oldcred = p->p_ucred, *newcred;
 	register uid_t uid;
 	int error;
 
@@ -449,16 +449,17 @@
 	 * 3: Change euid last. (after tests in #2 for "appropriate privs")
 	 */
 	uid = uap->uid;
-	if (uid != pc->p_ruid &&		/* allow setuid(getuid()) */
+	if (uid != oldcred->cr_ruid &&		/* allow setuid(getuid()) */
 #ifdef _POSIX_SAVED_IDS
-	    uid != pc->p_svuid &&		/* allow setuid(saved gid) */
+	    uid != oldcred->cr_svuid &&		/* allow setuid(saved gid) */
 #endif
 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
-	    uid != pc->pc_ucred->cr_uid &&	/* allow setuid(geteuid()) */
+	    uid != oldcred->cr_uid &&		/* allow setuid(geteuid()) */
 #endif
-	    (error = suser_xxx(0, p, PRISON_ROOT)))
+	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
 		return (error);
 
+	newcred = crdup(oldcred);
 #ifdef _POSIX_SAVED_IDS
 	/*
 	 * Do we have "appropriate privileges" (are we root or uid == euid)
@@ -466,16 +467,16 @@
 	 */
 	if (
 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use the clause from B.4.2.2 */
-	    uid == pc->pc_ucred->cr_uid ||
+	    uid == oldcred->cr_uid ||
 #endif
-	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
+	    suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
 #endif
 	{
 		/*
 		 * Set the real uid and transfer proc count to new user.
 		 */
-		if (uid != pc->p_ruid) {
-			change_ruid(p, uid);
+		if (uid != oldcred->cr_ruid) {
+			change_ruid(newcred, uid);
 			setsugid(p);
 		}
 		/*
@@ -485,8 +486,8 @@
 		 * the security of seteuid() depends on it.  B.4.2.2 says it
 		 * is important that we should do this.
 		 */
-		if (pc->p_svuid != uid) {
-			pc->p_svuid = uid;
+		if (uid != oldcred->cr_svuid) {
+			change_svuid(newcred, uid);
 			setsugid(p);
 		}
 	}
@@ -495,10 +496,12 @@
 	 * In all permitted cases, we are changing the euid.
 	 * Copy credentials so other references do not see our changes.
 	 */
-	if (pc->pc_ucred->cr_uid != uid) {
-		change_euid(p, uid);
+	if (uid != oldcred->cr_uid) {
+		change_euid(newcred, uid);
 		setsugid(p);
 	}
+	p->p_ucred = newcred;
+	crfree(oldcred);
 	return (0);
 }
 
@@ -513,23 +516,31 @@
 	struct proc *p;
 	struct seteuid_args *uap;
 {
-	register struct pcred *pc = p->p_cred;
-	register uid_t euid;
+	struct ucred *oldcred = p->p_ucred, *newcred;
+	uid_t euid;
 	int error;
 
 	euid = uap->euid;
-	if (euid != pc->p_ruid &&		/* allow seteuid(getuid()) */
-	    euid != pc->p_svuid &&		/* allow seteuid(saved uid) */
-	    (error = suser_xxx(0, p, PRISON_ROOT)))
+	/*
+	 * The new effective uid must equal the current real or saved
+	 * uid.  Appropriate privilege may override this restriction.
+	 */
+	if (euid != oldcred->cr_ruid &&		/* allow seteuid(getuid()) */
+	    euid != oldcred->cr_svuid &&	/* allow seteuid(saved uid) */
+	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
 		return (error);
+
 	/*
 	 * Everything's okay, do it.  Copy credentials so other references do
 	 * not see our changes.
 	 */
-	if (pc->pc_ucred->cr_uid != euid) {
-		change_euid(p, euid);
+	newcred = crdup(oldcred);
+	if (oldcred->cr_uid != euid) {
+		change_euid(newcred, euid);
 		setsugid(p);
 	}
+	p->p_ucred = newcred;
+	crfree(oldcred);
 	return (0);
 }
 
@@ -544,7 +555,7 @@
 	struct proc *p;
 	struct setgid_args *uap;
 {
-	register struct pcred *pc = p->p_cred;
+	struct ucred *oldcred = p->p_ucred, *newcred;
 	register gid_t gid;
 	int error;
 
@@ -560,16 +571,17 @@
 	 * For notes on the logic here, see setuid() above.
 	 */
 	gid = uap->gid;
-	if (gid != pc->p_rgid &&		/* allow setgid(getgid()) */
+	if (gid != oldcred->cr_rgid &&		/* allow setgid(getgid()) */
 #ifdef _POSIX_SAVED_IDS
-	    gid != pc->p_svgid &&		/* allow setgid(saved gid) */
+	    gid != oldcred->cr_svgid &&		/* allow setgid(saved gid) */
 #endif
 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
-	    gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */
+	    gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */
 #endif
-	    (error = suser_xxx(0, p, PRISON_ROOT)))
+	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
 		return (error);
 
+	newcred = crdup(oldcred);
 #ifdef _POSIX_SAVED_IDS
 	/*
 	 * Do we have "appropriate privileges" (are we root or gid == egid)
@@ -577,16 +589,16 @@
 	 */
 	if (
 #ifdef POSIX_APPENDIX_B_4_2_2	/* use the clause from B.4.2.2 */
-	    gid == pc->pc_ucred->cr_groups[0] ||
+	    gid == oldcred->cr_groups[0] ||
 #endif
-	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
+	    suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
 #endif
 	{
 		/*
 		 * Set real gid
 		 */
-		if (pc->p_rgid != gid) {
-			pc->p_rgid = gid;
+		if (oldcred->cr_rgid != gid) {
+			change_rgid(newcred, gid);
 			setsugid(p);
 		}
 		/*
@@ -596,8 +608,8 @@
 		 * the security of setegid() depends on it.  B.4.2.2 says it
 		 * is important that we should do this.
 		 */
-		if (pc->p_svgid != gid) {
-			pc->p_svgid = gid;
+		if (oldcred->cr_svgid != gid) {
+			change_svgid(newcred, gid);
 			setsugid(p);
 		}
 	}
@@ -605,11 +617,12 @@
 	 * In all cases permitted cases, we are changing the egid.
 	 * Copy credentials so other references do not see our changes.
 	 */
-	if (pc->pc_ucred->cr_groups[0] != gid) {
-		pc->pc_ucred = crcopy(pc->pc_ucred);
-		pc->pc_ucred->cr_groups[0] = gid;
+	if (oldcred->cr_groups[0] != gid) {
+		change_egid(newcred, gid);
 		setsugid(p);
 	}
+	p->p_ucred = newcred;
+	crfree(oldcred);
 	return (0);
 }
 
@@ -624,20 +637,27 @@
 	struct proc *p;
 	struct setegid_args *uap;
 {
-	register struct pcred *pc = p->p_cred;
-	register gid_t egid;
+	struct ucred *oldcred = p->p_ucred, *newcred;
+	gid_t egid;
 	int error;
 
 	egid = uap->egid;
-	if (egid != pc->p_rgid &&		/* allow setegid(getgid()) */
-	    egid != pc->p_svgid &&		/* allow setegid(saved gid) */
-	    (error = suser_xxx(0, p, PRISON_ROOT)))
+	/*
+	 * The new effective gid must be equal to either the current real or
+	 * saved gid.  Appropriate privilege may override this restriction.
+	 */
+	if (egid != oldcred->cr_rgid &&		/* allow setegid(getgid()) */
+	    egid != oldcred->cr_svgid &&	/* allow setegid(saved gid) */
+	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
 		return (error);
-	if (pc->pc_ucred->cr_groups[0] != egid) {
-		pc->pc_ucred = crcopy(pc->pc_ucred);
-		pc->pc_ucred->cr_groups[0] = egid;
+	
+	newcred = crdup(oldcred);
+	if (oldcred->cr_groups[0] != egid) {
+		change_egid(newcred, egid);
 		setsugid(p);
 	}
+	p->p_ucred = newcred;
+	crfree(oldcred);
 	return (0);
 }
 
@@ -653,11 +673,11 @@
 	struct proc *p;
 	struct setgroups_args *uap;
 {
-	register struct pcred *pc = p->p_cred;
-	register u_int ngrp;
+	struct ucred *oldcred = p->p_ucred, *newcred;
+	u_int ngrp;
 	int error;
 
-	if ((error = suser_xxx(0, p, PRISON_ROOT)))
+	if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
 		return (error);
 	ngrp = uap->gidsetsize;
 	if (ngrp > NGROUPS)
@@ -666,7 +686,7 @@
 	 * XXX A little bit lazy here.  We could test if anything has
 	 * changed before crcopy() and setting P_SUGID.
 	 */
-	pc->pc_ucred = crcopy(pc->pc_ucred);
+	newcred = crdup(oldcred);
 	if (ngrp < 1) {
 		/*
 		 * setgroups(0, NULL) is a legitimate way of clearing the
@@ -674,14 +694,18 @@
 		 * have the egid in the groups[0]).  We risk security holes
 		 * when running non-BSD software if we do not do the same.
 		 */
-		pc->pc_ucred->cr_ngroups = 1;
+		newcred->cr_ngroups = 1;
 	} else {
 		if ((error = copyin((caddr_t)uap->gidset,
-		    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
+		    (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) {
+			crfree(newcred);
 			return (error);
-		pc->pc_ucred->cr_ngroups = ngrp;
+		}
+		newcred->cr_ngroups = ngrp;
 	}
 	setsugid(p);
+	p->p_ucred = newcred;
+	crfree(oldcred);
 	return (0);
 }
 
@@ -697,31 +721,52 @@
 	register struct proc *p;
 	struct setreuid_args *uap;
 {
-	register struct pcred *pc = p->p_cred;
-	register uid_t ruid, euid;
+	struct ucred *oldcred = p->p_ucred, *newcred;
+	uid_t ruid, euid;
 	int error;
 
 	ruid = uap->ruid;
 	euid = uap->euid;
-	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) ||
-	     (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid &&
-	     euid != pc->p_ruid && euid != pc->p_svuid)) &&
-	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
+	/*
+	 * If an real uid update is requested, the requested real uid must
+	 * be equal to the current real or saved uid.  If an effective uid
+	 * update is requested, the requested euid must be equal to the
+	 * current effective uid, real uid, or saved uid.  Appropriate
+	 * privilege may override these restrictions.
+	 */
+	if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
+	      ruid != oldcred->cr_svuid) ||
+	     (euid != (uid_t)-1 && euid != oldcred->cr_uid &&
+	      euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
+	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
 		return (error);
 
-	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
-		change_euid(p, euid);
+	newcred = crdup(oldcred);
+	if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
+		change_euid(newcred, euid);
 		setsugid(p);
 	}
-	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
-		change_ruid(p, ruid);
+	if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
+		change_ruid(newcred, ruid);
 		setsugid(p);
 	}
-	if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) &&
-	    pc->p_svuid != pc->pc_ucred->cr_uid) {
-		pc->p_svuid = pc->pc_ucred->cr_uid;
+	/*
+	 * XXX: What is this intended to accomplish?  In which cases should
+	 * it be looking at the old values, and in which, the new values?
+	 *
+	 * Note current behavior is:
+	 * If the ruid update is requested (even if the ruid is not changed)
+	 * or the euid is not equal to the value of the ruid, a difference
+	 * in the svuid and the euid will result in the svuid being
+	 * updated to the new value of the euid.
+	 */
+	if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) &&
+	    newcred->cr_svuid != newcred->cr_uid) {
+		change_svuid(newcred, newcred->cr_uid);
 		setsugid(p);
 	}
+	p->p_ucred = newcred;
+	crfree(oldcred);
 	return (0);
 }
 
@@ -737,30 +782,49 @@
 	register struct proc *p;
 	struct setregid_args *uap;
 {
-	register struct pcred *pc = p->p_cred;
-	register gid_t rgid, egid;
+	struct ucred *oldcred = p->p_ucred, *newcred;
+	gid_t rgid, egid;
 	int error;
 
 	rgid = uap->rgid;
 	egid = uap->egid;
-	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) ||
-	     (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] &&
-	     egid != pc->p_rgid && egid != pc->p_svgid)) &&
-	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
+	/*
+	 * If a real gid update is requested, the requested real gid must
+	 * be equal to the current real or saved gid.  If an effective gid
+	 * update is requested, the requested effective gid must be equal
+	 * to the current effective gid, the current real gid, or the
+	 * current saved gid.  Apropriate privilege may override this
+	 * restriction.
+	 */
+	if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
+	    rgid != oldcred->cr_svgid) ||
+	     (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] &&
+	     egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) &&
+	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
 		return (error);
 
-	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
-		pc->pc_ucred = crcopy(pc->pc_ucred);
-		pc->pc_ucred->cr_groups[0] = egid;
+	newcred = crdup(oldcred);
+	if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
+		change_egid(newcred, egid);
 		setsugid(p);
 	}
-	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
-		pc->p_rgid = rgid;
+	if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
+		change_rgid(newcred, rgid);
 		setsugid(p);
 	}
-	if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) &&
-	    pc->p_svgid != pc->pc_ucred->cr_groups[0]) {
-		pc->p_svgid = pc->pc_ucred->cr_groups[0];
+	/*
+	 * XXX: What is this intended to accomplish?  In which cases should
+	 * it be looking at the old values, and in which, the new values?
+	 *
+	 * Note current behavior is:
+	 * If the rgid update is requested (even if the rgid is not changed)
+	 * or the egid is not equal to the value of the rgid, a difference
+	 * in the svgid and the egid will result in the svuid being
+	 * updated to the new value of the euid.
+	 */
+	if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) &&
+	    newcred->cr_svgid != newcred->cr_groups[0]) {
+		change_svgid(newcred, newcred->cr_groups[0]);
 		setsugid(p);
 	}
 	return (0);
@@ -784,33 +848,40 @@
 	register struct proc *p;
 	struct setresuid_args *uap;
 {
-	register struct pcred *pc = p->p_cred;
-	register uid_t ruid, euid, suid;
+	struct ucred *oldcred = p->p_ucred, *newcred;
+	uid_t ruid, euid, suid;
 	int error;
 
 	ruid = uap->ruid;
 	euid = uap->euid;
 	suid = uap->suid;
-	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid &&
-	      ruid != pc->pc_ucred->cr_uid) ||
-	     (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid &&
-	      euid != pc->pc_ucred->cr_uid) ||
-	     (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid &&
-	      suid != pc->pc_ucred->cr_uid)) &&
-	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
+	if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
+	     ruid != oldcred->cr_svuid &&
+	      ruid != oldcred->cr_uid) ||
+	     (euid != (uid_t)-1 && euid != oldcred->cr_ruid &&
+	    euid != oldcred->cr_svuid &&
+	      euid != oldcred->cr_uid) ||
+	     (suid != (uid_t)-1 && suid != oldcred->cr_ruid &&
+	    suid != oldcred->cr_svuid &&
+	      suid != oldcred->cr_uid)) &&
+	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
 		return (error);
-	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
-		change_euid(p, euid);
+
+	newcred = crdup(oldcred);
+	if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
+		change_euid(newcred, euid);
 		setsugid(p);
 	}
-	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
-		change_ruid(p, ruid);
+	if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
+		change_ruid(newcred, ruid);
 		setsugid(p);
 	}
-	if (suid != (uid_t)-1 && pc->p_svuid != suid) {
-		pc->p_svuid = suid;
+	if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) {
+		change_svuid(newcred, suid);
 		setsugid(p);
 	}
+	p->p_ucred = newcred;
+	crfree(oldcred);
 	return (0);
 }
 
@@ -832,35 +903,40 @@
 	register struct proc *p;
 	struct setresgid_args *uap;
 {
-	register struct pcred *pc = p->p_cred;
-	register gid_t rgid, egid, sgid;
+	struct ucred *oldcred = p->p_ucred, *newcred;
+	gid_t rgid, egid, sgid;
 	int error;
 
 	rgid = uap->rgid;
 	egid = uap->egid;
 	sgid = uap->sgid;
-	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid &&
-	      rgid != pc->pc_ucred->cr_groups[0]) ||
-	     (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid &&
-	      egid != pc->pc_ucred->cr_groups[0]) ||
-	     (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid &&
-	      sgid != pc->pc_ucred->cr_groups[0])) &&
-	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
+	if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
+	      rgid != oldcred->cr_svgid &&
+	      rgid != oldcred->cr_groups[0]) ||
+	     (egid != (gid_t)-1 && egid != oldcred->cr_rgid &&
+	      egid != oldcred->cr_svgid &&
+	      egid != oldcred->cr_groups[0]) ||
+	     (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid &&
+	      sgid != oldcred->cr_svgid &&
+	      sgid != oldcred->cr_groups[0])) &&
+	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
 		return (error);
 
-	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
-		pc->pc_ucred = crcopy(pc->pc_ucred);
-		pc->pc_ucred->cr_groups[0] = egid;
+	newcred = crdup(oldcred);
+	if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
+		change_egid(newcred, egid);
 		setsugid(p);
 	}
-	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
-		pc->p_rgid = rgid;
+	if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
+		change_rgid(newcred, rgid);
 		setsugid(p);
 	}
-	if (sgid != (gid_t)-1 && pc->p_svgid != sgid) {
-		pc->p_svgid = sgid;
+	if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) {
+		change_svgid(newcred, sgid);
 		setsugid(p);
 	}
+	p->p_ucred = newcred;
+	crfree(oldcred);
 	return (0);
 }
 
@@ -877,18 +953,18 @@
 	register struct proc *p;
 	struct getresuid_args *uap;
 {
-	struct pcred *pc = p->p_cred;
+	struct ucred *cred = p->p_ucred;
 	int error1 = 0, error2 = 0, error3 = 0;
 
 	if (uap->ruid)
-		error1 = copyout((caddr_t)&pc->p_ruid,
-		    (caddr_t)uap->ruid, sizeof(pc->p_ruid));
+		error1 = copyout((caddr_t)&cred->cr_ruid,
+		    (caddr_t)uap->ruid, sizeof(cred->cr_ruid));
 	if (uap->euid)
-		error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid,
-		    (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid));
+		error2 = copyout((caddr_t)&cred->cr_uid,
+		    (caddr_t)uap->euid, sizeof(cred->cr_uid));
 	if (uap->suid)
-		error3 = copyout((caddr_t)&pc->p_svuid,
-		    (caddr_t)uap->suid, sizeof(pc->p_svuid));
+		error3 = copyout((caddr_t)&cred->cr_svuid,
+		    (caddr_t)uap->suid, sizeof(cred->cr_svuid));
 	return error1 ? error1 : (error2 ? error2 : error3);
 }
 
@@ -905,18 +981,18 @@
 	register struct proc *p;
 	struct getresgid_args *uap;
 {
-	struct pcred *pc = p->p_cred;
+	struct ucred *cred = p->p_ucred;
 	int error1 = 0, error2 = 0, error3 = 0;
 
 	if (uap->rgid)
-		error1 = copyout((caddr_t)&pc->p_rgid,
-		    (caddr_t)uap->rgid, sizeof(pc->p_rgid));
+		error1 = copyout((caddr_t)&cred->cr_rgid,
+		    (caddr_t)uap->rgid, sizeof(cred->cr_rgid));
 	if (uap->egid)
-		error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0],
-		    (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0]));
+		error2 = copyout((caddr_t)&cred->cr_groups[0],
+		    (caddr_t)uap->egid, sizeof(cred->cr_groups[0]));
 	if (uap->sgid)
-		error3 = copyout((caddr_t)&pc->p_svgid,
-		    (caddr_t)uap->sgid, sizeof(pc->p_svgid));
+		error3 = copyout((caddr_t)&cred->cr_svgid,
+		    (caddr_t)uap->sgid, sizeof(cred->cr_svgid));
 	return error1 ? error1 : (error2 ? error2 : error3);
 }
 
@@ -972,7 +1048,7 @@
 int
 groupmember(gid, cred)
 	gid_t gid;
-	register struct ucred *cred;
+	struct ucred *cred;
 {
 	register gid_t *gp;
 	gid_t *egp;
@@ -1113,10 +1189,10 @@
 	 * Generally, the object credential's ruid or svuid must match the
 	 * subject credential's ruid or euid.
 	 */
-	if (p1->p_cred->p_ruid != p2->p_cred->p_ruid &&
-	    p1->p_cred->p_ruid != p2->p_cred->p_svuid &&
-	    p1->p_ucred->cr_uid != p2->p_cred->p_ruid &&
-	    p1->p_ucred->cr_uid != p2->p_cred->p_svuid) {
+	if (p1->p_ucred->cr_ruid != p2->p_ucred->cr_ruid &&
+	    p1->p_ucred->cr_ruid != p2->p_ucred->cr_svuid &&
+	    p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid &&
+	    p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid) {
 		/* Not permitted, try privilege. */
 		error = suser_xxx(NULL, p1, PRISON_ROOT);
 		if (error)
@@ -1140,9 +1216,9 @@
 	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
 		return (error);
 
-	if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
+	if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid)
 		return (0);
-	if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid)
+	if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid)
 		return (0);
 
 	if (!suser_xxx(0, p1, PRISON_ROOT)) {
@@ -1178,9 +1254,9 @@
 
 	/* not owned by you, has done setuid (unless you're root) */
 	/* add a CAP_SYS_PTRACE here? */
-	if (p1->p_cred->pc_ucred->cr_uid != p2->p_cred->p_ruid ||
-	    p1->p_cred->p_ruid != p2->p_cred->p_ruid ||
-	    p1->p_cred->p_svuid != p2->p_cred->p_ruid ||
+	if (p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid ||
+	    p1->p_ucred->cr_ruid != p2->p_ucred->cr_ruid ||
+	    p1->p_ucred->cr_svuid != p2->p_ucred->cr_ruid ||
 	    p2->p_flag & P_SUGID) {
 		if ((error = suser_xxx(0, p1, PRISON_ROOT)))
 			return (error);
@@ -1308,6 +1384,7 @@
 	*newcr = *cr;
 	mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF);
 	uihold(newcr->cr_uidinfo);
+	uihold(newcr->cr_ruidinfo);
 	if (jailed(newcr))
 		prison_hold(newcr->cr_prison);
 	newcr->cr_ref = 1;
@@ -1375,48 +1452,123 @@
 }
 
 /*
- * Helper function to change the effective uid of a process
+ * change_euid(): Change a process's effective uid.
+ * Arguments: struct ucred *newcred, uid_t euid
+ * Returns: none
+ * Locks: none
+ * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified.
+ * References: newcred must be an exclusive credential reference for the
+ *             duration of the call.
+ * Notes: none
  */
 void
-change_euid(p, euid)
-	struct	proc *p;
-	uid_t	euid;
+change_euid(newcred, euid)
+	struct ucred *newcred;
+	uid_t euid;
 {
-	struct	pcred *pc;
-	struct	uidinfo *uip;
 
-	pc = p->p_cred;
-	/*
-	 * crcopy is essentially a NOP if ucred has a reference count
-	 * of 1, which is true if it has already been copied.
-	 */
-	pc->pc_ucred = crcopy(pc->pc_ucred);
-	uip = pc->pc_ucred->cr_uidinfo;
-	pc->pc_ucred->cr_uid = euid;
-	pc->pc_ucred->cr_uidinfo = uifind(euid);
-	uifree(uip);
+	newcred->cr_uid = euid;
+	uifree(newcred->cr_uidinfo);
+	newcred->cr_uidinfo = uifind(euid);
 }
 
 /*
- * Helper function to change the real uid of a process
- *
- * The per-uid process count for this process is transfered from
- * the old uid to the new uid.
+ * change_egid(): Change a process's effective gid.
+ * Arguments: struct ucred *newcred, gid_t egid
+ * Returns: none
+ * Locks: none
+ * Side effects: newcred->cr_gid will be modified.
+ * References: newcred must be an exclusive credential reference for the
+ *             duration of the call.
+ * Notes: none
  */
 void
-change_ruid(p, ruid)
-	struct	proc *p;
-	uid_t	ruid;
+change_egid(newcred, egid)
+	struct ucred *newcred;
+	gid_t egid;
+{
+
+	newcred->cr_groups[0] = egid;
+}
+
+/*
+ * change_ruid(): Change a process's real uid.
+ * Arguments: struct ucred *newcred, uid_t ruid
+ * Returns: none
+ * Locks: none
+ * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo
+ *               will be updated, and the old and new cr_ruidinfo proc
+ *               counts will be updated.
+ * References: newcred must be an exclusive credential reference for the
+ *             duration of the call.
+ * Notes: none
+ */
+void
+change_ruid(newcred, ruid)
+	struct ucred *newcred;
+	uid_t ruid;
+{
+
+	(void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
+	newcred->cr_ruid = ruid;
+	uifree(newcred->cr_ruidinfo);
+	newcred->cr_ruidinfo = uifind(ruid);
+	(void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
+}
+
+/*
+ * change_rgid(): Change a process's real gid.
+ * Arguments: struct ucred *newcred, gid_t rgid
+ * Returns: none
+ * Locks: none
+ * Side effects: newcred->cr_rgid will be updated.
+ * References: newcred must be an exclusive credential reference for the
+ *             duration of the call.
+ * Notes: none
+ */
+void
+change_rgid(newcred, rgid)
+	struct ucred *newcred;
+	gid_t rgid;
+{
+
+	newcred->cr_rgid = rgid;
+}
+
+/*
+ * change_svuid(): Change a process's saved uid.
+ * Arguments: struct ucred *newcred, uid_t svuid
+ * Returns: none
+ * Locks: none
+ * Side effects: newcred->cr_svuid will be updated.
+ * References: newcred must be an exclusive credential reference for the
+ *             duration of the call.
+ * Notes: none
+ */
+void
+change_svuid(newcred, svuid)
+	struct ucred *newcred;
+	uid_t svuid;
+{
+
+	newcred->cr_svuid = svuid;
+}
+
+/*
+ * change_svgid(): Change a process's saved gid.
+ * Arguments: struct ucred *newcred, gid_t svgid
+ * Returns: none
+ * Locks: none
+ * Side effects: newcred->cr_svgid will be updated.
+ * References: newcred must be an exclusive credential reference for the
+ *             duration of the call.
+ * Notes: none
+ */
+void
+change_svgid(newcred, svgid)
+	struct ucred *newcred;
+	gid_t svgid;
 {
-	struct	pcred *pc;
-	struct	uidinfo *uip;
 
-	pc = p->p_cred;
-	(void)chgproccnt(pc->p_uidinfo, -1, 0);
-	uip = pc->p_uidinfo;
-	/* It is assumed that pcred is not shared between processes */
-	pc->p_ruid = ruid;
-	pc->p_uidinfo = uifind(ruid);
-	(void)chgproccnt(pc->p_uidinfo, 1, 0);
-	uifree(uip);
+	newcred->cr_svgid = svgid;
 }
Index: kern/kern_sig.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_sig.c,v
retrieving revision 1.118
diff -u -r1.118 kern_sig.c
--- kern/kern_sig.c	2001/05/07 18:07:29	1.118
+++ kern/kern_sig.c	2001/05/13 03:24:11
@@ -98,14 +98,14 @@
     "Log processes quitting on abnormal signals to syslog(3)");
 
 /*
- * Policy -- Can real uid ruid with ucred uc send a signal to process q?
+ * Policy -- Can ucred cr1 send SIGIO to process cr2?
  */
-#define CANSIGIO(ruid, uc, q) \
-	((uc)->cr_uid == 0 || \
-	    (ruid) == (q)->p_cred->p_ruid || \
-	    (uc)->cr_uid == (q)->p_cred->p_ruid || \
-	    (ruid) == (q)->p_ucred->cr_uid || \
-	    (uc)->cr_uid == (q)->p_ucred->cr_uid)
+#define CANSIGIO(cr1, cr2) \
+	((cr1)->cr_uid == 0 || \
+	    (cr2)->cr_ruid == (cr2)->cr_ruid || \
+	    (cr2)->cr_uid == (cr2)->cr_ruid || \
+	    (cr2)->cr_ruid == (cr2)->cr_uid || \
+	    (cr2)->cr_uid == (cr2)->cr_uid)
 
 int sugid_coredump;
 SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RW, 
@@ -1610,8 +1610,8 @@
 {
 	CTR3(KTR_PROC, "killproc: proc %p (pid %d, %s)",
 		p, p->p_pid, p->p_comm);
-	log(LOG_ERR, "pid %d (%s), uid %d, was killed: %s\n", p->p_pid, p->p_comm,
-		p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1, why);
+	log(LOG_ERR, "pid %d (%s), uid %d, was killed: %s\n", p->p_pid,
+	    p->p_comm, p->p_ucred ? p->p_ucred->cr_uid : -1, why);
 	PROC_LOCK(p);
 	psignal(p, SIGKILL);
 	PROC_UNLOCK(p);
@@ -1650,7 +1650,7 @@
 			log(LOG_INFO,
 			    "pid %d (%s), uid %d: exited on signal %d%s\n",
 			    p->p_pid, p->p_comm,
-			    p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1,
+			    p->p_ucred ? p->p_ucred->cr_uid : -1,
 			    sig &~ WCOREFLAG,
 			    sig & WCOREFLAG ? " (core dumped)" : "");
 	} else {
@@ -1870,8 +1870,7 @@
 		
 	if (sigio->sio_pgid > 0) {
 		PROC_LOCK(sigio->sio_proc);
-		if (CANSIGIO(sigio->sio_ruid, sigio->sio_ucred,
-		             sigio->sio_proc))
+		if (CANSIGIO(sigio->sio_ucred, sigio->sio_proc->p_ucred))
 			psignal(sigio->sio_proc, sig);
 		PROC_UNLOCK(sigio->sio_proc);
 	} else if (sigio->sio_pgid < 0) {
@@ -1879,7 +1878,7 @@
 
 		LIST_FOREACH(p, &sigio->sio_pgrp->pg_members, p_pglist) {
 			PROC_LOCK(p);
-			if (CANSIGIO(sigio->sio_ruid, sigio->sio_ucred, p) &&
+			if (CANSIGIO(sigio->sio_ucred, p->p_ucred) &&
 			    (checkctty == 0 || (p->p_flag & P_CONTROLT)))
 				psignal(p, sig);
 			PROC_UNLOCK(p);
Index: kern/uipc_usrreq.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.65
diff -u -r1.65 uipc_usrreq.c
--- kern/uipc_usrreq.c	2001/05/01 08:12:59	1.65
+++ kern/uipc_usrreq.c	2001/05/13 03:24:12
@@ -988,8 +988,8 @@
 	if (cm->cmsg_type == SCM_CREDS) {
 		cmcred = (struct cmsgcred *)(cm + 1);
 		cmcred->cmcred_pid = p->p_pid;
-		cmcred->cmcred_uid = p->p_cred->p_ruid;
-		cmcred->cmcred_gid = p->p_cred->p_rgid;
+		cmcred->cmcred_uid = p->p_ucred->cr_ruid;
+		cmcred->cmcred_gid = p->p_ucred->cr_rgid;
 		cmcred->cmcred_euid = p->p_ucred->cr_uid;
 		cmcred->cmcred_ngroups = MIN(p->p_ucred->cr_ngroups,
 							CMGROUP_MAX);
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.189
diff -u -r1.189 vfs_syscalls.c
--- kern/vfs_syscalls.c	2001/04/29 02:44:49	1.189
+++ kern/vfs_syscalls.c	2001/05/13 03:24:14
@@ -1711,8 +1711,8 @@
 	 * rather than to modify the potentially shared process structure.
 	 */
 	tmpcred = crdup(cred);
-	tmpcred->cr_uid = p->p_cred->p_ruid;
-	tmpcred->cr_groups[0] = p->p_cred->p_rgid;
+	tmpcred->cr_uid = cred->cr_ruid;
+	tmpcred->cr_groups[0] = cred->cr_rgid;
 	p->p_ucred = tmpcred;
 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
 	    SCARG(uap, path), p);
@@ -3799,7 +3799,7 @@
 	}
 	cnt = auio.uio_resid;
 	error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
-	    p->p_cred->pc_ucred, p);
+	    p->p_ucred, p);
 	cnt -= auio.uio_resid;
 	p->p_retval[0] = cnt;
 done:
@@ -3912,7 +3912,7 @@
 	}
 	cnt = auio.uio_resid;
 	error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio,
-	    p->p_cred->pc_ucred, p);
+	    p->p_ucred, p);
 	cnt -= auio.uio_resid;
 	p->p_retval[0] = cnt;
 done:
@@ -3995,7 +3995,7 @@
 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 
 	error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
-	    p->p_cred->pc_ucred, p);
+	    p->p_ucred, p);
 
 	VOP_UNLOCK(vp, 0, p);
 	vn_finished_write(mp);
Index: miscfs/procfs/procfs_status.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_status.c,v
retrieving revision 1.29
diff -u -r1.29 procfs_status.c
--- miscfs/procfs/procfs_status.c	2001/05/01 08:13:09	1.29
+++ miscfs/procfs/procfs_status.c	2001/05/13 03:24:15
@@ -153,11 +153,11 @@
 
 	ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " %lu %lu %lu", 
 		(u_long)cr->cr_uid,
-		(u_long)p->p_cred->p_ruid,
-		(u_long)p->p_cred->p_rgid);
+		(u_long)cr->cr_ruid,
+		(u_long)cr->cr_rgid);
 	DOCHECK();
 
-	/* egid (p->p_cred->p_svgid) is equal to cr_ngroups[0] 
+	/* egid (cr->cr_svgid) is equal to cr_ngroups[0] 
 	   see also getegid(2) in /sys/kern/kern_prot.c */
 
 	for (i = 0; i < cr->cr_ngroups; i++) {
Index: miscfs/procfs/procfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_vnops.c,v
retrieving revision 1.95
diff -u -r1.95 procfs_vnops.c
--- miscfs/procfs/procfs_vnops.c	2001/05/01 08:13:09	1.95
+++ miscfs/procfs/procfs_vnops.c	2001/05/13 03:24:22
@@ -404,7 +404,7 @@
 		procp = PFIND(pfs->pfs_pid);
 		if (procp == NULL)
 			return (ENOENT);
-		if (procp->p_cred == NULL || procp->p_ucred == NULL) {
+		if (procp->p_ucred == NULL) {
 			PROC_UNLOCK(procp);
 			return (ENOENT);
 		}
@@ -942,8 +942,7 @@
 	 */
 	case Pfile:
 		procp = PFIND(pfs->pfs_pid);
-		if (procp == NULL || procp->p_cred == NULL ||
-		    procp->p_ucred == NULL) {
+		if (procp == NULL || procp->p_ucred == NULL) {
 			if (procp != NULL)
 				PROC_UNLOCK(procp);
 			printf("procfs_readlink: pid %d disappeared\n",
Index: nfs/nfs_lock.c
===================================================================
RCS file: /home/ncvs/src/sys/nfs/nfs_lock.c,v
retrieving revision 1.4
diff -u -r1.4 nfs_lock.c
--- nfs/nfs_lock.c	2001/05/01 08:13:14	1.4
+++ nfs/nfs_lock.c	2001/05/13 03:24:34
@@ -236,9 +236,11 @@
 
 	/* Let root, or someone who once was root (lockd generally
 	 * switches to the daemon uid once it is done setting up) make 
-	 * this call
+	 * this call.
+	 *
+	 * XXX
 	 */
-	if ((error = suser(p)) != 0 && p->p_cred->p_svuid != 0)
+	if ((error = suser(p)) != 0 && p->p_ucred->cr_svuid != 0)
 		return (error);
 
 	/* the version should match, or we're out of sync */
Index: posix4/p1003_1b.c
===================================================================
RCS file: /home/ncvs/src/sys/posix4/p1003_1b.c,v
retrieving revision 1.9
diff -u -r1.9 p1003_1b.c
--- posix4/p1003_1b.c	2001/05/06 16:15:42	1.9
+++ posix4/p1003_1b.c	2001/05/13 03:24:35
@@ -68,16 +68,17 @@
 /*
  * This is stolen from CANSIGNAL in kern_sig:
  *
- * Can process p, with pcred pc, do "write flavor" operations to process q?
+ * Can process with credential cr1 do "write flavor" operations to credential
+ * cr2.  This check needs to use generalized checks.
  */
-#define CAN_AFFECT(p, q) \
-	(!suser_xxx(NULL, p, PRISON_ROOT) || \
-	    (p)->p_cred->pc_ruid == (q)->p_cred->p_ruid || \
-	    (p)->p_ucred->cr_uid == (q)->p_cred->p_ruid || \
-	    (p)->p_cred->pc_ruid == (q)->p_ucred->cr_uid || \
-	    (p)->p_ucred->cr_uid == (q)->p_ucred->cr_uid)
+#define CAN_AFFECT(cr1, cr2) \
+	(!suser_xxx(cr1, NULL, PRISON_ROOT) || \
+	    (c1)->cr_ruid == (cr2)->cr_ruid || \
+	    (c1)->cr_uid == (cr2)->cr_ruid || \
+	    (c1)->cr_ruid == (cr2)->cr_uid || \
+	    (c1)->cr_uid == (cr2)->cr_uid)
 #else
-#define CAN_AFFECT(p, q) (!suser_xxx(NULL, p, PRISON_ROOT))
+#define CAN_AFFECT(cr1, cr2) (!suser_xxx(cr1, NULL, PRISON_ROOT))
 #endif
 
 /*
@@ -99,7 +100,7 @@
 	{
 		/* Enforce permission policy.
 		 */
-		if (CAN_AFFECT(p, other_proc))
+		if (CAN_AFFECT(p->p_ucred, other_proc->p_ucred))
 			*pp = other_proc;
 		else
 			ret = EPERM;
Index: sys/filedesc.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/filedesc.h,v
retrieving revision 1.26
diff -u -r1.26 filedesc.h
--- sys/filedesc.h	2000/11/18 21:01:04	1.26
+++ sys/filedesc.h	2001/05/13 03:24:35
@@ -117,7 +117,6 @@
 	struct	sigio **sio_myref;	/* location of the pointer that holds
 					 * the reference to this structure */
 	struct	ucred *sio_ucred;	/* current credentials */
-	uid_t	sio_ruid;		/* real user id */
 	pid_t	sio_pgid;		/* pgid for signals */
 };
 #define	sio_proc	sio_u.siu_proc
Index: sys/proc.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/proc.h,v
retrieving revision 1.161
diff -u -r1.161 proc.h
--- sys/proc.h	2001/04/27 19:28:25	1.161
+++ sys/proc.h	2001/05/13 03:24:35
@@ -156,7 +156,7 @@
 	LIST_ENTRY(proc) p_list;	/* (d) List of all processes. */
 
 	/* substructures: */
-	struct	pcred *p_cred;		/* (c + k) Process owner's identity. */
+	struct	ucred *p_ucred;		/* (c + k) Process owner's identity. */
 	struct	filedesc *p_fd;		/* (b) Ptr to open files structure. */
 	struct	pstats *p_stats;	/* (b) Accounting/statistics (CPU). */
 	struct	plimit *p_limit;	/* (m) Process limits. */
@@ -166,7 +166,6 @@
 #define	p_sigignore	p_procsig->ps_sigignore
 #define	p_sigcatch	p_procsig->ps_sigcatch
 
-#define	p_ucred		p_cred->pc_ucred
 #define	p_rlimit	p_limit->pl_rlimit
 
 	int	p_flag;			/* (c) P_* flags. */
@@ -336,23 +335,6 @@
 #define	P_CAN_SEE	1
 #define	P_CAN_SCHED	3
 #define	P_CAN_DEBUG	4
-
-/*
- * MOVE TO ucred.h?
- *
- * Shareable process credentials (always resident).  This includes a reference
- * to the current user credentials as well as real and saved ids that may be
- * used to change ids.
- */
-struct	pcred {
-	struct	ucred *pc_ucred;	/* Current credentials. */
-	uid_t	p_ruid;			/* Real user id. */
-	uid_t	p_svuid;		/* Saved effective user id. */
-	gid_t	p_rgid;			/* Real group id. */
-	gid_t	p_svgid;		/* Saved effective group id. */
-	int	p_refcnt;		/* Number of references. */
-	struct	uidinfo *p_uidinfo;	/* Per uid resource consumption. */
-};
 
 #ifdef _KERNEL
 
Index: sys/ucred.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/ucred.h,v
retrieving revision 1.23
diff -u -r1.23 ucred.h
--- sys/ucred.h	2001/05/01 08:13:18	1.23
+++ sys/ucred.h	2001/05/13 03:24:35
@@ -50,9 +50,14 @@
 struct ucred {
 	u_int	cr_ref;			/* reference count */
 	uid_t	cr_uid;			/* effective user id */
+	uid_t	cr_ruid;		/* real user id */
+	uid_t	cr_svuid;		/* saved user id */
 	short	cr_ngroups;		/* number of groups */
 	gid_t	cr_groups[NGROUPS];	/* groups */
-	struct	uidinfo *cr_uidinfo;	/* per uid resource consumption */
+	gid_t	cr_rgid;		/* real group id */
+	gid_t	cr_svgid;		/* saved user id */
+	struct	uidinfo *cr_uidinfo;	/* per euid resource consumption */
+	struct	uidinfo *cr_ruidinfo;	/* per ruid resource consumption */
 	struct	prison *cr_prison;	/* jail(4) */
 	struct	mtx cr_mtx;		/* protect refcount */
 };
@@ -77,8 +82,12 @@
 
 struct proc;
 
-void		change_euid __P((struct proc *p, uid_t euid));
-void		change_ruid __P((struct proc *p, uid_t ruid));
+void		change_euid __P((struct ucred *newcred, uid_t euid));
+void		change_egid __P((struct ucred *newcred, gid_t egid));
+void		change_ruid __P((struct ucred *newcred, uid_t ruid));
+void		change_rgid __P((struct ucred *newcred, uid_t rgid));
+void		change_svuid __P((struct ucred *newcred, uid_t svuid));
+void		change_svgid __P((struct ucred *newcred, gid_t svgid));
 struct ucred	*crcopy __P((struct ucred *cr));
 struct ucred	*crdup __P((struct ucred *cr));
 void		crfree __P((struct ucred *cr));
Index: ufs/ufs/ufs_extattr.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ufs/ufs_extattr.c,v
retrieving revision 1.31
diff -u -r1.31 ufs_extattr.c
--- ufs/ufs/ufs_extattr.c	2001/04/29 02:45:28	1.31
+++ ufs/ufs/ufs_extattr.c	2001/05/13 03:24:36
@@ -621,7 +621,7 @@
 	auio.uio_rw = UIO_READ;
 	auio.uio_procp = (struct proc *) p;
 
-	VOP_LEASE(backing_vnode, p, p->p_cred->pc_ucred, LEASE_WRITE);
+	VOP_LEASE(backing_vnode, p, p->p_ucred, LEASE_WRITE);
 	vn_lock(backing_vnode, LK_SHARED | LK_NOPAUSE | LK_RETRY, p);
 	error = VOP_READ(backing_vnode, &auio, IO_NODELOCKED,
 	    ump->um_extattr.uepm_ucred);
@@ -702,7 +702,7 @@
 	 * Processes with privilege, but in jail, are not allowed to
 	 * configure extended attributes.
 	 */
-	if ((error = suser_xxx(p->p_cred->pc_ucred, p, 0))) {
+	if ((error = suser_xxx(p->p_ucred, p, 0))) {
 		if (filename_vp != NULL)
 			VOP_UNLOCK(filename_vp, 0, p);
 		return (error);
Index: ufs/ufs/ufs_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ufs/ufs_vfsops.c,v
retrieving revision 1.24
diff -u -r1.24 ufs_vfsops.c
--- ufs/ufs/ufs_vfsops.c	2001/05/01 08:13:19	1.24
+++ ufs/ufs/ufs_vfsops.c	2001/05/13 03:24:37
@@ -108,14 +108,14 @@
 	int cmd, type, error;
 
 	if (uid == -1)
-		uid = p->p_cred->p_ruid;
+		uid = p->p_ucred->cr_ruid;
 	cmd = cmds >> SUBCMDSHIFT;
 
 	switch (cmd) {
 	case Q_SYNC:
 		break;
 	case Q_GETQUOTA:
-		if (uid == p->p_cred->p_ruid)
+		if (uid == p->p_ucred->cr_ruid)
 			break;
 		/* fall through */
 	default:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.NEB.3.96L.1010512233942.49820B-100000>