diff options
author | Doug Rabson <dfr@FreeBSD.org> | 2022-11-23 14:51:13 +0000 |
---|---|---|
committer | Doug Rabson <dfr@FreeBSD.org> | 2022-12-19 16:46:13 +0000 |
commit | 521fbb722c33663cf00a83bca70ad7cb790687b3 (patch) | |
tree | fe2bed0dd21c809d9072450ed503982f2072b783 /sys/kern/vfs_mount.c | |
parent | 78d35459a2586da024ac18e8768b44893c7184e7 (diff) | |
download | src-521fbb722c33663cf00a83bca70ad7cb790687b3.tar.gz src-521fbb722c33663cf00a83bca70ad7cb790687b3.zip |
Diffstat (limited to 'sys/kern/vfs_mount.c')
-rw-r--r-- | sys/kern/vfs_mount.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index bf8fd3b1c179..8001604d2855 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -1105,8 +1105,13 @@ vfs_domount_first( error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN); if (error == 0) error = vinvalbuf(vp, V_SAVE, 0, 0); - if (error == 0 && vp->v_type != VDIR) - error = ENOTDIR; + if (vfsp->vfc_flags & VFCF_FILEMOUNT) { + if (error == 0 && vp->v_type != VDIR && vp->v_type != VREG) + error = EINVAL; + } else { + if (error == 0 && vp->v_type != VDIR) + error = ENOTDIR; + } if (error == 0 && (fsflags & MNT_EMPTYDIR) != 0) error = vfs_emptydir(vp); if (error == 0) { @@ -1535,22 +1540,33 @@ vfs_domount( /* * Get vnode to be covered or mount point's vnode in case of MNT_UPDATE. */ - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_SYSSPACE, - fspath); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1 | WANTPARENT, + UIO_SYSSPACE, fspath); error = namei(&nd); if (error != 0) return (error); - NDFREE_PNBUF(&nd); vp = nd.ni_vp; if ((fsflags & MNT_UPDATE) == 0) { if ((vp->v_vflag & VV_ROOT) != 0 && (fsflags & MNT_NOCOVER) != 0) { vput(vp); - return (EBUSY); + error = EBUSY; + goto out; } pathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK); strcpy(pathbuf, fspath); - error = vn_path_to_global_path(td, vp, pathbuf, MNAMELEN); + /* + * Note: we allow any vnode type here. If the path sanity check + * succeeds, the type will be validated in vfs_domount_first + * above. + */ + if (vp->v_type == VDIR) + error = vn_path_to_global_path(td, vp, pathbuf, + MNAMELEN); + else + error = vn_path_to_global_path_hardlink(td, vp, + nd.ni_dvp, pathbuf, MNAMELEN, + nd.ni_cnd.cn_nameptr, nd.ni_cnd.cn_namelen); if (error == 0) { error = vfs_domount_first(td, vfsp, pathbuf, vp, fsflags, optlist); @@ -1559,6 +1575,10 @@ vfs_domount( } else error = vfs_domount_update(td, vp, fsflags, optlist); +out: + NDFREE_PNBUF(&nd); + vrele(nd.ni_dvp); + return (error); } |