vol: prevent salvage segfault for orphaned vnode with out-of-range parent 85/14385/3
authorMark Vitale <mvitale@sinenomine.net>
Thu, 20 Aug 2020 20:09:02 +0000 (16:09 -0400)
committerBenjamin Kaduk <kaduk@mit.edu>
Wed, 13 Jan 2021 22:33:05 +0000 (17:33 -0500)
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 <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>

src/vol/vol-salvage.c

index 6643968..706f9f0 100644 (file)
@@ -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++;
                    }
                }
            }