[f2fs] Fix UAF and root handling in Dir::IsSubdir

In Dir::IsSubdir(), the loop walked the parent inode chain by calling
fs()->GetVnode() into a local zx::result<fbl::RefPtr<VnodeF2fs>>
variable that fell out of scope at the end of each iteration. Because
vnode was assigned via (*parent).get(), subsequent iterations
dereferenced a raw pointer after the owning RefPtr was destroyed. If a
concurrent unlink evicted and destroyed the unlinked directory, this
caused a heap-use-after-free when reading vnode->Ino() or
vnode->GetParentNid().

Fix this by maintaining the owning fbl::RefPtr<VnodeF2fs> across loop
iterations until traversal completes.

Additionally, Dir::IsSubdir() previously returned false when checking
if a directory was a subdirectory of the root directory, because the
traversal loop while (vnode->Ino() != root_ino) stopped upon reaching
the root without matching. Fix this by adding an early guard clause
returning true when this is the root directory (Ino() == root_ino), as
every directory is under root.

Test: fx test f2fs-unittest f2fs-rename-tests
TAG: agy
CONV: 745076da-a1ea-4c30-ae49-cc8e8d2f5434
Change-Id: I539d1d2cae7d1a8b570d4bd0e58ff175c2c8b92c
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1787037
Reviewed-by: Stephen Demos <sdemos@google.com>
Commit-Queue: Aaron Drew <ripper@google.com>
1 file changed