windows-smb-writedata-crash-20080307
authorJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 7 Mar 2008 15:35:38 +0000 (15:35 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 7 Mar 2008 15:35:38 +0000 (15:35 +0000)
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.

src/WINNT/afsd/smb.c

index a21bd29..66c8389 100644 (file)
@@ -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;