Fix afs_AccessOK for dropbox case
authorAndrew Deason <adeason@sinenomine.net>
Fri, 22 Jan 2010 01:42:33 +0000 (20:42 -0500)
committerDerrick Brashear <shadow|account-1000005@unknown>
Fri, 22 Jan 2010 18:49:48 +0000 (10:49 -0800)
afs_AccessOK did not check for if we have 'i' rights on a directory, nor
if we were the owner of a file, if we were only checking PRSFS_READ or
PRSFS_WRITE. Thus, it does not correctly address the 'dropbox'
permissions case (if you are the owner of a file and have insert
permissions, you get implicit 'r' and 'w').

Fix this to check for 'i' and ownership when we need to, so the dropbox
special-case check works as intended.

FIXES 126216

Change-Id: Ib629bc30b73bc3965e777747067259451f0adff6
Reviewed-on: http://gerrit.openafs.org/1143
Tested-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/afs/VNOPS/afs_vnop_access.c

index 0a31ac8..f72b6e6 100644 (file)
@@ -148,15 +148,36 @@ afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq,
            /* Avoid this GetVCache call */
            tvc = afs_GetVCache(&dirFid, areq, NULL, NULL);
            if (tvc) {
-               dirBits = afs_GetAccessBits(tvc, arights, areq);
+               if ((arights & (PRSFS_READ | PRSFS_WRITE))) {
+                   /* we may need to grant implicit 'rw' rights if we have
+                    * 'i' on the parent dir and we are the owner, so check
+                    * for 'i' rights in addition, here */
+                   dirBits = afs_GetAccessBits(tvc, arights | PRSFS_INSERT, areq);
+               } else {
+                   dirBits = afs_GetAccessBits(tvc, arights, areq);
+               }
                afs_PutVCache(tvc);
            }
        } else
            dirBits = 0xffffffff;       /* assume OK; this is a race condition */
-       if (arights & PRSFS_ADMINISTER)
+       if (arights & PRSFS_ADMINISTER) {
            fileBits = afs_GetAccessBits(avc, arights, areq);
-       else
+
+       } else if ((dirBits & PRSFS_INSERT) &&
+                 ((arights & (PRSFS_READ | PRSFS_WRITE)) & dirBits) !=
+                  (arights & (PRSFS_READ | PRSFS_WRITE))) {
+
+           /* if we have 'i' rights in the directory, and we are requesting
+            * read or write access, AND the directory ACL (dirBits) does not
+            * already give us the requested read or write access, we need to
+            * find out if we are the owner for the file ('A' bit), for the
+            * "throw in R and W if we have I and A" check below */
+
+           fileBits = afs_GetAccessBits(avc, arights | PRSFS_ADMINISTER, areq);
+
+       } else {
            fileBits = 0;       /* don't make call if results don't matter */
+       }
 
        /* compute basic rights in fileBits, taking A from file bits */
        fileBits =
@@ -164,8 +185,8 @@ afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq,
 
        /* for files, throw in R and W if have I and A (owner).  This makes
         * insert-only dirs work properly */
-       if (vType(avc) != VDIR
-           && (fileBits & (PRSFS_ADMINISTER | PRSFS_INSERT)) ==
+       /* note that we know vType(avc) != VDIR from the top-level 'else' */
+       if ((fileBits & (PRSFS_ADMINISTER | PRSFS_INSERT)) ==
            (PRSFS_ADMINISTER | PRSFS_INSERT))
            fileBits |= (PRSFS_READ | PRSFS_WRITE);