From 5af63fabc553a2fecd4c3080b25fe14483f5bd98 Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Fri, 2 Mar 2012 17:06:48 -0600 Subject: [PATCH] afs: Sanity-check some AFSFetchStatus structures We currently do not do any sanity checking on the AFSFetchStatus structures returned from fileservers. Add some sanity checking for BulkStatus and FetchStatus calls, so we do not screw up our cache if a fileserver gives us bogus data. If we do get an invalid AFSFetchStatus structure, act as if the server gave us a VBUSY error code, so we will retry the request. For OpenAFS fileservers prior to 1.6.1 that yield this situation, VBUSY is likely the error code the fileserver should have responded anyway. Change-Id: Ie16a5210149b21dd5945380f5d7b6a4d9ee01a72 Reviewed-on: http://gerrit.openafs.org/6880 Reviewed-by: Alistair Ferguson Tested-by: BuildBot Reviewed-by: Derrick Brashear --- src/afs/VNOPS/afs_vnop_lookup.c | 27 +++++++++++++++++++++++++++ src/afs/afs_prototypes.h | 2 ++ src/afs/afs_vcache.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c index 1a15f49b4..c14b4a513 100644 --- a/src/afs/VNOPS/afs_vnop_lookup.c +++ b/src/afs/VNOPS/afs_vnop_lookup.c @@ -622,6 +622,29 @@ Next_AtSys(struct vcache *avc, struct vrequest *areq, return 1; } +static int +afs_CheckBulkStatus(struct afs_conn *tc, int nFids, AFSBulkStats *statParm, + AFSCBs *cbParm) +{ + int i; + int code; + + if (statParm->AFSBulkStats_len != nFids || cbParm->AFSCBs_len != nFids) { + return VBUSY; + } + for (i = 0; i < nFids; i++) { + if (statParm->AFSBulkStats_val[i].errorCode) { + continue; + } + code = afs_CheckFetchStatus(tc, &statParm->AFSBulkStats_val[i]); + if (code) { + return code; + } + } + + return 0; +} + extern int BlobScan(struct dcache * afile, afs_int32 ablob); /* called with an unlocked directory and directory cookie. Areqp @@ -1002,6 +1025,10 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) RX_AFS_GLOCK(); } XSTATS_END_TIME; + + if (code == 0) { + code = afs_CheckBulkStatus(tcp, fidIndex, &statParm, &cbParm); + } } else code = -1; } while (afs_Analyze diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h index 71ef0a6a9..26335284b 100644 --- a/src/afs/afs_prototypes.h +++ b/src/afs/afs_prototypes.h @@ -1071,6 +1071,8 @@ extern void afs_FlushReclaimedVcaches(void); void afs_vcacheInit(int astatSize); extern struct vcache *afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag); +extern int afs_CheckFetchStatus(struct afs_conn *tc, + struct AFSFetchStatus *status); extern afs_int32 afs_FetchStatus(struct vcache *avc, struct VenusFid *afid, struct vrequest *areq, struct AFSFetchStatus *Outsp); diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index 7428c94a6..4f1372b2e 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -2346,6 +2346,30 @@ afs_UpdateStatus(struct vcache *avc, struct VenusFid *afid, afs_PutVolume(volp, READ_LOCK); } +/** + * Check if a given AFSFetchStatus structure is sane. + * + * @param[in] tc The server from which we received the status + * @param[in] status The status we received + * + * @return whether the given structure is valid or not + * @retval 0 the structure is fine + * @retval nonzero the structure looks like garbage; act as if we received + * the returned error code from the server + */ +int +afs_CheckFetchStatus(struct afs_conn *tc, struct AFSFetchStatus *status) +{ + if (status->errorCode || + status->InterfaceVersion != 1 || + !(status->FileType > Invalid && status->FileType <= SymbolicLink) || + status->ParentVnode == 0 || status->ParentUnique == 0) { + + return VBUSY; + } + return 0; +} + /*! * Must be called with avc write-locked * don't absolutely have to invalidate the hint unless the dv has @@ -2377,6 +2401,10 @@ afs_FetchStatus(struct vcache * avc, struct VenusFid * afid, XSTATS_END_TIME; + if (code == 0) { + code = afs_CheckFetchStatus(tc, Outsp); + } + } else code = -1; } while (afs_Analyze -- 2.39.5