Index: sys/kern/init_main.c =================================================================== --- sys/kern/init_main.c +++ sys/kern/init_main.c @@ -531,7 +531,7 @@ newcred->cr_ruidinfo = uifind(0); newcred->cr_prison = &prison0; newcred->cr_loginclass = loginclass_find("default"); - proc_set_cred(p, newcred); + proc_set_cred_init(p, newcred); #ifdef AUDIT audit_cred_kproc0(newcred); #endif Index: sys/kern/kern_fork.c =================================================================== --- sys/kern/kern_fork.c +++ sys/kern/kern_fork.c @@ -419,9 +419,6 @@ p2->p_treeflag = 0; p2->p_filemon = NULL; - 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); @@ -892,7 +889,7 @@ td2 = thread_alloc(pages); if (td2 == NULL) { error = ENOMEM; - goto fail1; + goto fail2; } proc_linkup(newproc, td2); } else { @@ -901,7 +898,7 @@ vm_thread_dispose(td2); if (!thread_alloc_stack(td2, pages)) { error = ENOMEM; - goto fail1; + goto fail2; } } } @@ -910,7 +907,7 @@ vm2 = vmspace_fork(p1->p_vmspace, &mem_charged); if (vm2 == NULL) { error = ENOMEM; - goto fail1; + goto fail2; } if (!swap_reserve(mem_charged)) { /* @@ -921,7 +918,7 @@ */ swap_reserve_force(mem_charged); error = ENOMEM; - goto fail1; + goto fail2; } } else vm2 = NULL; @@ -930,7 +927,7 @@ * XXX: This is ugly; when we copy resource usage, we need to bump * per-cred resource counters. */ - proc_set_cred(newproc, p1->p_ucred); + proc_set_cred_init(newproc, crhold(td->td_ucred)); /* * Initialize resource accounting for the child process. @@ -991,6 +988,9 @@ #endif racct_proc_exit(newproc); fail1: + crfree(newproc->p_ucred); + newproc->p_ucred = NULL; +fail2: if (vm2 != NULL) vmspace_free(vm2); uma_zfree(proc_zone, newproc); Index: sys/kern/kern_prot.c =================================================================== --- sys/kern/kern_prot.c +++ sys/kern/kern_prot.c @@ -1971,8 +1971,19 @@ } /* + * Set initial process credentials. + * Callers are responsible for providing the reference for provided credentials. + */ +void +proc_set_cred_init(struct proc *p, struct ucred *newcred) +{ + + p->p_ucred = newcred; +} + +/* * Change process credentials. - * Callers are responsible for providing the reference for current credentials + * Callers are responsible for providing the reference for passed credentials * and for freeing old ones. * * Process has to be locked except when it does not have credentials (as it @@ -1985,9 +1996,10 @@ { struct ucred *oldcred; + MPASS(p->p_ucred != NULL); if (newcred == NULL) MPASS(p->p_state == PRS_ZOMBIE); - else if (p->p_ucred != NULL) + else PROC_LOCK_ASSERT(p, MA_OWNED); oldcred = p->p_ucred; Index: sys/sys/ucred.h =================================================================== --- sys/sys/ucred.h +++ sys/sys/ucred.h @@ -106,6 +106,7 @@ struct ucred *crdup(struct ucred *cr); void crextend(struct ucred *cr, int n); void cred_update_thread(struct thread *td); +void proc_set_cred_init(struct proc *p, struct ucred *cr); struct ucred *proc_set_cred(struct proc *p, struct ucred *cr); void crfree(struct ucred *cr); struct ucred *crget(void);