From: Jeffrey Altman Date: Fri, 7 Mar 2008 15:35:38 +0000 (+0000) Subject: windows-smb-writedata-crash-20080307 X-Git-Tag: BP-openafs-windows-kdfs-ifs~47 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=5589875561e0062b2f06fc4ce0a8fad37a0d8eb5;p=packages%2Fo%2Fopenafs.git windows-smb-writedata-crash-20080307 LICENSE MIT FIXES 88731 If an application opens a file for read only and then attempts to write to it, we would attempt to release an scp mutex without having obtained either the scp or the mutex within smb_WriteData There was no check in smb_ReadData to ensure that the file was opened for reading. Add one. --- diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index a21bd29cb..66c8389b9 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -6050,12 +6050,26 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char int sequential = (fidp->flags & SMB_FID_SEQUENTIAL); cm_req_t req; + osi_Log3(smb_logp, "smb_ReadData fid %d, off 0x%x, size 0x%x", + fidp->fid, offsetp->LowPart, count); + + *readp = 0; + + lock_ObtainMutex(&fidp->mx); + /* make sure we have a readable FD */ + if (!(fidp->flags & SMB_FID_OPENREAD_LISTDIR)) { + osi_Log2(smb_logp, "smb_ReadData fid %d not OPENREAD_LISTDIR flags 0x%x", + fidp->fid, fidp->flags); + lock_ReleaseMutex(&fidp->mx); + code = CM_ERROR_BADFDOP; + goto done2; + } + cm_InitReq(&req); bufferp = NULL; offset = *offsetp; - lock_ObtainMutex(&fidp->mx); scp = fidp->scp; cm_HoldSCache(scp); lock_ObtainWrite(&scp->rw); @@ -6179,6 +6193,9 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char cm_ReleaseSCache(scp); + done2: + osi_Log3(smb_logp, "smb_ReadData fid %d returns 0x%x read %d bytes", + fidp->fid, code, *readp); return code; } @@ -6191,7 +6208,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char osi_hyper_t offset = *offsetp; long code = 0; long written = 0; - cm_scache_t *scp; + cm_scache_t *scp = NULL; osi_hyper_t fileLength; /* file's length at start of write */ osi_hyper_t minLength; /* don't read past this */ afs_uint32 nbytes; /* # of bytes to transfer this iteration */ @@ -6209,8 +6226,6 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char *writtenp = 0; - cm_InitReq(&req); - lock_ObtainMutex(&fidp->mx); /* make sure we have a writable FD */ if (!(fidp->flags & SMB_FID_OPENWRITE)) { @@ -6218,9 +6233,11 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char fidp->fid, fidp->flags); lock_ReleaseMutex(&fidp->mx); code = CM_ERROR_BADFDOP; - goto done; + goto done2; } + cm_InitReq(&req); + scp = fidp->scp; cm_HoldSCache(scp); lock_ReleaseMutex(&fidp->mx); @@ -6441,6 +6458,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char cm_ReleaseSCache(scp); + done2: osi_Log3(smb_logp, "smb_WriteData fid %d returns 0x%x written %d bytes", fidp->fid, code, *writtenp); return code;