--- /home/maxx/dfbsd/dfbsd/sys/kern/vfs_nlookup.c 2026-06-29 12:51:19.000000000 +0000 +++ guest-vfs_nlookup.c 2026-10-20 08:46:37.108583771 +0000 @@ -59,6 +59,8 @@ #include #include #include +#include +#include #include #include #include @@ -144,6 +146,7 @@ if (error == 0) { if (p && p->p_fd) { + spin_lock(&p->p_fd->fd_spin); if (nd->nl_path[0] == '/') { if ((flags & NLC_NLNCH_NOINIT) == 0) { nd->nl_basench = &p->p_fd->fd_nrdir; @@ -165,6 +168,7 @@ nd->nl_cred = td->td_ucred; nd->nl_flags |= NLC_BORROWCRED; } + spin_unlock(&p->p_fd->fd_spin); } else { if ((flags & NLC_NLNCH_NOINIT) == 0) { nd->nl_basench = &rootnch; @@ -239,7 +243,18 @@ nd->nl_basench = &fp->f_nchandle; *fpp = fp; } - cache_copy(nd->nl_basench, &nd->nl_nch); + { + struct filedesc *fdp = curproc->p_fd; + + if (nd->nl_basench == &fdp->fd_ncdir || + nd->nl_basench == &fdp->fd_nrdir) { + spin_lock(&fdp->fd_spin); + cache_copy(nd->nl_basench, &nd->nl_nch); + spin_unlock(&fdp->fd_spin); + } else { + cache_copy(nd->nl_basench, &nd->nl_nch); + } + } done: if (error) nlookup_done(nd); @@ -757,6 +772,21 @@ } else { nctmp.ncp = nctmp.ncp->nc_parent; } + /* + * The current directory's namecache topology can become + * disconnected (directory removed out from under us while + * fd_ncdir still holds a reference). nc_parent is then + * NULL; recover using the process root, same as the + * jail-break case above, instead of dereferencing NULL. + */ + if (nctmp.ncp == NULL) { + kprintf("vfs_nlookup: '..' traverse disconnected: " + "pid %d (%s)\n", + curthread->td_proc ? + curthread->td_proc->p_pid : 0, + curthread->td_comm); + nctmp = nd->nl_rootnch; + } if (last_element) { cache_get_maybe_shared(&nctmp, &nch, wantsexcllock(nd, 1)); @@ -1377,7 +1407,20 @@ nd->nl_flags &= ~NLC_NCPISLOCKED; } cache_drop(&nd->nl_nch); - cache_copy(nd->nl_basench, &nd->nl_nch); + { + struct filedesc *fdp; + + fdp = nd->nl_td->td_proc ? nd->nl_td->td_proc->p_fd : NULL; + if (fdp && + (nd->nl_basench == &fdp->fd_ncdir || + nd->nl_basench == &fdp->fd_nrdir)) { + spin_lock(&fdp->fd_spin); + cache_copy(nd->nl_basench, &nd->nl_nch); + spin_unlock(&fdp->fd_spin); + } else { + cache_copy(nd->nl_basench, &nd->nl_nch); + } + } nd->nl_elmno = 0; nd->nl_flags |= saveflag; --- /home/maxx/dfbsd/dfbsd/sys/kern/vfs_syscalls.c 2026-06-29 12:51:19.000000000 +0000 +++ guest-vfs_syscalls.c 2026-10-20 08:46:37.388580174 +0000 @@ -2028,6 +2028,9 @@ struct proc *p = td->td_proc; struct filedesc *fdp = p->p_fd; struct vnode *vp; + struct vnode *ovp; + struct nchandle onch; + int setjail; int error; /* @@ -2059,15 +2062,21 @@ vn_unlock(vp); /* leave reference intact */ if (error == 0) { lwkt_gettoken(&p->p_token); - vrele(fdp->fd_rdir); + ovp = fdp->fd_rdir; + setjail = (fdp->fd_jdir == NULL); + if (setjail) + vref(vp); + spin_lock(&fdp->fd_spin); fdp->fd_rdir = vp; /* reference inherited by fd_rdir */ - cache_drop(&fdp->fd_nrdir); + onch = fdp->fd_nrdir; cache_copy(nch, &fdp->fd_nrdir); - if (fdp->fd_jdir == NULL) { - fdp->fd_jdir = vp; - vref(fdp->fd_jdir); + if (setjail) { + fdp->fd_jdir = vp; /* reference taken above */ cache_copy(nch, &fdp->fd_njdir); } + spin_unlock(&fdp->fd_spin); + vrele(ovp); + cache_drop(&onch); if ((p->p_flags & P_DIDCHROOT) == 0) { p->p_flags |= P_DIDCHROOT; if (p->p_depth <= 65535 - 32)