From a9df3ca715f483a31c14b72bae3f548a4c9291d4 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 10 Jan 2006 13:26:41 +0000 Subject: [PATCH] windows-smb-username-refcount-20060110 the smb_username_t objects are reference counted but they were never released on their own accord. Instead the smb_uid_t objects when released were also cleaning up the smb_username_t. Since the smb_username_t is reused, now that smb_user_t objects are being cleaned up, this was a problem. --- src/WINNT/afsd/cm_ioctl.c | 5 ++++ src/WINNT/afsd/smb.c | 51 +++++++++++++++++++++++++++++---------- src/WINNT/afsd/smb.h | 2 ++ src/WINNT/afsd/smb3.c | 5 ++-- 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index d3ce8476c..cbb0fa96c 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -1914,6 +1914,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) int flags; char sessionKey[8]; char *smbname; + int release_userp = 0; saveDataPtr = ioctlp->inDatap; @@ -1985,6 +1986,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) if (flags & PIOCTL_LOGON) { userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname); + release_userp = 1; } /* store the token */ @@ -2022,6 +2024,9 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp) cm_ResetACLCache(userp); + if (release_userp) + cm_ReleaseUser(userp); + return 0; } diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 20a925454..e849ac388 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -1137,13 +1137,43 @@ smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern) lock_ReleaseWrite(&smb_rctLock); return uidp; } + +void smb_ReleaseUsername(smb_username_t *unp) +{ + smb_username_t *up; + smb_username_t **lupp; + cm_user_t *userp = NULL; + + lock_ObtainWrite(&smb_rctLock); + osi_assert(unp->refCount-- > 0); + if (unp->refCount == 0) { + lupp = &usernamesp; + for(up = *lupp; up; lupp = &up->nextp, up = *lupp) { + if (up == unp) + break; + } + osi_assert(up != NULL); + *lupp = up->nextp; + lock_FinalizeMutex(&unp->mx); + userp = unp->userp; + free(unp->name); + free(unp->machine); + free(unp); + } + lock_ReleaseWrite(&smb_rctLock); + + if (userp) { + cm_ReleaseUserVCRef(userp); + cm_ReleaseUser(userp); + } +} + void smb_ReleaseUID(smb_user_t *uidp) { smb_user_t *up; smb_user_t **lupp; - cm_user_t *userp; + smb_username_t *unp = NULL; - userp = NULL; lock_ObtainWrite(&smb_rctLock); osi_assert(uidp->refCount-- > 0); if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) { @@ -1155,20 +1185,15 @@ void smb_ReleaseUID(smb_user_t *uidp) osi_assert(up != NULL); *lupp = up->nextp; lock_FinalizeMutex(&uidp->mx); - if (uidp->unp) { - userp = uidp->unp->userp; /* avoid deadlock by releasing */ - uidp->unp->userp = NULL; /* after releasing the lock */ - } + unp = uidp->unp; smb_ReleaseVCNoLock(uidp->vcp); - uidp->vcp = NULL; + free(uidp); } lock_ReleaseWrite(&smb_rctLock); - if (userp) { - cm_ReleaseUserVCRef(userp); - cm_ReleaseUser(userp); - } -} + if (unp) + smb_ReleaseUsername(unp); +} /* retrieve a held reference to a user structure corresponding to an incoming * request. @@ -5893,7 +5918,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op, /* handle over quota or out of space */ if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) { *writtenp = written; - code = CM_ERROR_QUOTA; + code = (scp->flags & CM_SCACHEFLAG_OVERQUOTA) ? CM_ERROR_QUOTA : CM_ERROR_SPACE; break; } diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 02a2a7566..81fda6443 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -505,6 +505,8 @@ extern smb_username_t *smb_FindUserByName(char *usern, char *machine, int flags) extern smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern); +extern void smb_ReleaseUsername(smb_username_t *unp); + extern void smb_ReleaseUID(smb_user_t *uidp); extern cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 043673280..fefc6e57a 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -7146,9 +7146,8 @@ void smb3_Init() lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock"); } -cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine) +cm_user_t *smb_FindCMUserByName(char *usern, char *machine) { - /*int newUid;*/ smb_username_t *unp; unp = smb_FindUserByName(usern, machine, SMB_FLAG_CREATE); @@ -7160,6 +7159,8 @@ cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine) } else { osi_Log2(smb_logp,"smb_FindCMUserByName Not found name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine)); } + cm_HoldUser(unp->userp); + smb_ReleaseUsername(unp); return unp->userp; } -- 2.39.5