windows-getaccessrights-20080805
authorJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 5 Aug 2008 16:45:35 +0000 (16:45 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 5 Aug 2008 16:45:35 +0000 (16:45 +0000)
LICENSE MIT

Do not permit GetAccessRights() to be called multiple times within
cm_SyncOp for the same rights check.  If the GetAccessRights() succeeded
and in the next loop the rights check fails, the user simply doesn't
have the rights.

Move a call to cm_SyncOpDone(FETCHSTATUS) from GetBuffer() to MergeStatus().
Anytime an RPC completes successfully we get updated status info for
the object.  Might as well allow threads waiting for status info to us
it.

src/WINNT/afsd/cm_access.c
src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_scache.c

index da1593c..90948cf 100644 (file)
@@ -157,7 +157,7 @@ long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp,
 
     /* pretty easy: just force a pass through the fetch status code */
         
-    osi_Log2(afsd_logp, "GetAccess scp 0x%p user 0x%p", scp, userp);
+    osi_Log2(afsd_logp, "GetAccessRights scp 0x%p user 0x%p", scp, userp);
 
     /* first, start by finding out whether we have a directory or something
      * else, so we can find what object's ACL we need.
@@ -177,7 +177,7 @@ long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp,
            goto _done;
         }       
                 
-        osi_Log2(afsd_logp, "GetAccess parent scp %x user %x", aclScp, userp);
+        osi_Log2(afsd_logp, "GetAccessRights parent scp %x user %x", aclScp, userp);
        lock_ObtainWrite(&aclScp->rw);
        code = cm_SyncOp(aclScp, NULL, userp, reqp, 0,
                         CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_FORCECB);
index d7852b6..f1f3288 100644 (file)
@@ -1694,8 +1694,6 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
 
     lock_ObtainWrite(&scp->rw);
     
-    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_FETCHSTATUS);
-
     /* we know that no one else has changed the buffer, since we still have
      * the fetching flag on the buffers, and we have the scp locked again.
      * Copy in the version # into the buffer if we got code 0 back from the
index 1ac0e68..1d44ec7 100644 (file)
@@ -1045,6 +1045,7 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *req
     afs_uint32 sleep_buf_cmflags = 0;
     afs_uint32 sleep_scp_bufs = 0;
     int wakeupCycle;
+    int getAccessRights = 1;
 
     /* lookup this first */
     bufLocked = flags & CM_SCACHESYNC_BUFLOCKED;
@@ -1247,7 +1248,7 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *req
             if ((rights & PRSFS_WRITE) && (scp->flags & CM_SCACHEFLAG_RO))
                 return CM_ERROR_READONLY;
 
-            if (cm_HaveAccessRights(scp, userp, rights, &outRights)) {
+            if (cm_HaveAccessRights(scp, userp, rights, &outRights) || !getAccessRights) {
                 if (~outRights & rights) 
                    return CM_ERROR_NOACCESS;
             }
@@ -1262,6 +1263,7 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *req
                 }
                 if (code) 
                     return code;
+                getAccessRights = 0;    /* do not repeat */
                 continue;
             }
         }
@@ -1725,6 +1727,13 @@ void cm_MergeStatus(cm_scache_t *dscp,
         scp->bufDataVersionLow = dataVersion;
     
     scp->dataVersion = dataVersion;
+
+    /* 
+     * If someone is waiting for status information, we can wake them up
+     * now even though the entity that issued the FetchStatus may not 
+     * have completed yet.
+     */
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_FETCHSTATUS);
 }
 
 /* note that our stat cache info is incorrect, so force us eventually