summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_mount.c
diff options
context:
space:
mode:
authormm <mm@FreeBSD.org>2011-08-02 19:13:56 +0000
committermm <mm@FreeBSD.org>2011-08-02 19:13:56 +0000
commita1639c8fd44b7049b1a784f1d4c3e8d740972480 (patch)
tree0be435e7e1f43bc17986ae847deb1c85edc4f020 /sys/kern/vfs_mount.c
parenta698574a2dd1fc6989826cb60bfb64bc30711969 (diff)
downloadFreeBSD-src-a1639c8fd44b7049b1a784f1d4c3e8d740972480.zip
FreeBSD-src-a1639c8fd44b7049b1a784f1d4c3e8d740972480.tar.gz
For mount, discover f_mntonname from supplied path argument
using vn_fullpath_global(). This fixes f_mntonname if mounting inside chroot, jail or with relative path as argument. For unmount in jail, use vn_fullpath_global() to discover global path from supplied path argument. This fixes unmount in jail. Reviewed by: pjd, kib Approved by: re (kib) MFC after: 2 weeks
Diffstat (limited to 'sys/kern/vfs_mount.c')
-rw-r--r--sys/kern/vfs_mount.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 5d6892c..d601c56 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -745,7 +745,6 @@ static int
vfs_domount_first(
struct thread *td, /* Calling thread. */
struct vfsconf *vfsp, /* File system type. */
- char *fspath, /* Mount path. */
struct vnode *vp, /* Vnode to be covered. */
int fsflags, /* Flags common to all filesystems. */
struct vfsoptlist **optlist /* Options local to the filesystem. */
@@ -754,12 +753,25 @@ vfs_domount_first(
struct vattr va;
struct mount *mp;
struct vnode *newdp;
+ char *fspath, *fbuf;
int error;
mtx_assert(&Giant, MA_OWNED);
ASSERT_VOP_ELOCKED(vp, __func__);
KASSERT((fsflags & MNT_UPDATE) == 0, ("MNT_UPDATE shouldn't be here"));
+ /* Construct global filesystem path from vp. */
+ error = vn_fullpath_global(td, vp, &fspath, &fbuf);
+ if (error != 0) {
+ vput(vp);
+ return (error);
+ }
+ if (strlen(fspath) >= MNAMELEN) {
+ vput(vp);
+ free(fbuf, M_TEMP);
+ return (ENAMETOOLONG);
+ }
+
/*
* If the user is not root, ensure that they own the directory
* onto which we are attempting to mount.
@@ -781,12 +793,14 @@ vfs_domount_first(
}
if (error != 0) {
vput(vp);
+ free(fbuf, M_TEMP);
return (error);
}
VOP_UNLOCK(vp, 0);
/* Allocate and initialize the filesystem. */
mp = vfs_mount_alloc(vp, vfsp, fspath, td->td_ucred);
+ free(fbuf, M_TEMP);
/* XXXMAC: pass to vfs_mount_alloc? */
mp->mnt_optnew = *optlist;
/* Set the mount level flags. */
@@ -1069,12 +1083,10 @@ vfs_domount(
mtx_lock(&Giant);
NDFREE(&nd, NDF_ONLY_PNBUF);
vp = nd.ni_vp;
- if ((fsflags & MNT_UPDATE) == 0) {
- error = vfs_domount_first(td, vfsp, fspath, vp, fsflags,
- optlist);
- } else {
+ if ((fsflags & MNT_UPDATE) == 0)
+ error = vfs_domount_first(td, vfsp, vp, fsflags, optlist);
+ else
error = vfs_domount_update(td, vp, fsflags, optlist);
- }
mtx_unlock(&Giant);
ASSERT_VI_UNLOCKED(vp, __func__);
@@ -1105,7 +1117,8 @@ unmount(td, uap)
} */ *uap;
{
struct mount *mp;
- char *pathbuf;
+ struct nameidata nd;
+ char *pathbuf, *rpathbuf, *fbuf;
int error, id0, id1;
AUDIT_ARG_VALUE(uap->flags);
@@ -1140,6 +1153,28 @@ unmount(td, uap)
mtx_unlock(&mountlist_mtx);
} else {
AUDIT_ARG_UPATH1(td, pathbuf);
+ /*
+ * If we are jailed and this is not a root jail try to find
+ * global path for path argument.
+ */
+ if (jailed(td->td_ucred) &&
+ td->td_ucred->cr_prison->pr_root != rootvnode) {
+ NDINIT(&nd, LOOKUP,
+ FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
+ UIO_SYSSPACE, pathbuf, td);
+ if (namei(&nd) == 0) {
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ if (vn_fullpath_global(td, nd.ni_vp, &rpathbuf,
+ &fbuf) == 0) {
+ if (strlen(rpathbuf) < MNAMELEN) {
+ strlcpy(pathbuf, rpathbuf,
+ MNAMELEN);
+ }
+ free(fbuf, M_TEMP);
+ }
+ vput(nd.ni_vp);
+ }
+ }
mtx_lock(&mountlist_mtx);
TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0)
OpenPOWER on IntegriCloud