From 29a68de93b71b8180b1230fe64956fc611c97f3c Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 10 Jan 2006 13:28:01 +0000 Subject: [PATCH] STABLE14-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. (cherry picked from commit a9df3ca715f483a31c14b72bae3f548a4c9291d4) --- src/WINNT/afsd/cm_ioctl.c | 5 ++++ src/WINNT/afsd/smb.c | 51 +++++++++++++++++++++++++++++---------- src/WINNT/afsd/smb.h | 2 ++ src/WINNT/afsd/smb3.c | 7 +++--- 4 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index ffdd6d59c..a4bfa36a5 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -1882,6 +1882,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; @@ -1951,6 +1952,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 */ @@ -1988,6 +1990,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 a3b570824..1c326bbfe 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -1130,13 +1130,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)) { @@ -1148,20 +1178,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. @@ -5898,7 +5923,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 89d668894..e5c7ad347 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 2adfb8056..4d8af4dc1 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -7173,9 +7173,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); @@ -7188,7 +7187,9 @@ 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)); osi_LogEvent("AFS smb_FindCMUserByName : Found",NULL,"name[%s] machine[%s]",usern,machine); - } + } + cm_HoldUser(unp->userp); + smb_ReleaseUsername(unp); return unp->userp; } -- 2.39.5