diff --git a/sys/vfs/ufs/ufs_lookup.c b/sys/vfs/ufs/ufs_lookup.c --- a/sys/vfs/ufs/ufs_lookup.c +++ b/sys/vfs/ufs/ufs_lookup.c @@ -1105,6 +1105,8 @@ return (1); } +#define UFS_CHECKPATH_MAXDEPTH 64 /* sane bound on .. chain length */ + /* * Check if source directory is in the path of the target directory. * Target is supplied locked, source is unlocked. @@ -1114,7 +1116,7 @@ ufs_checkpath(struct inode *source, struct inode *target, struct ucred *cred) { struct vnode *vp; - int error, rootino, namlen; + int error, rootino, namlen, depth = 0; struct dirtemplate dirbuf; vp = ITOV(target); @@ -1128,6 +1130,10 @@ goto out; for (;;) { + if (++depth > UFS_CHECKPATH_MAXDEPTH) { + error = ENOTDIR; /* .. chain too long or cyclic */ + break; + } if (vp->v_type != VDIR) { error = ENOTDIR; break;