windows-misc-20050125
authorJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 25 Jan 2005 23:24:43 +0000 (23:24 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 25 Jan 2005 23:24:43 +0000 (23:24 +0000)
The list of ACL entries was being corrupted because the function
which obtains a free ACL entry was doing so without the appropriate
lock being held.

Returning Not A Directory is not the right thing to do when we are
attempting to resolve a path if the error is found on one of the
intermediary path components.  Instead return No Such Path or
No Such File as appropriate.

src/WINNT/afsd/cm_aclent.c
src/WINNT/afsd/cm_vnodeops.c

index 6dc9dff..bbaf4ff 100644 (file)
@@ -28,8 +28,6 @@
  * An aclent structure is free if it has no back vnode pointer.
  */
 osi_rwlock_t cm_aclLock;               /* lock for system's aclents */
-cm_aclent_t *cm_aclLRUp;               /* LRUQ for dudes in vnodes' lists */
-cm_aclent_t *cm_aclLRUEndp;            /* ditto */
 
 /* 
  * Get an acl cache entry for a particular user and file, or return that it doesn't exist.
@@ -37,39 +35,39 @@ cm_aclent_t *cm_aclLRUEndp;         /* ditto */
  */
 long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, long *rightsp)
 {
-       cm_aclent_t *aclp;
-
-       lock_ObtainWrite(&cm_aclLock);
-       for (aclp = scp->randomACLp; aclp; aclp = aclp->nextp) {
-               if (aclp->userp == userp) {
-                       if (aclp->tgtLifetime && aclp->tgtLifetime <= (long) osi_Time()) {
-                               /* ticket expired */
-                               aclp->tgtLifetime = 0;
-                               *rightsp = 0;
-                               break; /* get a new acl from server */
-                       }
-                       else {
-                               *rightsp = aclp->randomAccess;
-                               if (cm_aclLRUEndp == aclp)
-                                       cm_aclLRUEndp = (cm_aclent_t *) osi_QPrev(&aclp->q);
-
-                               /* move to the head of the LRU queue */
-                               osi_QRemove((osi_queue_t **) &cm_aclLRUp, &aclp->q);
-                                osi_QAddH((osi_queue_t **) &cm_aclLRUp,
-                                       (osi_queue_t **) &cm_aclLRUEndp,
-                                        &aclp->q);
-                       }
-                       lock_ReleaseWrite(&cm_aclLock);
-                       return 0;
-               }
-       }
-
-       /* 
-        * If we make it here, this entry isn't present, so we're going to fail. 
-        */
-       lock_ReleaseWrite(&cm_aclLock);
-       return -1;
-}
+    cm_aclent_t *aclp;
+    long retval = -1;
+
+    lock_ObtainWrite(&cm_aclLock);
+    for (aclp = scp->randomACLp; aclp; aclp = aclp->nextp) {
+        if (aclp->userp == userp) {
+            if (aclp->tgtLifetime && aclp->tgtLifetime <= (long) osi_Time()) {
+                /* ticket expired */
+                aclp->tgtLifetime = 0;
+                *rightsp = 0;   /* get a new acl from server */
+
+                /* Shouldn't we remove this entry from the scp?
+                 * 2005-01-25 - jaltman@secure-endpoints.com
+                 */
+            } else {
+                *rightsp = aclp->randomAccess;
+                if (cm_data.aclLRUEndp == aclp)
+                    cm_data.aclLRUEndp = (cm_aclent_t *) osi_QPrev(&aclp->q);
+
+                /* move to the head of the LRU queue */
+                osi_QRemove((osi_queue_t **) &cm_data.aclLRUp, &aclp->q);
+                osi_QAddH((osi_queue_t **) &cm_data.aclLRUp,
+                           (osi_queue_t **) &cm_data.aclLRUEndp,
+                           &aclp->q);
+                retval = 0;     /* success */
+            }               
+            break;
+        }
+    }
+
+    lock_ReleaseWrite(&cm_aclLock);
+    return retval;
+}       
 
 
 /* 
@@ -78,38 +76,40 @@ long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, long *rightsp)
  */
 static cm_aclent_t *GetFreeACLEnt(void)
 {
-       cm_aclent_t *aclp;
-        cm_aclent_t *taclp;
-        cm_aclent_t **laclpp;
-
-       if (cm_aclLRUp == NULL)
-               osi_panic("empty aclent LRU", __FILE__, __LINE__);
-
-       aclp = cm_aclLRUEndp;
-       if (aclp == cm_aclLRUEndp)
-               cm_aclLRUEndp = (cm_aclent_t *) osi_QPrev(&aclp->q);
-       osi_QRemove((osi_queue_t **) &cm_aclLRUp, &aclp->q);
-       if (aclp->backp) {
-               /* 
-                * Remove the entry from the vnode's list 
-                */
-               laclpp = &aclp->backp->randomACLp;
-               for (taclp = *laclpp; taclp; laclpp = &taclp->nextp, taclp = *laclpp) {
-                       if (taclp == aclp) 
-                               break;
-               }
-               if (!taclp) 
-                       osi_panic("GetFreeACLEnt race", __FILE__, __LINE__);
-               *laclpp = aclp->nextp;                  /* remove from vnode list */
-               aclp->backp = NULL;
-       }
-       
+    cm_aclent_t *aclp;
+    cm_aclent_t *taclp;
+    cm_aclent_t **laclpp;
+
+    if (cm_data.aclLRUp == NULL)
+        osi_panic("empty aclent LRU", __FILE__, __LINE__);
+
+    lock_ObtainWrite(&cm_aclLock);
+    aclp = cm_data.aclLRUEndp;
+    if (aclp == cm_data.aclLRUEndp)
+        cm_data.aclLRUEndp = (cm_aclent_t *) osi_QPrev(&aclp->q);
+    osi_QRemove((osi_queue_t **) &cm_data.aclLRUp, &aclp->q);
+    if (aclp->backp) {
+        /* 
+         * Remove the entry from the vnode's list 
+         */
+        laclpp = &aclp->backp->randomACLp;
+        for (taclp = *laclpp; taclp; laclpp = &taclp->nextp, taclp = *laclpp) {
+            if (taclp == aclp) 
+                break;
+        }
+        if (!taclp) 
+            osi_panic("GetFreeACLEnt race", __FILE__, __LINE__);
+        *laclpp = aclp->nextp;                 /* remove from vnode list */
+        aclp->backp = NULL;
+    }
+
     /* release the old user */
     if (aclp->userp) {
-               cm_ReleaseUser(aclp->userp);
+        cm_ReleaseUser(aclp->userp);
         aclp->userp = NULL;
-       }
-       return aclp;
+    }
+    lock_ReleaseWrite(&cm_aclLock);
+    return aclp;
 }
 
 
@@ -121,69 +121,139 @@ static cm_aclent_t *GetFreeACLEnt(void)
  */
 long cm_AddACLCache(cm_scache_t *scp, cm_user_t *userp, long rights)
 {
-       register struct cm_aclent *aclp;
-
-       lock_ObtainWrite(&cm_aclLock);
-       for (aclp = scp->randomACLp; aclp; aclp = aclp->nextp) {
-               if (aclp->userp == userp) {
-                       aclp->randomAccess = rights;
-                       if (aclp->tgtLifetime == 0) 
-                               aclp->tgtLifetime = cm_TGTLifeTime(pag);
-                       lock_ReleaseWrite(&cm_aclLock);
-                       return 0;
-               }
-       }
-
-       /* 
-        * Didn't find the dude we're looking for, so take someone from the LRUQ 
-        * and  reuse. But first try the free list and see if there's already 
-        * someone there.
-        */
-       aclp = GetFreeACLEnt();          /* can't fail, panics instead */
-       osi_QAddH((osi_queue_t **) &cm_aclLRUp, (osi_queue_t **) &cm_aclLRUEndp, &aclp->q);
-       aclp->backp = scp;
-       aclp->nextp = scp->randomACLp;
-       scp->randomACLp = aclp;
+    register struct cm_aclent *aclp;
+
+    lock_ObtainWrite(&cm_aclLock);
+    for (aclp = scp->randomACLp; aclp; aclp = aclp->nextp) {
+        if (aclp->userp == userp) {
+            aclp->randomAccess = rights;
+            if (aclp->tgtLifetime == 0) 
+                aclp->tgtLifetime = cm_TGTLifeTime(pag);
+            lock_ReleaseWrite(&cm_aclLock);
+            return 0;
+        }
+    }
+
+    /* 
+     * Didn't find the dude we're looking for, so take someone from the LRUQ 
+     * and  reuse. But first try the free list and see if there's already 
+     * someone there.
+     */
+    aclp = GetFreeACLEnt();             /* can't fail, panics instead */
+    osi_QAddH((osi_queue_t **) &cm_data.aclLRUp, (osi_queue_t **) &cm_data.aclLRUEndp, &aclp->q);
+    aclp->backp = scp;
+    aclp->nextp = scp->randomACLp;
+    scp->randomACLp = aclp;
     cm_HoldUser(userp);
-       aclp->userp = userp;
-       aclp->randomAccess = rights;
-       aclp->tgtLifetime = cm_TGTLifeTime(userp);
-       lock_ReleaseWrite(&cm_aclLock);
+    aclp->userp = userp;
+    aclp->randomAccess = rights;
+    aclp->tgtLifetime = cm_TGTLifeTime(userp);
+    lock_ReleaseWrite(&cm_aclLock);
 
-       return 0;
+    return 0;
+}
+
+long cm_ShutdownACLCache(void)
+{
+    return 0;
+}
+
+long cm_ValidateACLCache(void)
+{
+    long size = cm_data.stats * 2;
+    long count;
+    cm_aclent_t * aclp;
+
+    for ( aclp = cm_data.aclLRUp, count = 0; aclp;
+          aclp = (cm_aclent_t *) osi_QNext(&aclp->q), count++ ) {
+        if (aclp->magic != CM_ACLENT_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: acpl->magic != CM_ACLENT_MAGIC");
+            fprintf(stderr, "cm_ValidateACLCache failure: acpl->magic != CM_ACLENT_MAGIC\n");
+            return -1;
+        }
+        if (aclp->nextp && aclp->nextp->magic != CM_ACLENT_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: acpl->nextp->magic != CM_ACLENT_MAGIC");
+            fprintf(stderr,"cm_ValidateACLCache failure: acpl->nextp->magic != CM_ACLENT_MAGIC\n");
+            return -2;
+        }
+        if (aclp->backp && aclp->backp->magic != CM_SCACHE_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: acpl->backp->magic != CM_SCACHE_MAGIC");
+            fprintf(stderr,"cm_ValidateACLCache failure: acpl->backp->magic != CM_SCACHE_MAGIC\n");
+            return -3;
+        }
+        if (count != 0 && aclp == cm_data.aclLRUp || count > size) {
+            afsi_log("cm_ValidateACLCache failure: loop in cm_data.aclLRUp list");
+            fprintf(stderr, "cm_ValidateACLCache failure: loop in cm_data.aclLRUp list\n");
+            return -4;
+        }
+    }
+
+    for ( aclp = cm_data.aclLRUEndp, count = 0; aclp;
+          aclp = (cm_aclent_t *) osi_QPrev(&aclp->q), count++ ) {
+        if (aclp->magic != CM_ACLENT_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: aclp->magic != CM_ACLENT_MAGIC");
+            fprintf(stderr, "cm_ValidateACLCache failure: aclp->magic != CM_ACLENT_MAGIC\n");
+            return -5;
+        }
+        if (aclp->nextp && aclp->nextp->magic != CM_ACLENT_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: aclp->nextp->magic != CM_ACLENT_MAGIC");
+            fprintf(stderr, "cm_ValidateACLCache failure: aclp->nextp->magic != CM_ACLENT_MAGIC\n");
+            return -6;
+        }
+        if (aclp->backp && aclp->backp->magic != CM_SCACHE_MAGIC) {
+            afsi_log("cm_ValidateACLCache failure: aclp->backp->magic != CM_SCACHE_MAGIC");
+            fprintf(stderr, "cm_ValidateACLCache failure: aclp->backp->magic != CM_SCACHE_MAGIC\n");
+            return -7;
+        }
+
+        if (count != 0 && aclp == cm_data.aclLRUEndp || count > size) {
+            afsi_log("cm_ValidateACLCache failure: loop in cm_data.aclLRUEndp list");
+            fprintf(stderr, "cm_ValidateACLCache failure: loop in cm_data.aclLRUEndp list\n");
+            return -8;
+        }
+    }
+
+    return 0;
 }
 
 /* 
  * Initialize the cache to have an entries.  Called during system startup.
  */
-long cm_InitACLCache(long size)
+long cm_InitACLCache(int newFile, long size)
 {
-       cm_aclent_t *aclp;
-       long i;
-       static osi_once_t once;
-
-       
-       if (osi_Once(&once)) {
-               lock_InitializeRWLock(&cm_aclLock, "cm_aclLock");
-               osi_EndOnce(&once);
-       }
-
-       lock_ObtainWrite(&cm_aclLock);
-       cm_aclLRUp = cm_aclLRUEndp = NULL;
-       aclp = (cm_aclent_t *) malloc(size * sizeof(cm_aclent_t));
-       memset(aclp, 0, size * sizeof(cm_aclent_t));
-
-       /* 
-        * Put all of these guys on the LRU queue 
-        */
-       for (i = 0; i < size; i++) {
-               osi_QAddH((osi_queue_t **) &cm_aclLRUp, (osi_queue_t **) &cm_aclLRUEndp,
-                       &aclp->q);
-               aclp++;
-       }
-
-       lock_ReleaseWrite(&cm_aclLock);
-       return 0;
+    cm_aclent_t *aclp;
+    long i;
+    static osi_once_t once;
+
+    if (osi_Once(&once)) {
+        lock_InitializeRWLock(&cm_aclLock, "cm_aclLock");
+        osi_EndOnce(&once);
+    }
+
+    lock_ObtainWrite(&cm_aclLock);
+    if ( newFile ) {
+        cm_data.aclLRUp = cm_data.aclLRUEndp = NULL;
+        aclp = (cm_aclent_t *) cm_data.aclBaseAddress;
+        memset(aclp, 0, size * sizeof(cm_aclent_t));
+
+        /* 
+         * Put all of these guys on the LRU queue 
+         */
+        for (i = 0; i < size; i++) {
+            aclp->magic = CM_ACLENT_MAGIC;
+            osi_QAddH((osi_queue_t **) &cm_data.aclLRUp, (osi_queue_t **) &cm_data.aclLRUEndp, &aclp->q);
+            aclp++;
+        }
+    } else {
+        aclp = (cm_aclent_t *) cm_data.aclBaseAddress;
+        for (i = 0; i < size; i++) {
+            aclp->userp = NULL;
+            aclp->tgtLifetime = 0;
+            aclp++;
+        }
+    }
+    lock_ReleaseWrite(&cm_aclLock);
+    return 0;
 }
 
 
@@ -194,22 +264,22 @@ long cm_InitACLCache(long size)
  */
 void cm_FreeAllACLEnts(cm_scache_t *scp)
 {
-       cm_aclent_t *aclp;
-       cm_aclent_t *taclp;
-
-       lock_ObtainWrite(&cm_aclLock);
-       for (aclp = scp->randomACLp; aclp; aclp = taclp) {
-               taclp = aclp->nextp;
-               if (aclp->userp) {
-                       cm_ReleaseUser(aclp->userp);
-                       aclp->userp = NULL;
-               }
-               aclp->backp = (struct cm_scache *) 0;
-       }
-
-       scp->randomACLp = (struct cm_aclent *) 0;
-       scp->anyAccess = 0;             /* reset this, too */
-       lock_ReleaseWrite(&cm_aclLock);
+    cm_aclent_t *aclp;
+    cm_aclent_t *taclp;
+
+    lock_ObtainWrite(&cm_aclLock);
+    for (aclp = scp->randomACLp; aclp; aclp = taclp) {
+        taclp = aclp->nextp;
+        if (aclp->userp) {
+            cm_ReleaseUser(aclp->userp);
+            aclp->userp = NULL;
+        }
+        aclp->backp = (struct cm_scache *) 0;
+    }
+
+    scp->randomACLp = (struct cm_aclent *) 0;
+    scp->anyAccess = 0;                /* reset this, too */
+    lock_ReleaseWrite(&cm_aclLock);
 }
 
 
@@ -220,19 +290,19 @@ void cm_FreeAllACLEnts(cm_scache_t *scp)
  */
 void cm_InvalidateACLUser(cm_scache_t *scp, cm_user_t *userp)
 {
-       cm_aclent_t *aclp;
-        cm_aclent_t **laclpp;
-
-       lock_ObtainWrite(&cm_aclLock);
-       laclpp = &scp->randomACLp;
-       for (aclp = *laclpp; aclp; laclpp = &aclp->nextp, aclp = *laclpp) {
-               if (userp == aclp->userp) {     /* One for a given user/scache */
-                       *laclpp = aclp->nextp;
+    cm_aclent_t *aclp;
+    cm_aclent_t **laclpp;
+
+    lock_ObtainWrite(&cm_aclLock);
+    laclpp = &scp->randomACLp;
+    for (aclp = *laclpp; aclp; laclpp = &aclp->nextp, aclp = *laclpp) {
+        if (userp == aclp->userp) {    /* One for a given user/scache */
+            *laclpp = aclp->nextp;
             cm_ReleaseUser(aclp->userp);
             aclp->userp = NULL;
-                       aclp->backp = (struct cm_scache *) 0;
-                       break;
-               }
-       }
-       lock_ReleaseWrite(&cm_aclLock);
+            aclp->backp = (struct cm_scache *) 0;
+            break;
+        }
+    }
+    lock_ReleaseWrite(&cm_aclLock);
 }
index b936b44..27ba3f8 100644 (file)
@@ -995,8 +995,19 @@ long cm_LookupInternal(cm_scache_t *dscp, char *namep, long flags, cm_user_t *us
      * that we stopped early, probably because we found the entry we're
      * looking for.  Any other non-zero code is an error.
      */
-    if (code && code != CM_ERROR_STOPNOW) 
+    if (code && code != CM_ERROR_STOPNOW) { 
+        /* if the cm_scache_t we are searching in is not a directory 
+         * we must return path not found because the error 
+         * is to describe the final component not an intermediary
+         */
+        if (code == CM_ERROR_NOTDIR) {
+            if (flags & CM_FLAG_CHECKPATH)
+                return CM_ERROR_NOSUCHPATH;
+            else
+                return CM_ERROR_NOSUCHFILE;
+        }
         return code;
+    }
 
     getroot = (dscp==cm_rootSCachep) ;
     if (!rock.found) {