--- a/sys/vfs/msdosfs/msdosfs_lookup.c +++ b/sys/vfs/msdosfs/msdosfs_lookup.c @@ -798,6 +798,7 @@ struct denode *dep; struct buf *bp = NULL; int error = 0; + int depth = 0; dep = target; if ((target->de_Attributes & ATTR_DIRECTORY) == 0 || @@ -820,6 +821,19 @@ goto out; for (;;) { + /* + * DF-3037: a corrupt or crafted filesystem may contain a + * cycle in the ".." chain. Without a bound this walk + * spins forever on cached buffers/denodes and wedges + * rename(2) (and the whole system) until reboot. A + * legitimate ancestor chain is bounded by the + * namei-reachable path depth (PATH_MAX components), far + * below this cap. + */ + if (++depth > 4096) { + error = EINVAL; + break; + } if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) { error = ENOTDIR; break;