From: Mark Vitale Date: Thu, 20 Aug 2020 20:09:02 +0000 (-0400) Subject: vol: prevent salvage segfault for orphaned vnode with out-of-range parent X-Git-Tag: openafs-devel-1_9_1~44 X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=750628da77bb71e24ed3061431bbb913ff8d5f72 vol: prevent salvage segfault for orphaned vnode with out-of-range parent While salvaging a RW volume, salvager may segfault if it encounters an orphaned directory with a parent vnode that does not exist. For example, if the large vnode index contains a maximum vnode of 2901, any parent vnode encountered that is larger than 2901 will result in an out-of-bounds reference to our vnode essence array, leading to a segfault or undefined behavior. Modify the logic to check for out-of-bounds parent vnodes, and log them rather than segfaulting. Change-Id: I49f53935830fbb428fe0bff04c33248d3806a4b2 Reviewed-on: https://gerrit.openafs.org/14385 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Benjamin Kaduk --- diff --git a/src/vol/vol-salvage.c b/src/vol/vol-salvage.c index 6643968..706f9f0 100644 --- a/src/vol/vol-salvage.c +++ b/src/vol/vol-salvage.c @@ -4052,8 +4052,15 @@ SalvageVolume(struct SalvInfo *salvinfo, struct InodeSummary *rwIsp, IHandle_t * * link count was not incremented in JudgeEntry(). */ if (class == vLarge) { /* directory vnode */ - pv = vnodeIdToBitNumber(vep->parent); - if (salvinfo->vnodeInfo[vLarge].vnodes[pv].unique != 0) { + struct VnodeEssence *parent_vep; + + parent_vep = CheckVnodeNumber(salvinfo, vep->parent); + + if (!parent_vep) + Log("Vnode %d has invalid or out-of-range parent vnode %d;" \ + " ignore parent count adjustment\n", + ThisVnode, vep->parent); + else if (parent_vep->unique != 0) { if (vep->parent == 1 && newrootdir) { /* this vnode's parent was the volume root, and * we just created the volume root. So, the parent @@ -4064,7 +4071,7 @@ SalvageVolume(struct SalvInfo *salvinfo, struct InodeSummary *rwIsp, IHandle_t * /* noop */ } else { - salvinfo->vnodeInfo[vLarge].vnodes[pv].count++; + parent_vep->count++; } } }