OPENAFS-SA-2016-002 AFSStoreStatus information leak
[openafs.git] / src / afs / afs_disconnected.c
index db244bf..a83d076 100644 (file)
@@ -6,8 +6,8 @@
 
 #include <afsconfig.h>
 #include "afs/param.h"
+
+
 #include "afs/sysincludes.h"
 #include "afsincludes.h"
 #include "afs/afs_stats.h"     /* statistics */
@@ -71,12 +71,14 @@ afs_FindDCacheByFid(struct VenusFid *afid)
     ObtainWriteLock(&afs_xdcache, 758);
     for (index = afs_dvhashTbl[i]; index != NULLIDX;) {
        if (afs_indexUnique[index] == afid->Fid.Unique) {
-           tdc = afs_GetDSlot(index, NULL);
-           ReleaseReadLock(&tdc->tlock);
-           if (!FidCmp(&tdc->f.fid, afid)) {
-               break;          /* leaving refCount high for caller */
+           tdc = afs_GetValidDSlot(index);
+           if (tdc) {
+               ReleaseReadLock(&tdc->tlock);
+               if (!FidCmp(&tdc->f.fid, afid)) {
+                   break;              /* leaving refCount high for caller */
+               }
+               afs_PutDCache(tdc);
            }
-           afs_PutDCache(tdc);
        }
        index = afs_dvnextTbl[index];
     }
@@ -185,7 +187,6 @@ afs_GetParentDirFid(struct vcache *avc, struct VenusFid *afid)
        break;
     default:
        return -1;
-       break;
     }
 
     return 0;
@@ -263,7 +264,7 @@ afs_GetVnodeName(struct vcache *avc, struct VenusFid *afid, char *aname,
        parent_vc = afs_FindVCache(&parent_fid, 0, 1);
        ReleaseSharedLock(&afs_xvcache);
        if (!parent_vc) {
-           return ENOENT;
+           return ENETDOWN;
        }
 
        shadow_fid.Cell = parent_vc->f.fid.Cell;
@@ -292,7 +293,7 @@ afs_GetVnodeName(struct vcache *avc, struct VenusFid *afid, char *aname,
            code = ENOENT;
     } else {
        /* printf("Directory dcache not found!\n"); */
-        code = ENOENT;
+        code = ENETDOWN;
     }
 
     return code;
@@ -497,7 +498,7 @@ afs_DbgListDirEntries(struct VenusFid *afid)
  */
 
 int
-afs_GetParentVCache(struct vcache *avc, int deleted, struct VenusFid *afid, 
+afs_GetParentVCache(struct vcache *avc, int deleted, struct VenusFid *afid,
                    char *aname, struct vcache **adp)
 {
     int code;
@@ -506,7 +507,7 @@ afs_GetParentVCache(struct vcache *avc, int deleted, struct VenusFid *afid,
 
     if (afs_GetParentDirFid(avc, afid)) {
        /* printf("afs_GetParentVCache: Couldn't find parent dir's FID.\n"); */
-       return ENOENT;
+       return ENETDOWN;
     }
 
     code = afs_GetVnodeName(avc, afid, aname, deleted);
@@ -520,7 +521,7 @@ afs_GetParentVCache(struct vcache *avc, int deleted, struct VenusFid *afid,
     ReleaseSharedLock(&afs_xvcache);
     if (!*adp) {
        /* printf("afs_GetParentVCache: Couldn't find parent dir's vcache\n"); */
-       code = ENOENT;
+       code = ENETDOWN;
        goto end;
     }
 
@@ -531,8 +532,10 @@ afs_GetParentVCache(struct vcache *avc, int deleted, struct VenusFid *afid,
     }
 
 end:
-    if (code && *adp)
+    if (code && *adp) {
        afs_PutVCache(*adp);
+       *adp = NULL;
+    }
     return code;
 }
 
@@ -551,6 +554,7 @@ afs_ProcessOpRename(struct vcache *avc, struct vrequest *areq)
     struct AFSFetchStatus OutOldDirStatus, OutNewDirStatus;
     struct AFSVolSync tsync;
     struct afs_conn *tc;
+    struct rx_connection *rxconn;
     afs_uint32 code = 0;
     XSTATS_DECLS;
 
@@ -561,7 +565,7 @@ afs_ProcessOpRename(struct vcache *avc, struct vrequest *areq)
     old_pdir_fid.Fid.Unique = avc->f.oldParent.unique;
 
     /* Get old name. */
-    old_name = (char *) afs_osi_Alloc(AFSNAMEMAX);
+    old_name = afs_osi_Alloc(AFSNAMEMAX);
     if (!old_name) {
        /* printf("afs_ProcessOpRename: Couldn't alloc space for old name.\n"); */
        return ENOMEM;
@@ -573,7 +577,7 @@ afs_ProcessOpRename(struct vcache *avc, struct vrequest *areq)
     }
 
     /* Alloc data first. */
-    new_name = (char *) afs_osi_Alloc(AFSNAMEMAX);
+    new_name = afs_osi_Alloc(AFSNAMEMAX);
     if (!new_name) {
        /* printf("afs_ProcessOpRename: Couldn't alloc space for new name.\n"); */
        code = ENOMEM;
@@ -589,7 +593,7 @@ afs_ProcessOpRename(struct vcache *avc, struct vrequest *areq)
        /* Get parent dir's FID.*/
        if (afs_GetParentDirFid(avc, &new_pdir_fid)) {
            /* printf("afs_ProcessOpRename: Couldn't find new parent dir FID.\n"); */
-           code = ENOENT;
+           code = ENETDOWN;
            goto done;
         }
     }
@@ -603,11 +607,11 @@ afs_ProcessOpRename(struct vcache *avc, struct vrequest *areq)
 
     /* Send to data to server. */
     do {
-       tc = afs_Conn(&old_pdir_fid, areq, SHARED_LOCK);
+       tc = afs_Conn(&old_pdir_fid, areq, SHARED_LOCK, &rxconn);
        if (tc) {
            XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RENAME);
            RX_AFS_GUNLOCK();
-           code = RXAFS_Rename(tc->id,
+           code = RXAFS_Rename(rxconn,
                (struct AFSFid *)&old_pdir_fid.Fid,
                old_name,
                (struct AFSFid *)&new_pdir_fid.Fid,
@@ -621,6 +625,7 @@ afs_ProcessOpRename(struct vcache *avc, struct vrequest *areq)
            code = -1;
 
     } while (afs_Analyze(tc,
+                rxconn,
                code,
                &new_pdir_fid,
                areq,
@@ -657,6 +662,7 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
     struct vcache *tdp = NULL, *tvc = NULL;
     struct dcache *tdc = NULL;
     struct afs_conn *tc;
+    struct rx_connection *rxconn;
     afs_int32 hash, new_hash, index;
     afs_size_t tlen;
     int code, op = 0;
@@ -665,9 +671,10 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
     tname = afs_osi_Alloc(AFSNAMEMAX);
     if (!tname)
        return ENOMEM;
+    memset(&InStatus, 0, sizeof(InStatus));
 
     code = afs_GetParentVCache(avc, 0, &pdir_fid, tname, &tdp);
-    if (code) 
+    if (code)
        goto end;
 
     /* This data may also be in linkData, but then we have to deal with
@@ -681,7 +688,7 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
 
        tdc = afs_GetDCache(avc, 0, areq, &offset, &tlen, 0);
        if (!tdc) {
-           code = ENOENT;
+           code = ENETDOWN;
            goto end;
        }
 
@@ -705,7 +712,7 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
        ReleaseReadLock(&tdc->lock);
        afs_PutDCache(tdc);
     }
-       
+
     /* Set status. */
     InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
     InStatus.ClientModTime = avc->f.m.Date;
@@ -715,7 +722,7 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
     InStatus.UnixModeBits = avc->f.m.Mode & 0xffff;
 
     do {
-       tc = afs_Conn(&tdp->f.fid, areq, SHARED_LOCK);
+       tc = afs_Conn(&tdp->f.fid, areq, SHARED_LOCK, &rxconn);
        if (tc) {
            switch (vType(avc)) {
            case VREG:
@@ -723,7 +730,7 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
                op = AFS_STATS_FS_RPCIDX_CREATEFILE;
                XSTATS_START_TIME(op);
                 RX_AFS_GUNLOCK();
-                code = RXAFS_CreateFile(tc->id,
+                code = RXAFS_CreateFile(rxconn,
                                        (struct AFSFid *)&tdp->f.fid.Fid,
                                        tname, &InStatus,
                                        (struct AFSFid *) &newFid.Fid,
@@ -737,7 +744,7 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
                op = AFS_STATS_FS_RPCIDX_MAKEDIR;
                XSTATS_START_TIME(op);
                 RX_AFS_GUNLOCK();
-               code = RXAFS_MakeDir(tc->id, (struct AFSFid *) &tdp->f.fid.Fid,
+               code = RXAFS_MakeDir(rxconn, (struct AFSFid *) &tdp->f.fid.Fid,
                                     tname, &InStatus,
                                     (struct AFSFid *) &newFid.Fid,
                                     &OutFidStatus, &OutDirStatus,
@@ -750,7 +757,7 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
                op = AFS_STATS_FS_RPCIDX_SYMLINK;
                XSTATS_START_TIME(op);
                RX_AFS_GUNLOCK();
-               code = RXAFS_Symlink(tc->id,
+               code = RXAFS_Symlink(rxconn,
                                (struct AFSFid *) &tdp->f.fid.Fid,
                                tname, ttargetName, &InStatus,
                                (struct AFSFid *) &newFid.Fid,
@@ -765,7 +772,7 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
            }
         } else
            code = -1;
-    } while (afs_Analyze(tc, code, &tdp->f.fid, areq, op, SHARED_LOCK, NULL));
+    } while (afs_Analyze(tc, rxconn, code, &tdp->f.fid, areq, op, SHARED_LOCK, NULL));
 
     /* TODO: Handle errors. */
     if (code) {
@@ -794,11 +801,11 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
         */
        tdc = afs_FindDCacheByFid(&avc->f.fid);
        if (tdc) {
-           afs_dir_ChangeFid(tdc, ".", &avc->f.fid.Fid.Vnode, 
+           afs_dir_ChangeFid(tdc, ".", &avc->f.fid.Fid.Vnode,
                              &newFid.Fid.Vnode);
 
            if (avc->f.m.LinkCount >= 2)
-               /* For non empty dirs, fix children's parentVnode and 
+               /* For non empty dirs, fix children's parentVnode and
                 * parentUnique reference.
                 */
                afs_FixChildrenFids(&avc->f.fid, &newFid);
@@ -849,7 +856,7 @@ afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
     ObtainWriteLock(&afs_xdcache, 743);
     for (index = afs_dvhashTbl[hash]; index != NULLIDX; index = hash) {
         hash = afs_dvnextTbl[index];
-        tdc = afs_GetDSlot(index, NULL);
+        tdc = afs_GetValidDSlot(index);
         ReleaseReadLock(&tdc->tlock);
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
             if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
@@ -882,7 +889,7 @@ end:
     if (tdp)
        afs_PutVCache(tdp);
     afs_osi_Free(tname, AFSNAMEMAX);
-    if (ttargetName) 
+    if (ttargetName)
        afs_osi_Free(ttargetName, tlen);
     return code;
 }
@@ -909,6 +916,7 @@ afs_ProcessOpRemove(struct vcache *avc, struct vrequest *areq)
     struct VenusFid pdir_fid;
     struct AFSVolSync tsync;
     struct afs_conn *tc;
+    struct rx_connection *rxconn;
     struct vcache *tdp = NULL;
     int code = 0;
     XSTATS_DECLS;
@@ -934,11 +942,11 @@ afs_ProcessOpRemove(struct vcache *avc, struct vrequest *areq)
     if (vType(avc) == VREG || vType(avc) == VLNK) {
        /* Remove file on server. */
        do {
-           tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK);
+           tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK, &rxconn);
            if (tc) {
                XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
                RX_AFS_GUNLOCK();
-               code = RXAFS_RemoveFile(tc->id,
+               code = RXAFS_RemoveFile(rxconn,
                                &pdir_fid.Fid,
                                tname,
                                &OutDirStatus,
@@ -949,6 +957,7 @@ afs_ProcessOpRemove(struct vcache *avc, struct vrequest *areq)
            } else
                code = -1;
        } while (afs_Analyze(tc,
+                       rxconn,
                        code,
                        &pdir_fid,
                        areq,
@@ -959,11 +968,11 @@ afs_ProcessOpRemove(struct vcache *avc, struct vrequest *areq)
     } else if (vType(avc) == VDIR) {
        /* Remove dir on server. */
        do {
-           tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK);
+           tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK, &rxconn);
            if (tc) {
                XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR);
                RX_AFS_GUNLOCK();
-               code = RXAFS_RemoveDir(tc->id,
+               code = RXAFS_RemoveDir(rxconn,
                                &pdir_fid.Fid,
                                tname,
                                &OutDirStatus,
@@ -973,6 +982,7 @@ afs_ProcessOpRemove(struct vcache *avc, struct vrequest *areq)
           } else
                code = -1;
        } while (afs_Analyze(tc,
+                       rxconn,
                        code,
                        &pdir_fid,
                        areq,
@@ -1003,6 +1013,7 @@ int
 afs_SendChanges(struct vcache *avc, struct vrequest *areq)
 {
     struct afs_conn *tc;
+    struct rx_connection *rxconn;
     struct AFSStoreStatus sstat;
     struct AFSFetchStatus fstat;
     struct AFSVolSync tsync;
@@ -1016,12 +1027,12 @@ afs_SendChanges(struct vcache *avc, struct vrequest *areq)
        /* Turn dirty vc data into a new store status... */
        if (afs_GenStoreStatus(avc, &sstat) > 0) {
            do {
-               tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
+               tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn);
                if (tc) {
                    /* ... and send it. */
                    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STORESTATUS);
                    RX_AFS_GUNLOCK();
-                   code = RXAFS_StoreStatus(tc->id,
+                   code = RXAFS_StoreStatus(rxconn,
                                (struct AFSFid *) &avc->f.fid.Fid,
                                &sstat,
                                &fstat,
@@ -1033,6 +1044,7 @@ afs_SendChanges(struct vcache *avc, struct vrequest *areq)
                    code = -1;
 
        } while (afs_Analyze(tc,
+                       rxconn,
                        code,
                        &avc->f.fid,
                        areq,
@@ -1054,7 +1066,7 @@ afs_SendChanges(struct vcache *avc, struct vrequest *areq)
 
        /* Truncate OP: */
        do {
-           tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
+           tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn);
            if (tc) {
                /* Set storing flags. XXX: A tad inefficient ... */
                if (avc->f.ddirty_flags & VDisconWriteClose)
@@ -1071,6 +1083,7 @@ afs_SendChanges(struct vcache *avc, struct vrequest *areq)
                code = -1;
 
        } while (afs_Analyze(tc,
+                       rxconn,
                        code,
                        &avc->f.fid,
                        areq,
@@ -1100,6 +1113,7 @@ int
 afs_ResyncDisconFiles(struct vrequest *areq, afs_ucred_t *acred)
 {
     struct afs_conn *tc;
+    struct rx_connection *rxconn;
     struct vcache *tvc;
     struct AFSFetchStatus fstat;
     struct AFSCallBack callback;
@@ -1140,11 +1154,11 @@ afs_ResyncDisconFiles(struct vrequest *areq, afs_ucred_t *acred)
 #if 0
        /* Get server write lock. */
        do {
-           tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK);
+           tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK, &rxconn);
            if (tc) {
                XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
                RX_AFS_GUNLOCK();
-               code = RXAFS_SetLock(tc->id,
+               code = RXAFS_SetLock(rxconn,
                                        (struct AFSFid *)&tvc->f.fid.Fid,
                                        LockWrite,
                                        &tsync);
@@ -1154,6 +1168,7 @@ afs_ResyncDisconFiles(struct vrequest *areq, afs_ucred_t *acred)
                code = -1;
 
        } while (afs_Analyze(tc,
+                       rxconn,
                        code,
                        &tvc->f.fid,
                        areq,
@@ -1173,13 +1188,13 @@ afs_ResyncDisconFiles(struct vrequest *areq, afs_ucred_t *acred)
 
        /* Issue a FetchStatus to get info about DV and callbacks. */
        do {
-           tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK);
+           tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK, &rxconn);
            if (tc) {
-               tvc->callback = tc->srvr->server;
+               tvc->callback = tc->parent->srvr->server;
                start = osi_Time();
                XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
                RX_AFS_GUNLOCK();
-               code = RXAFS_FetchStatus(tc->id,
+               code = RXAFS_FetchStatus(rxconn,
                                (struct AFSFid *)&tvc->f.fid.Fid,
                                &fstat,
                                &callback,
@@ -1190,6 +1205,7 @@ afs_ResyncDisconFiles(struct vrequest *areq, afs_ucred_t *acred)
                code = -1;
 
        } while (afs_Analyze(tc,
+                       rxconn,
                        code,
                        &tvc->f.fid,
                        areq,
@@ -1219,7 +1235,7 @@ afs_ResyncDisconFiles(struct vrequest *areq, afs_ucred_t *acred)
        } else if (afs_ConflictPolicy == SERVER_WINS) {
            /* DV mismatch, apply collision resolution policy. */
            /* Discard this files chunks and remove from current dir. */
-           afs_ResetVCache(tvc, acred);
+           afs_ResetVCache(tvc, acred, 0);
            tvc->f.truncPos = AFS_NOTRUNC;
        } else {
            /* printf("afs_ResyncDisconFiles: no resolution policy selected.\n"); */
@@ -1229,11 +1245,11 @@ unlock_srv_file:
        /* Release server write lock. */
 #if 0
        do {
-           tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK);
+           tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK, &rxconn);
            if (tc) {
                XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
                RX_AFS_GUNLOCK();
-               ucode = RXAFS_ReleaseLock(tc->id,
+               ucode = RXAFS_ReleaseLock(rxconn,
                                (struct AFSFid *) &tvc->f.fid.Fid,
                                &tsync);
                RX_AFS_GLOCK();
@@ -1241,6 +1257,7 @@ unlock_srv_file:
            } else
                ucode = -1;
        } while (afs_Analyze(tc,
+                       rxconn,
                        ucode,
                        &tvc->f.fid,
                        areq,
@@ -1251,14 +1268,14 @@ unlock_srv_file:
 next_file:
        ObtainWriteLock(&afs_disconDirtyLock, 710);
        if (code == 0) {
-           /* Replayed successfully - pull the vcache from the 
+           /* Replayed successfully - pull the vcache from the
             * disconnected list */
            tvc->f.ddirty_flags = 0;
            QRemove(&tvc->dirtyq);
            afs_PutVCache(tvc);
        } else {
            if (code == EAGAIN) {
-               /* Operation was deferred. Pull it from the current place in 
+               /* Operation was deferred. Pull it from the current place in
                 * the list, and stick it at the end again */
                QRemove(&tvc->dirtyq);
                QAdd(&afs_disconDirty, &tvc->dirtyq);
@@ -1290,7 +1307,7 @@ next_file:
  * Discard all of our shadow directory copies. If squash is true, then
  * we also invalidate the vcache holding the shadow directory, to ensure
  * that any disconnected changes are deleted
- * 
+ *
  * \param squash
  * \param acred
  *
@@ -1310,12 +1327,10 @@ afs_DisconDiscardAllShadows(int squash, afs_ucred_t *acred)
        ReleaseWriteLock(&afs_disconDirtyLock);
        ObtainWriteLock(&tvc->lock, 706);
 
-       afs_DeleteShadowDir(tvc);
-       tvc->f.shadow.vnode = 0;
-       tvc->f.shadow.unique = 0;
-
        if (squash)
-          afs_ResetVCache(tvc, acred);
+          afs_ResetVCache(tvc, acred, 0);
+
+       afs_DeleteShadowDir(tvc);
 
        ReleaseWriteLock(&tvc->lock);
        ObtainWriteLock(&afs_disconDirtyLock, 709);
@@ -1330,7 +1345,7 @@ afs_DisconDiscardAllShadows(int squash, afs_ucred_t *acred)
  * \param acred
  *
  */
-void 
+void
 afs_DisconDiscardAll(afs_ucred_t *acred)
 {
     struct vcache *tvc;
@@ -1338,14 +1353,15 @@ afs_DisconDiscardAll(afs_ucred_t *acred)
     ObtainWriteLock(&afs_disconDirtyLock, 717);
     while (!QEmpty(&afs_disconDirty)) {
        tvc = QEntry(QPrev(&afs_disconDirty), struct vcache, dirtyq);
+       QRemove(&tvc->dirtyq);
        ReleaseWriteLock(&afs_disconDirtyLock);
 
        ObtainWriteLock(&tvc->lock, 718);
-       afs_ResetVCache(tvc, acred);
+       afs_ResetVCache(tvc, acred, 0);
        tvc->f.truncPos = AFS_NOTRUNC;
        ReleaseWriteLock(&tvc->lock);
-       afs_PutVCache(tvc);
        ObtainWriteLock(&afs_disconDirtyLock, 719);
+       afs_PutVCache(tvc);
     }
 
     afs_DisconDiscardAllShadows(1, acred);
@@ -1520,7 +1536,7 @@ afs_GenDisconStatus(struct vcache *adp, struct vcache *avc,
        vSetType(avc, VLNK);
        avc->f.m.Mode |= S_IFLNK;
        if ((avc->f.m.Mode & 0111) == 0)
-           avc->mvstat = 1;
+           avc->mvstat = AFS_MVSTAT_MTPT;
        avc->f.parent.vnode = adp->f.fid.Fid.Vnode;
        avc->f.parent.unique = adp->f.fid.Fid.Unique;
        break;