diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index ab1578b3845f..b2412708fe11 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1131,9 +1131,9 @@ crget() { register struct ucred *cr; - MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); - bzero((caddr_t)cr, sizeof(*cr)); + MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK|M_ZERO); cr->cr_ref = 1; + mtx_init(&cr->cr_mtx, "ucred", MTX_DEF); return (cr); } @@ -1145,7 +1145,10 @@ void crfree(cr) struct ucred *cr; { + + mtx_enter(&cr->cr_mtx, MTX_DEF); if (--cr->cr_ref == 0) { + mtx_destroy(&cr->cr_mtx); /* * Some callers of crget(), such as nfs_statfs(), * allocate a temporary credential, but don't @@ -1154,6 +1157,8 @@ crfree(cr) if (cr->cr_uidinfo != NULL) uifree(cr->cr_uidinfo); FREE((caddr_t)cr, M_CRED); + } else { + mtx_exit(&cr->cr_mtx, MTX_DEF); } } @@ -1166,13 +1171,14 @@ crcopy(cr) { struct ucred *newcr; - if (cr->cr_ref == 1) + mtx_enter(&cr->cr_mtx, MTX_DEF); + if (cr->cr_ref == 1) { + mtx_exit(&cr->cr_mtx, MTX_DEF); return (cr); - newcr = crget(); - *newcr = *cr; - uihold(newcr->cr_uidinfo); + } + mtx_exit(&cr->cr_mtx, MTX_DEF); + newcr = crdup(cr); crfree(cr); - newcr->cr_ref = 1; return (newcr); } @@ -1185,8 +1191,9 @@ crdup(cr) { struct ucred *newcr; - newcr = crget(); + MALLOC(newcr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); *newcr = *cr; + mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF); uihold(newcr->cr_uidinfo); newcr->cr_ref = 1; return (newcr); diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h index 7857d168f278..ad5643ea942f 100644 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -37,6 +37,8 @@ #ifndef _SYS_UCRED_H_ #define _SYS_UCRED_H_ +#include + /* * Credentials. * @@ -44,7 +46,8 @@ * Only the suser()/suser_xxx() function should be used for this. */ struct ucred { - u_short cr_ref; /* reference count */ + struct mtx cr_mtx; /* protect refcount */ + u_int cr_ref; /* reference count */ uid_t cr_uid; /* effective user id */ short cr_ngroups; /* number of groups */ gid_t cr_groups[NGROUPS]; /* groups */ @@ -55,7 +58,12 @@ struct ucred { #define FSCRED ((struct ucred *)-1) /* filesystem credential */ #ifdef _KERNEL -#define crhold(cr) (cr)->cr_ref++ +#define crhold(cr) \ + do { \ + mtx_enter(&(cr)->cr_mtx, MTX_DEF); \ + (cr)->cr_ref++; \ + mtx_exit(&(cr)->cr_mtx, MTX_DEF); \ + } while (0) struct proc;