]> xenbits.xensource.com Git - people/royger/freebsd.git/commitdiff
cache: only let non-dir descriptors through when doing EMPTYPATH lookups
authorMateusz Guzik <mjg@FreeBSD.org>
Wed, 27 Oct 2021 18:17:59 +0000 (20:17 +0200)
committerMateusz Guzik <mjg@FreeBSD.org>
Sat, 5 Mar 2022 19:52:57 +0000 (19:52 +0000)
Otherwise things like realpath against a file and '.' end up with an
illegal state of having a regular vnode for the parent.

Reported by: syzbot+9aa5439dd9c708aeb1a8@syzkaller.appspotmail.com

(cherry picked from commit 628c3b307fb29e9812008b8a0b3ccb73e0f0ecfa)

sys/kern/vfs_cache.c

index 14e148b2f839b29288fbde7a7ac94e97306534bd..bc85c96c045f68bef358787d1b5026da21b5236f 100644 (file)
@@ -4242,19 +4242,28 @@ cache_can_fplookup(struct cache_fpl *fpl)
        return (true);
 }
 
-static int
+static int __noinline
 cache_fplookup_dirfd(struct cache_fpl *fpl, struct vnode **vpp)
 {
        struct nameidata *ndp;
+       struct componentname *cnp;
        int error;
        bool fsearch;
 
        ndp = fpl->ndp;
+       cnp = fpl->cnp;
+
        error = fgetvp_lookup_smr(ndp->ni_dirfd, ndp, vpp, &fsearch);
        if (__predict_false(error != 0)) {
                return (cache_fpl_aborted(fpl));
        }
        fpl->fsearch = fsearch;
+       if ((*vpp)->v_type != VDIR) {
+               if (!((cnp->cn_flags & EMPTYPATH) != 0 && cnp->cn_pnbuf[0] == '\0')) {
+                       cache_fpl_smr_exit(fpl);
+                       return (cache_fpl_handled_error(fpl, ENOTDIR));
+               }
+       }
        return (0);
 }