summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/compat/linux/linux_misc.c2
-rw-r--r--sys/compat/linux/linux_uid16.c2
-rw-r--r--sys/kern/init_main.c22
-rw-r--r--sys/kern/kern_exec.c4
-rw-r--r--sys/kern/kern_exit.c2
-rw-r--r--sys/kern/kern_fork.c5
-rw-r--r--sys/kern/kern_jail.c2
-rw-r--r--sys/kern/kern_loginclass.c2
-rw-r--r--sys/kern/kern_prot.c43
-rw-r--r--sys/kern/sys_capability.c2
-rw-r--r--sys/security/audit/audit_syscalls.c8
-rw-r--r--sys/security/mac/mac_syscalls.c2
-rw-r--r--sys/security/mac_lomac/mac_lomac.c2
-rw-r--r--sys/sys/ucred.h1
14 files changed, 64 insertions, 35 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index db7488b..cb2379a5 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -1338,7 +1338,7 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args)
newcred->cr_ngroups = 1;
setsugid(p);
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
crfree(oldcred);
error = 0;
diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c
index 9acc047..5e6b3df 100644
--- a/sys/compat/linux/linux_uid16.c
+++ b/sys/compat/linux/linux_uid16.c
@@ -214,7 +214,7 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args)
newcred->cr_ngroups = 1;
setsugid(td->td_proc);
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
crfree(oldcred);
error = 0;
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index ae6bd3a..03a3d9e 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -437,6 +437,7 @@ proc0_init(void *dummy __unused)
{
struct proc *p;
struct thread *td;
+ struct ucred *newcred;
vm_paddr_t pageablemem;
int i;
@@ -513,19 +514,20 @@ proc0_init(void *dummy __unused)
callout_init(&td->td_slpcallout, CALLOUT_MPSAFE);
/* Create credentials. */
- 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 = &prison0;
- p->p_ucred->cr_loginclass = loginclass_find("default");
+ newcred = crget();
+ newcred->cr_ngroups = 1; /* group 0 */
+ newcred->cr_uidinfo = uifind(0);
+ newcred->cr_ruidinfo = uifind(0);
+ newcred->cr_prison = &prison0;
+ newcred->cr_loginclass = loginclass_find("default");
+ proc_set_cred(p, newcred);
#ifdef AUDIT
- audit_cred_kproc0(p->p_ucred);
+ audit_cred_kproc0(newcred);
#endif
#ifdef MAC
- mac_cred_create_swapper(p->p_ucred);
+ mac_cred_create_swapper(newcred);
#endif
- td->td_ucred = crhold(p->p_ucred);
+ td->td_ucred = crhold(newcred);
/* Create sigacts. */
p->p_sigacts = sigacts_alloc();
@@ -844,7 +846,7 @@ create_init(const void *udata __unused)
#ifdef AUDIT
audit_cred_proc1(newcred);
#endif
- initproc->p_ucred = newcred;
+ proc_set_cred(initproc, newcred);
PROC_UNLOCK(initproc);
sx_xunlock(&proctree_lock);
crfree(oldcred);
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 188eba7..ef51347 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -751,7 +751,7 @@ interpret:
*/
change_svuid(newcred, newcred->cr_uid);
change_svgid(newcred, newcred->cr_gid);
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
} else {
if (oldcred->cr_uid == oldcred->cr_ruid &&
oldcred->cr_gid == oldcred->cr_rgid)
@@ -777,7 +777,7 @@ interpret:
PROC_LOCK(p);
change_svuid(newcred, newcred->cr_uid);
change_svgid(newcred, newcred->cr_gid);
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
}
}
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 76b4427..cb7387d 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -937,7 +937,7 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options)
* Free credentials, arguments, and sigacts.
*/
crfree(p->p_ucred);
- p->p_ucred = NULL;
+ proc_set_cred(p, NULL);
pargs_drop(p->p_args);
p->p_args = NULL;
sigacts_free(p->p_sigacts);
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 7b02c4d..6f5f74b 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -413,7 +413,8 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
p2->p_treeflag = 0;
p2->p_filemon = NULL;
- p2->p_ucred = crhold(td->td_ucred);
+ crhold(td->td_ucred);
+ proc_set_cred(p2, td->td_ucred);
/* Tell the prison that we exist. */
prison_proc_hold(p2->p_ucred->cr_prison);
@@ -913,7 +914,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
* XXX: This is ugly; when we copy resource usage, we need to bump
* per-cred resource counters.
*/
- newproc->p_ucred = p1->p_ucred;
+ proc_set_cred(newproc, p1->p_ucred);
/*
* Initialize resource accounting for the child process.
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index a0e4c61..5d7824d 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -2476,7 +2476,7 @@ do_jail_attach(struct thread *td, struct prison *pr)
PROC_LOCK(p);
oldcred = crcopysafe(p, newcred);
newcred->cr_prison = pr;
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
setsugid(p);
PROC_UNLOCK(p);
#ifdef RACCT
diff --git a/sys/kern/kern_loginclass.c b/sys/kern/kern_loginclass.c
index b20f60b..04f6809 100644
--- a/sys/kern/kern_loginclass.c
+++ b/sys/kern/kern_loginclass.c
@@ -205,7 +205,7 @@ sys_setloginclass(struct thread *td, struct setloginclass_args *uap)
PROC_LOCK(p);
oldcred = crcopysafe(p, newcred);
newcred->cr_loginclass = newlc;
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
#ifdef RACCT
racct_proc_ucred_changed(p, oldcred, newcred);
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 03b9001..a7d4331 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -582,7 +582,7 @@ sys_setuid(struct thread *td, struct setuid_args *uap)
change_euid(newcred, uip);
setsugid(p);
}
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
#ifdef RACCT
racct_proc_ucred_changed(p, oldcred, newcred);
@@ -641,7 +641,7 @@ sys_seteuid(struct thread *td, struct seteuid_args *uap)
change_euid(newcred, euip);
setsugid(p);
}
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
uifree(euip);
crfree(oldcred);
@@ -741,7 +741,7 @@ sys_setgid(struct thread *td, struct setgid_args *uap)
change_egid(newcred, gid);
setsugid(p);
}
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
crfree(oldcred);
return (0);
@@ -787,7 +787,7 @@ sys_setegid(struct thread *td, struct setegid_args *uap)
change_egid(newcred, egid);
setsugid(p);
}
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
crfree(oldcred);
return (0);
@@ -860,7 +860,7 @@ kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups)
crsetgroups_locked(newcred, ngrp, groups);
}
setsugid(p);
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
crfree(oldcred);
return (0);
@@ -923,7 +923,7 @@ sys_setreuid(register struct thread *td, struct setreuid_args *uap)
change_svuid(newcred, newcred->cr_uid);
setsugid(p);
}
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
#ifdef RACCT
racct_proc_ucred_changed(p, oldcred, newcred);
@@ -990,7 +990,7 @@ sys_setregid(register struct thread *td, struct setregid_args *uap)
change_svgid(newcred, newcred->cr_groups[0]);
setsugid(p);
}
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
crfree(oldcred);
return (0);
@@ -1064,7 +1064,7 @@ sys_setresuid(register struct thread *td, struct setresuid_args *uap)
change_svuid(newcred, suid);
setsugid(p);
}
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
#ifdef RACCT
racct_proc_ucred_changed(p, oldcred, newcred);
@@ -1143,7 +1143,7 @@ sys_setresgid(register struct thread *td, struct setresgid_args *uap)
change_svgid(newcred, sgid);
setsugid(p);
}
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
crfree(oldcred);
return (0);
@@ -1956,6 +1956,31 @@ cred_update_thread(struct thread *td)
crfree(cred);
}
+/*
+ * Change process credentials.
+ * Callers are responsible for providing the reference for current credentials
+ * and for freeing old ones.
+ *
+ * Process has to be locked except when it does not have credentials (as it
+ * should not be visible just yet) or when newcred is NULL (as this can be
+ * only used when the process is about to be freed, at which point it should
+ * not be visible anymore).
+ */
+struct ucred *
+proc_set_cred(struct proc *p, struct ucred *newcred)
+{
+ struct ucred *oldcred;
+
+ if (newcred == NULL)
+ MPASS(p->p_state == PRS_ZOMBIE);
+ else if (p->p_ucred != NULL)
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ oldcred = p->p_ucred;
+ p->p_ucred = newcred;
+ return (oldcred);
+}
+
struct ucred *
crcopysafe(struct proc *p, struct ucred *cr)
{
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
index b309905..b3dc1b5 100644
--- a/sys/kern/sys_capability.c
+++ b/sys/kern/sys_capability.c
@@ -105,7 +105,7 @@ sys_cap_enter(struct thread *td, struct cap_enter_args *uap)
oldcred = p->p_ucred;
crcopy(newcred, oldcred);
newcred->cr_flags |= CRED_FLAG_CAPMODE;
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
crfree(oldcred);
return (0);
diff --git a/sys/security/audit/audit_syscalls.c b/sys/security/audit/audit_syscalls.c
index 6ef606b..90d811d 100644
--- a/sys/security/audit/audit_syscalls.c
+++ b/sys/security/audit/audit_syscalls.c
@@ -461,7 +461,7 @@ sys_auditon(struct thread *td, struct auditon_args *uap)
udata.au_aupinfo.ap_mask.am_success;
newcred->cr_audit.ai_mask.am_failure =
udata.au_aupinfo.ap_mask.am_failure;
- tp->p_ucred = newcred;
+ proc_set_cred(tp, newcred);
PROC_UNLOCK(tp);
crfree(oldcred);
break;
@@ -600,7 +600,7 @@ sys_setauid(struct thread *td, struct setauid_args *uap)
if (error)
goto fail;
newcred->cr_audit.ai_auid = id;
- td->td_proc->p_ucred = newcred;
+ proc_set_cred(td->td_proc, newcred);
PROC_UNLOCK(td->td_proc);
crfree(oldcred);
return (0);
@@ -671,7 +671,7 @@ sys_setaudit(struct thread *td, struct setaudit_args *uap)
newcred->cr_audit.ai_termid.at_addr[0] = ai.ai_termid.machine;
newcred->cr_audit.ai_termid.at_port = ai.ai_termid.port;
newcred->cr_audit.ai_termid.at_type = AU_IPv4;
- td->td_proc->p_ucred = newcred;
+ proc_set_cred(td->td_proc, newcred);
PROC_UNLOCK(td->td_proc);
crfree(oldcred);
return (0);
@@ -728,7 +728,7 @@ sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
if (error)
goto fail;
newcred->cr_audit = aia;
- td->td_proc->p_ucred = newcred;
+ proc_set_cred(td->td_proc, newcred);
PROC_UNLOCK(td->td_proc);
crfree(oldcred);
return (0);
diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c
index f084ea4..304d313 100644
--- a/sys/security/mac/mac_syscalls.c
+++ b/sys/security/mac/mac_syscalls.c
@@ -208,7 +208,7 @@ sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
setsugid(p);
crcopy(newcred, oldcred);
mac_cred_relabel(newcred, intlabel);
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
PROC_UNLOCK(p);
crfree(oldcred);
diff --git a/sys/security/mac_lomac/mac_lomac.c b/sys/security/mac_lomac/mac_lomac.c
index 40c9c2f..67f3a36 100644
--- a/sys/security/mac_lomac/mac_lomac.c
+++ b/sys/security/mac_lomac/mac_lomac.c
@@ -2275,7 +2275,7 @@ lomac_thread_userret(struct thread *td)
crcopy(newcred, oldcred);
crhold(newcred);
lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label));
- p->p_ucred = newcred;
+ proc_set_cred(p, newcred);
crfree(oldcred);
dodrop = 1;
out:
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index 45ed0d5..b3d6f52 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -106,6 +106,7 @@ struct ucred *crcopysafe(struct proc *p, struct ucred *cr);
struct ucred *crdup(struct ucred *cr);
void crextend(struct ucred *cr, int n);
void cred_update_thread(struct thread *td);
+struct ucred *proc_set_cred(struct proc *p, struct ucred *cr);
void crfree(struct ucred *cr);
struct ucred *crget(void);
struct ucred *crhold(struct ucred *cr);
OpenPOWER on IntegriCloud