From aab4b2b32f933daf48cc138c0eb5d8cf5a2023b5 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 5 Aug 2008 16:45:35 +0000 Subject: [PATCH] windows-getaccessrights-20080805 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 | 4 ++-- src/WINNT/afsd/cm_dcache.c | 2 -- src/WINNT/afsd/cm_scache.c | 11 ++++++++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/WINNT/afsd/cm_access.c b/src/WINNT/afsd/cm_access.c index da1593c19..90948cfd8 100644 --- a/src/WINNT/afsd/cm_access.c +++ b/src/WINNT/afsd/cm_access.c @@ -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); diff --git a/src/WINNT/afsd/cm_dcache.c b/src/WINNT/afsd/cm_dcache.c index d7852b6e2..f1f328873 100644 --- a/src/WINNT/afsd/cm_dcache.c +++ b/src/WINNT/afsd/cm_dcache.c @@ -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 diff --git a/src/WINNT/afsd/cm_scache.c b/src/WINNT/afsd/cm_scache.c index 1ac0e680d..1d44ec719 100644 --- a/src/WINNT/afsd/cm_scache.c +++ b/src/WINNT/afsd/cm_scache.c @@ -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 -- 2.39.5