aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Rabson <dfr@FreeBSD.org>2022-11-23 14:51:13 +0000
committerDoug Rabson <dfr@FreeBSD.org>2022-12-19 16:46:13 +0000
commit521fbb722c33663cf00a83bca70ad7cb790687b3 (patch)
treefe2bed0dd21c809d9072450ed503982f2072b783
parent78d35459a2586da024ac18e8768b44893c7184e7 (diff)
downloadsrc-521fbb722c33.tar.gz
src-521fbb722c33.zip
Add support for mounting single files in nullfs
The main use-case for this is to support mounting config files and secrets into OCI containers. My current workaround copies the files into the container which is messy and risks secrets leaking into container images if the cleanup fails. This adds a VFCF flag to indicate whether the filesystem supports file mounts and allows fspath to be either a directory or a file if the flag is set. Test Plan: $ sudo mkdir -p /mnt $ sudo touch /mnt/foo $ sudo mount -t nullfs /COPYRIGHT /mnt/foo Reviewed by: mjg, kib Tested by: pho
-rw-r--r--sys/fs/nullfs/null_vfsops.c13
-rw-r--r--sys/kern/vfs_mount.c34
-rw-r--r--sys/sys/mount.h1
3 files changed, 40 insertions, 8 deletions
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index 216a8badce56..7f78d23ba016 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -156,6 +156,17 @@ nullfs_mount(struct mount *mp)
}
}
+ /*
+ * Lower vnode must be the same type as the covered vnode - we
+ * don't allow mounting directories to files or vice versa.
+ */
+ if ((lowerrootvp->v_type != VDIR && lowerrootvp->v_type != VREG) ||
+ lowerrootvp->v_type != mp->mnt_vnodecovered->v_type) {
+ NULLFSDEBUG("nullfs_mount: target must be same type as fspath");
+ vput(lowerrootvp);
+ return (EINVAL);
+ }
+
xmp = (struct null_mount *) malloc(sizeof(struct null_mount),
M_NULLFSMNT, M_WAITOK | M_ZERO);
@@ -503,4 +514,4 @@ static struct vfsops null_vfsops = {
.vfs_unlink_lowervp = nullfs_unlink_lowervp,
};
-VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK | VFCF_JAIL);
+VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK | VFCF_JAIL | VFCF_FILEMOUNT);
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);
}
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index ffb2676258f3..4bfc77b7f1a1 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -678,6 +678,7 @@ struct ovfsconf {
#define VFCF_DELEGADMIN 0x00800000 /* supports delegated administration */
#define VFCF_SBDRY 0x01000000 /* Stop at Boundary: defer stop requests
to kernel->user (AST) transition */
+#define VFCF_FILEMOUNT 0x02000000 /* allow mounting files */
typedef uint32_t fsctlop_t;