summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libkvm/kvm_proc.c12
-rw-r--r--sys/alpha/osf1/osf1_misc.c47
-rw-r--r--sys/compat/linprocfs/linprocfs.c10
-rw-r--r--sys/compat/linprocfs/linprocfs_misc.c10
-rw-r--r--sys/compat/linprocfs/linprocfs_vnops.c2
-rw-r--r--sys/compat/linux/linux_misc.c24
-rw-r--r--sys/compat/svr4/svr4_misc.c11
-rw-r--r--sys/compat/svr4/svr4_sysvec.c8
-rw-r--r--sys/ddb/db_ps.c2
-rw-r--r--sys/fs/procfs/procfs_status.c6
-rw-r--r--sys/fs/procfs/procfs_vnops.c5
-rw-r--r--sys/i386/linux/linux_sysvec.c8
-rw-r--r--sys/kern/init_main.c7
-rw-r--r--sys/kern/kern_acct.c4
-rw-r--r--sys/kern/kern_descrip.c2
-rw-r--r--sys/kern/kern_exec.c58
-rw-r--r--sys/kern/kern_exit.c10
-rw-r--r--sys/kern/kern_fork.c12
-rw-r--r--sys/kern/kern_ktrace.c16
-rw-r--r--sys/kern/kern_proc.c18
-rw-r--r--sys/kern/kern_prot.c451
-rw-r--r--sys/kern/kern_sig.c23
-rw-r--r--sys/kern/p1003_1b.c19
-rw-r--r--sys/kern/uipc_usrreq.c4
-rw-r--r--sys/kern/vfs_extattr.c10
-rw-r--r--sys/kern/vfs_syscalls.c10
-rw-r--r--sys/nfs/nfs_lock.c6
-rw-r--r--sys/nfsclient/nfs_lock.c6
-rw-r--r--sys/posix4/p1003_1b.c19
-rw-r--r--sys/sys/filedesc.h1
-rw-r--r--sys/sys/proc.h20
-rw-r--r--sys/sys/ucred.h15
-rw-r--r--sys/ufs/ufs/ufs_extattr.c4
-rw-r--r--sys/ufs/ufs/ufs_vfsops.c4
34 files changed, 489 insertions, 375 deletions
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c
index d313925..b45aec2 100644
--- a/lib/libkvm/kvm_proc.c
+++ b/lib/libkvm/kvm_proc.c
@@ -114,7 +114,6 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
struct tty tty;
struct vmspace vmspace;
struct procsig procsig;
- struct pcred pcred;
struct pstats pstats;
struct ucred ucred;
struct proc proc;
@@ -127,12 +126,11 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
_kvm_err(kd, kd->program, "can't read proc at %x", p);
return (-1);
}
- if (KREAD(kd, (u_long)proc.p_cred, &pcred) == 0) {
- kp->ki_ruid = pcred.p_ruid;
- kp->ki_svuid = pcred.p_svuid;
- kp->ki_rgid = pcred.p_rgid;
- kp->ki_svgid = pcred.p_svgid;
- (void)(KREAD(kd, (u_long)pcred.pc_ucred, &ucred));
+ if (KREAD(kd, (u_long)proc.p_ucred, &ucred) == 0) {
+ kp->ki_ruid = ucred.cr_ruid;
+ kp->ki_svuid = ucred.cr_svuid;
+ kp->ki_rgid = ucred.cr_rgid;
+ kp->ki_svgid = ucred.cr_svgid;
kp->ki_ngroups = ucred.cr_ngroups;
bcopy(ucred.cr_groups, kp->ki_groups,
NGROUPS * sizeof(gid_t));
diff --git a/sys/alpha/osf1/osf1_misc.c b/sys/alpha/osf1/osf1_misc.c
index 707e640..7d9a213 100644
--- a/sys/alpha/osf1/osf1_misc.c
+++ b/sys/alpha/osf1/osf1_misc.c
@@ -1054,29 +1054,32 @@ osf1_setuid(p, uap)
{
int error;
uid_t uid;
- register struct pcred *pc;
+ struct ucred *newcred, oldcred;
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 @@ osf1_setgid(p, uap)
{
int error;
gid_t gid;
- register struct pcred *pc;
+ struct ucred *newcred, *oldcred;
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);
}
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 6a356fb..04858f7 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -478,14 +478,14 @@ linprocfs_doprocstatus(curp, p, pfs, uio)
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");
@@ -577,7 +577,7 @@ linprocfs_doexelink(curp, p, pfs, uio)
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);
diff --git a/sys/compat/linprocfs/linprocfs_misc.c b/sys/compat/linprocfs/linprocfs_misc.c
index 6a356fb..04858f7 100644
--- a/sys/compat/linprocfs/linprocfs_misc.c
+++ b/sys/compat/linprocfs/linprocfs_misc.c
@@ -478,14 +478,14 @@ linprocfs_doprocstatus(curp, p, pfs, uio)
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");
@@ -577,7 +577,7 @@ linprocfs_doexelink(curp, p, pfs, uio)
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);
diff --git a/sys/compat/linprocfs/linprocfs_vnops.c b/sys/compat/linprocfs/linprocfs_vnops.c
index 2bb824e..08a5023 100644
--- a/sys/compat/linprocfs/linprocfs_vnops.c
+++ b/sys/compat/linprocfs/linprocfs_vnops.c
@@ -433,7 +433,7 @@ linprocfs_getattr(ap)
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);
}
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 2c7c9b5..64200b1 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -958,13 +958,13 @@ linux_setgroups(p, uap)
struct proc *p;
struct linux_setgroups_args *uap;
{
- struct pcred *pc;
+ struct ucred *newcred, *oldcred;
linux_gid_t linux_gidset[NGROUPS];
gid_t *bsd_gidset;
int ngrp, error;
- pc = p->p_cred;
ngrp = uap->gidsetsize;
+ oldcred = p->p_ucred;
/*
* cr_groups[0] holds egid. Setting the whole set from
@@ -972,22 +972,22 @@ linux_setgroups(p, uap)
* 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 +995,11 @@ linux_setgroups(p, uap)
}
}
else
- pc->pc_ucred->cr_ngroups = 1;
+ newcred->cr_ngroups = 1;
setsugid(p);
+ p->p_ucred = newcred;
+ crfree(oldcred);
return (0);
}
@@ -1006,14 +1008,14 @@ linux_getgroups(p, uap)
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
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
index 1baed66..a92e8a4 100644
--- a/sys/compat/svr4/svr4_misc.c
+++ b/sys/compat/svr4/svr4_misc.c
@@ -1283,7 +1283,7 @@ loop:
/*
* 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 @@ loop:
/*
* 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
diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c
index 912cd2a..9137e0c 100644
--- a/sys/compat/svr4/svr4_sysvec.c
+++ b/sys/compat/svr4/svr4_sysvec.c
@@ -213,10 +213,10 @@ svr4_fixup(register_t **stack_base, struct image_params *imgp)
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);
diff --git a/sys/ddb/db_ps.c b/sys/ddb/db_ps.c
index bccda5a..cbedb1e 100644
--- a/sys/ddb/db_ps.c
+++ b/sys/ddb/db_ps.c
@@ -95,7 +95,7 @@ db_ps(dummy1, dummy2, dummy3, dummy4)
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);
diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c
index 9620be5..0f57e49 100644
--- a/sys/fs/procfs/procfs_status.c
+++ b/sys/fs/procfs/procfs_status.c
@@ -153,11 +153,11 @@ procfs_dostatus(curp, p, pfs, uio)
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++) {
diff --git a/sys/fs/procfs/procfs_vnops.c b/sys/fs/procfs/procfs_vnops.c
index a054eb9..4ca89ac 100644
--- a/sys/fs/procfs/procfs_vnops.c
+++ b/sys/fs/procfs/procfs_vnops.c
@@ -403,7 +403,7 @@ procfs_getattr(ap)
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);
}
@@ -941,8 +941,7 @@ procfs_readlink(ap)
*/
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",
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 0734ba4..de82774 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -187,10 +187,10 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
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);
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 5624720..9698983 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -85,7 +85,6 @@ void mi_startup(void); /* Should be elsewhere */
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;
@@ -333,12 +332,10 @@ proc0_init(void *dummy __unused)
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. */
@@ -394,7 +391,7 @@ proc0_init(void *dummy __unused)
/*
* 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)
diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c
index 7562e31..98f2495 100644
--- a/sys/kern/kern_acct.c
+++ b/sys/kern/kern_acct.c
@@ -222,8 +222,8 @@ acct_process(p)
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)
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index f89e413..b2cc930 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -525,8 +525,6 @@ fsetown(pgid, sigiop)
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;
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index abb08fc..e3ae485 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -104,6 +104,7 @@ execve(p, uap)
register struct execve_args *uap;
{
struct nameidata nd, *ndp;
+ struct ucred *newcred, *oldcred;
register_t *stack_base;
int error, len, i;
struct image_params image_params, *imgp;
@@ -274,13 +275,24 @@ interpret:
}
/*
+ * 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)) &&
+ oldcred = p->p_ucred;
+ 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 +300,7 @@ interpret:
* 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 +308,49 @@ interpret:
/*
* 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 sourses 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 (oldcred->cr_svuid != oldcred->cr_uid ||
+ oldcred->cr_svgid != oldcred->cr_gid) {
+ /*
+ * Avoid allocating a newcred if we don't have one yet and
+ * the saved uid/gid update would be a noop.
+ */
+ if (newcred == NULL)
+ newcred = crdup(oldcred);
+ change_svuid(newcred, newcred->cr_uid);
+ change_svgid(newcred, newcred->cr_gid);
+ }
+ if (newcred != NULL) {
+ PROC_LOCK(p);
+ p->p_ucred = newcred;
+ PROC_UNLOCK(p);
+ crfree(oldcred);
+ }
/*
* Store the vp for use in procfs
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 1af27d2..6454d11 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -516,7 +516,7 @@ loop:
/*
* 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
@@ -541,12 +541,8 @@ loop:
/*
* 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
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 62dcc06..6774f64 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -258,7 +258,7 @@ fork1(p1, flags, procp)
* 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);
@@ -273,7 +273,7 @@ fork1(p1, flags, procp)
* 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) {
/*
@@ -409,15 +409,9 @@ again:
* 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++;
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index ce972bd..15b51c8 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -531,17 +531,17 @@ static int
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);
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index d441144..f45ac26 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -424,15 +424,15 @@ fill_kinfo_proc(p, kp)
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 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
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;
}
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index f0b4ff8..fcef6d0 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -210,7 +210,7 @@ getuid(p, uap)
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 @@ getgid(p, uap)
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 @@ getgroups(p, uap)
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,10 +427,12 @@ setuid(p, uap)
struct proc *p;
struct setuid_args *uap;
{
- register struct pcred *pc = p->p_cred;
- register uid_t uid;
+ struct ucred *newcred, *oldcred;
+ uid_t uid;
int error;
+ uid = uap->uid;
+ oldcred = p->p_ucred;
/*
* See if we have "permission" by POSIX 1003.1 rules.
*
@@ -448,17 +450,17 @@ setuid(p, uap)
* change. Determined by compile options.
* 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 +468,16 @@ setuid(p, uap)
*/
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 +487,8 @@ setuid(p, uap)
* 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 +497,12 @@ setuid(p, uap)
* 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 +517,27 @@ seteuid(p, uap)
struct proc *p;
struct seteuid_args *uap;
{
- register struct pcred *pc = p->p_cred;
- register uid_t euid;
+ struct ucred *newcred, *oldcred;
+ 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)))
+ oldcred = p->p_ucred;
+ 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,10 +552,12 @@ setgid(p, uap)
struct proc *p;
struct setgid_args *uap;
{
- register struct pcred *pc = p->p_cred;
- register gid_t gid;
+ struct ucred *newcred, *oldcred;
+ gid_t gid;
int error;
+ gid = uap->gid;
+ oldcred = p->p_ucred;
/*
* See if we have "permission" by POSIX 1003.1 rules.
*
@@ -559,17 +569,17 @@ setgid(p, uap)
*
* 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 +587,16 @@ setgid(p, uap)
*/
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 +606,8 @@ setgid(p, uap)
* 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 +615,12 @@ setgid(p, uap)
* 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 +635,23 @@ setegid(p, uap)
struct proc *p;
struct setegid_args *uap;
{
- register struct pcred *pc = p->p_cred;
- register gid_t egid;
+ struct ucred *newcred, *oldcred;
+ 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)))
+ oldcred = p->p_ucred;
+ 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,20 +667,21 @@ setgroups(p, uap)
struct proc *p;
struct setgroups_args *uap;
{
- register struct pcred *pc = p->p_cred;
- register u_int ngrp;
+ struct ucred *newcred, *oldcred;
+ u_int ngrp;
int error;
- if ((error = suser_xxx(0, p, PRISON_ROOT)))
- return (error);
ngrp = uap->gidsetsize;
+ oldcred = p->p_ucred;
+ if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
+ return (error);
if (ngrp > NGROUPS)
return (EINVAL);
/*
* 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 +689,18 @@ setgroups(p, uap)
* 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 +716,35 @@ setreuid(p, uap)
register struct proc *p;
struct setreuid_args *uap;
{
- register struct pcred *pc = p->p_cred;
- register uid_t ruid, euid;
+ struct ucred *newcred, *oldcred;
+ 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)
+ oldcred = p->p_ucred;
+ 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;
+ 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 +760,32 @@ setregid(p, uap)
register struct proc *p;
struct setregid_args *uap;
{
- register struct pcred *pc = p->p_cred;
- register gid_t rgid, egid;
+ struct ucred *newcred, *oldcred;
+ 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)
+ oldcred = p->p_ucred;
+ 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];
+ 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 +809,41 @@ setresuid(p, uap)
register struct proc *p;
struct setresuid_args *uap;
{
- register struct pcred *pc = p->p_cred;
- register uid_t ruid, euid, suid;
+ struct ucred *newcred, *oldcred;
+ 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)
+ oldcred = p->p_ucred;
+ 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 +865,41 @@ setresgid(p, uap)
register struct proc *p;
struct setresgid_args *uap;
{
- register struct pcred *pc = p->p_cred;
- register gid_t rgid, egid, sgid;
+ struct ucred *newcred, *oldcred;
+ 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)
+ oldcred = p->p_ucred;
+ 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 +916,18 @@ getresuid(p, uap)
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 +944,18 @@ getresgid(p, uap)
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 +1011,7 @@ __setugid(p, uap)
int
groupmember(gid, cred)
gid_t gid;
- register struct ucred *cred;
+ struct ucred *cred;
{
register gid_t *gp;
gid_t *egp;
@@ -1038,7 +1077,7 @@ u_cansee(struct ucred *u1, struct ucred *u2)
if ((error = prison_check(u1, u2)))
return (error);
- if (!ps_showallprocs && u1->cr_uid != u2->cr_uid) {
+ if (!ps_showallprocs && u1->cr_ruid != u2->cr_ruid) {
if (suser_xxx(u1, NULL, PRISON_ROOT) != 0)
return (ESRCH);
}
@@ -1113,10 +1152,10 @@ p_cansignal(struct proc *p1, struct proc *p2, int signum)
* 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 +1179,9 @@ p_cansched(struct proc *p1, struct proc *p2, int *privused)
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 +1217,9 @@ p_candebug(struct proc *p1, struct proc *p2, int *privused)
/* 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->pc_ucred->cr_uid ||
- p1->p_cred->pc_ucred->cr_uid != p2->p_cred->p_svuid ||
- p1->p_cred->pc_ucred->cr_uid != p2->p_cred->p_ruid ||
+ if (p1->p_ucred->cr_uid != p2->p_ucred->cr_uid ||
+ p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid ||
+ p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid ||
p2->p_flag & P_SUGID) {
if ((error = suser_xxx(0, p1, PRISON_ROOT)))
return (error);
@@ -1308,6 +1347,7 @@ crdup(cr)
*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 +1415,99 @@ setsugid(p)
}
/*
- * Helper function to change the effective uid of a process
+ * change_euid(): Change a process's effective uid.
+ * 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.
*/
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.
+ * Side effects: newcred->cr_gid will be modified.
+ * References: newcred must be an exclusive credential reference for the
+ * duration of the call.
*/
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.
+ * 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.
+ */
+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.
+ * Side effects: newcred->cr_rgid will be updated.
+ * References: newcred must be an exclusive credential reference for the
+ * duration of the call.
+ */
+void
+change_rgid(newcred, rgid)
+ struct ucred *newcred;
+ gid_t rgid;
{
- 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_rgid = rgid;
+}
+
+/*
+ * change_svuid(): Change a process's saved uid.
+ * Side effects: newcred->cr_svuid will be updated.
+ * References: newcred must be an exclusive credential reference for the
+ * duration of the call.
+ */
+void
+change_svuid(newcred, svuid)
+ struct ucred *newcred;
+ uid_t svuid;
+{
+
+ newcred->cr_svuid = svuid;
+}
+
+/*
+ * change_svgid(): Change a process's saved gid.
+ * Side effects: newcred->cr_svgid will be updated.
+ * References: newcred must be an exclusive credential reference for the
+ * duration of the call.
+ */
+void
+change_svgid(newcred, svgid)
+ struct ucred *newcred;
+ gid_t svgid;
+{
+
+ newcred->cr_svgid = svgid;
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 56837f4..ae68268 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -97,14 +97,14 @@ SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW,
"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,
@@ -1612,7 +1612,7 @@ killproc(p, why)
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);
+ p->p_ucred ? p->p_ucred->cr_uid : -1, why);
psignal(p, SIGKILL);
}
@@ -1649,7 +1649,7 @@ sigexit(p, sig)
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 {
@@ -1869,8 +1869,7 @@ pgsigio(sigio, sig, checkctty)
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) {
@@ -1878,7 +1877,7 @@ pgsigio(sigio, sig, checkctty)
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);
diff --git a/sys/kern/p1003_1b.c b/sys/kern/p1003_1b.c
index 569bb6f..cf2c7da 100644
--- a/sys/kern/p1003_1b.c
+++ b/sys/kern/p1003_1b.c
@@ -68,16 +68,17 @@ MALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B");
/*
* 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 @@ int p31b_proc(struct proc *p, pid_t pid, struct proc **pp)
{
/* 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;
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 33ff735..2907b4e 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -988,8 +988,8 @@ unp_internalize(control, p)
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);
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 89041a6..75d3eb7 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -1710,8 +1710,8 @@ access(p, uap)
* 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);
@@ -3801,7 +3801,7 @@ extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
}
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:
@@ -3914,7 +3914,7 @@ extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
}
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:
@@ -3997,7 +3997,7 @@ extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
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);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 89041a6..75d3eb7 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1710,8 +1710,8 @@ access(p, uap)
* 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);
@@ -3801,7 +3801,7 @@ extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
}
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:
@@ -3914,7 +3914,7 @@ extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
}
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:
@@ -3997,7 +3997,7 @@ extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
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);
diff --git a/sys/nfs/nfs_lock.c b/sys/nfs/nfs_lock.c
index 9fd243a..85bc9d9 100644
--- a/sys/nfs/nfs_lock.c
+++ b/sys/nfs/nfs_lock.c
@@ -236,9 +236,11 @@ nfslockdans(p, ansp)
/* 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 This authorization check is probably not right.
*/
- 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 */
diff --git a/sys/nfsclient/nfs_lock.c b/sys/nfsclient/nfs_lock.c
index 9fd243a..85bc9d9 100644
--- a/sys/nfsclient/nfs_lock.c
+++ b/sys/nfsclient/nfs_lock.c
@@ -236,9 +236,11 @@ nfslockdans(p, ansp)
/* 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 This authorization check is probably not right.
*/
- 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 */
diff --git a/sys/posix4/p1003_1b.c b/sys/posix4/p1003_1b.c
index 569bb6f..cf2c7da 100644
--- a/sys/posix4/p1003_1b.c
+++ b/sys/posix4/p1003_1b.c
@@ -68,16 +68,17 @@ MALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B");
/*
* 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 @@ int p31b_proc(struct proc *p, pid_t pid, struct proc **pp)
{
/* 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;
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 273ddf1..c0cb850 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -117,7 +117,6 @@ struct sigio {
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
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index d953b1d..3201669 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -156,7 +156,7 @@ struct proc {
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 @@ struct proc {
#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. */
@@ -337,23 +336,6 @@ struct proc {
#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
#ifdef MALLOC_DECLARE
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index c48df00..356cca2 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -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 xucred {
struct proc;
-void change_euid __P((struct proc *p, uid_t euid));
-void change_ruid __P((struct proc *p, uid_t ruid));
+void change_egid __P((struct ucred *newcred, gid_t egid));
+void change_euid __P((struct ucred *newcred, uid_t euid));
+void change_rgid __P((struct ucred *newcred, gid_t rgid));
+void change_ruid __P((struct ucred *newcred, uid_t ruid));
+void change_svgid __P((struct ucred *newcred, gid_t svgid));
+void change_svuid __P((struct ucred *newcred, uid_t svuid));
struct ucred *crcopy __P((struct ucred *cr));
struct ucred *crdup __P((struct ucred *cr));
void crfree __P((struct ucred *cr));
diff --git a/sys/ufs/ufs/ufs_extattr.c b/sys/ufs/ufs/ufs_extattr.c
index e77e9fb..817fde3 100644
--- a/sys/ufs/ufs/ufs_extattr.c
+++ b/sys/ufs/ufs/ufs_extattr.c
@@ -621,7 +621,7 @@ ufs_extattr_enable(struct ufsmount *ump, int attrnamespace,
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 @@ ufs_extattrctl(struct mount *mp, int cmd, struct vnode *filename_vp,
* 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);
diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c
index 5c293df..6b8905b 100644
--- a/sys/ufs/ufs/ufs_vfsops.c
+++ b/sys/ufs/ufs/ufs_vfsops.c
@@ -108,14 +108,14 @@ ufs_quotactl(mp, cmds, uid, arg, p)
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:
OpenPOWER on IntegriCloud