diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 819a964166f1..90515fb784c0 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_prot.c,v 1.82 2004/04/25 16:42:41 simonb Exp $ */ +/* $NetBSD: kern_prot.c,v 1.83 2004/05/02 12:36:55 pk Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.82 2004/04/25 16:42:41 simonb Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.83 2004/05/02 12:36:55 pk Exp $"); #include "opt_compat_43.h" @@ -620,6 +620,7 @@ crget(void) cr = pool_get(&cred_pool, PR_WAITOK); memset(cr, 0, sizeof(*cr)); + simple_lock_init(&cr->cr_lock); cr->cr_ref = 1; return (cr); } @@ -631,8 +632,12 @@ crget(void) void crfree(struct ucred *cr) { + int n; - if (--cr->cr_ref == 0) + simple_lock(&cr->cr_lock); + n = --cr->cr_ref; + simple_unlock(&cr->cr_lock); + if (n == 0) pool_put(&cred_pool, cr); } @@ -655,13 +660,18 @@ struct ucred * crcopy(struct ucred *cr) { struct ucred *newcr; + int n; - if (cr->cr_ref == 1) + simple_lock(&cr->cr_lock); + n = cr->cr_ref; + simple_unlock(&cr->cr_lock); + if (n == 1) return (cr); + newcr = crget(); - *newcr = *cr; + memcpy(&newcr->cr_startcopy, &cr->cr_startcopy, + sizeof(struct ucred) - offsetof(struct ucred, cr_startcopy)); crfree(cr); - newcr->cr_ref = 1; return (newcr); } @@ -674,8 +684,8 @@ crdup(const struct ucred *cr) struct ucred *newcr; newcr = crget(); - *newcr = *cr; - newcr->cr_ref = 1; + memcpy(&newcr->cr_startcopy, &cr->cr_startcopy, + sizeof(struct ucred) - offsetof(struct ucred, cr_startcopy)); return (newcr); } diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h index c4a197908f40..5e0b0ddeac92 100644 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -1,4 +1,4 @@ -/* $NetBSD: ucred.h,v 1.18 2003/08/07 16:34:21 agc Exp $ */ +/* $NetBSD: ucred.h,v 1.19 2004/05/02 12:36:55 pk Exp $ */ /* * Copyright (c) 1989, 1993 @@ -34,6 +34,8 @@ #ifndef _SYS_UCRED_H_ #define _SYS_UCRED_H_ +#include + /* * Credentials. */ @@ -48,7 +50,9 @@ struct uucred { }; struct ucred { + struct simplelock cr_lock; /* mutex for ref count */ u_int32_t cr_ref; /* reference count */ +#define cr_startcopy cr_uid /* for dup & copy */ uid_t cr_uid; /* effective user id */ gid_t cr_gid; /* effective group id */ u_int32_t cr_ngroups; /* number of groups */ @@ -59,7 +63,12 @@ struct ucred { #define FSCRED ((struct ucred *)-2) /* filesystem credential */ #ifdef _KERNEL -#define crhold(cr) (cr)->cr_ref++ +static void __inline__ crhold(struct ucred *cr) +{ + simple_lock(&cr->cr_lock); + cr->cr_ref++; + simple_unlock(&cr->cr_lock); +} /* flags that control when do_setres{u,g}id will do anything */ #define ID_E_EQ_E 0x001 /* effective equals effective */