Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105588106
D37741.id115280.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D37741.id115280.diff
View Options
diff --git a/sys/kern/vfs_mount.c.vnet b/sys/kern/vfs_mount.c
--- a/sys/kern/vfs_mount.c.vnet
+++ b/sys/kern/vfs_mount.c
@@ -797,7 +797,7 @@
struct vfsopt *opt, *tmp_opt;
char *fstype, *fspath, *errmsg;
int error, fstypelen, fspathlen, errmsg_len, errmsg_pos;
- bool autoro;
+ bool autoro, done_nonexport, has_nonexport;
errmsg = fspath = NULL;
errmsg_len = fspathlen = 0;
@@ -834,6 +834,19 @@
}
/*
+ * Make sure that "export" is only used with the "update", "fstype",
+ * "fspath", "from" and "errmsg" options when in a vnet jail.
+ * These are the ones used to set/update exports by mountd(8).
+ * Clear MNT_EXPORTED here, so that it cannot be passed in
+ * via the flags argument to nmount(2), to force use of "export".
+ * Use has_nonexport and done_nonexport to track whether or
+ * not other options have been specified.
+ */
+ has_nonexport = false;
+ if (jailed(td->td_ucred) && prison_check_nfsd(td->td_ucred))
+ fsflags &= ~MNT_EXPORTED;
+
+ /*
* We need to see if we have the "update" option
* before we call vfs_domount(), since vfs_domount() has special
* logic based on MNT_UPDATE. This is very important
@@ -842,9 +855,11 @@
TAILQ_FOREACH_SAFE(opt, optlist, link, tmp_opt) {
int do_freeopt = 0;
+ done_nonexport = true;
if (strcmp(opt->name, "update") == 0) {
fsflags |= MNT_UPDATE;
do_freeopt = 1;
+ done_nonexport = false;
}
else if (strcmp(opt->name, "async") == 0)
fsflags |= MNT_ASYNC;
@@ -924,9 +939,11 @@
fsflags |= MNT_SYNCHRONOUS;
else if (strcmp(opt->name, "union") == 0)
fsflags |= MNT_UNION;
- else if (strcmp(opt->name, "export") == 0)
+ else if (strcmp(opt->name, "export") == 0) {
fsflags |= MNT_EXPORTED;
- else if (strcmp(opt->name, "automounted") == 0) {
+ done_nonexport = false;
+ autoro = false;
+ } else if (strcmp(opt->name, "automounted") == 0) {
fsflags |= MNT_AUTOMOUNTED;
do_freeopt = 1;
} else if (strcmp(opt->name, "nocover") == 0) {
@@ -941,9 +958,21 @@
} else if (strcmp(opt->name, "noemptydir") == 0) {
fsflags &= ~MNT_EMPTYDIR;
do_freeopt = 1;
+ } else if (strcmp(opt->name, "fstype") == 0 ||
+ strcmp(opt->name, "fspath") == 0 ||
+ strcmp(opt->name, "from") == 0 ||
+ strcmp(opt->name, "errmsg") == 0) {
+ /*
+ * These four options are used along
+ * with "export" and "update" by
+ * mountd(8) for file system exporting.
+ */
+ done_nonexport = false;
}
if (do_freeopt)
vfs_freeopt(optlist, opt);
+ if (done_nonexport)
+ has_nonexport = true;
}
/*
@@ -956,6 +985,18 @@
goto bail;
}
+ /*
+ * Do not allow "export" to be mixed with any other options
+ * that change behaviour and only allow "export" with "update",
+ * when in a vnet jail.
+ */
+ if ((fsflags & MNT_EXPORTED) != 0 && jailed(td->td_ucred) &&
+ prison_check_nfsd(td->td_ucred) && ((fsflags & MNT_UPDATE) == 0 ||
+ has_nonexport)) {
+ error = EINVAL;
+ goto bail;
+ }
+
error = vfs_domount(td, fstype, fspath, fsflags, &optlist);
if (error == ENOENT) {
error = EINVAL;
@@ -1035,6 +1076,13 @@
*/
flags &= ~MNT_ROOTFS;
+ /*
+ * Do not allow exports to be set with the old syscall, when
+ * inside a vnet jail.
+ */
+ if (jailed(td->td_ucred) && prison_check_nfsd(td->td_ucred))
+ flags &= ~MNT_EXPORTED;
+
fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK);
error = copyinstr(uap->type, fstype, MFSNAMELEN, NULL);
if (error) {
@@ -1303,7 +1351,18 @@
* Only privileged root, or (if MNT_USER is set) the user that
* did the original mount is permitted to update it.
*/
- error = vfs_suser(mp, td);
+ /*
+ * For the case of mountd(8) doing exports in a jail, don't
+ * call vfs_suser(). vfs_domount() has already checked that
+ * "root" is doing this and vfs_suser() will fail when
+ * the file system has been mounted outside the jail.
+ * vfs_donmount() has ensured that MNT_EXPORTED is not
+ * mixed with other options that change mount behaviour.
+ */
+ error = 0;
+ if ((fsflags & MNT_EXPORTED) == 0 || !jailed(td->td_ucred) ||
+ !prison_check_nfsd(td->td_ucred))
+ error = vfs_suser(mp, td);
if (error != 0) {
vput(vp);
return (error);
@@ -1333,9 +1392,19 @@
error = EBUSY;
goto end;
}
- mp->mnt_flag &= ~MNT_UPDATEMASK;
- mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE |
- MNT_SNAPSHOT | MNT_ROOTFS | MNT_UPDATEMASK | MNT_RDONLY);
+
+ /*
+ * For mountd(8) doing exports from within a jail, only allow the
+ * MNT_EXPORTED flag to be updated.
+ */
+ if ((fsflags & MNT_EXPORTED) != 0 && jailed(td->td_ucred) &&
+ prison_check_nfsd(td->td_ucred)) {
+ mp->mnt_flag |= MNT_EXPORTED;
+ } else {
+ mp->mnt_flag &= ~MNT_UPDATEMASK;
+ mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE |
+ MNT_SNAPSHOT | MNT_ROOTFS | MNT_UPDATEMASK | MNT_RDONLY);
+ }
if ((mp->mnt_flag & MNT_ASYNC) == 0)
mp->mnt_kern_flag &= ~MNTK_ASYNC;
rootvp = vfs_cache_root_clear(mp);
@@ -1348,7 +1417,18 @@
* XXX The final recipients of VFS_MOUNT just overwrite the ndp they
* get. No freeing of cn_pnbuf.
*/
- error = VFS_MOUNT(mp);
+ /*
+ * For the case of mountd(8) doing exports from within a vnet jail,
+ * "from" is typically not set correctly such that VFS_MOUNT() will
+ * return ENOENT. It is not obvious that VFS_MOUNT() ever needs to be
+ * called when mountd is doing exports, but this check only applies to
+ * the specific case where it is running inside a vnet jail, to
+ * avoid any POLA violation.
+ */
+ error = 0;
+ if ((fsflags & MNT_EXPORTED) == 0 || !jailed(td->td_ucred) ||
+ !prison_check_nfsd(td->td_ucred))
+ error = VFS_MOUNT(mp);
export_error = 0;
/* Process the export option. */
@@ -1503,7 +1583,12 @@
if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN)
return (ENAMETOOLONG);
- if (jailed(td->td_ucred) || usermount == 0) {
+ if ((fsflags & MNT_EXPORTED) != 0 && jailed(td->td_ucred) &&
+ prison_check_nfsd(td->td_ucred)) {
+ error = priv_check(td, PRIV_NFS_DAEMON);
+ if (error)
+ return (error);
+ } else if (jailed(td->td_ucred) || usermount == 0) {
if ((error = priv_check(td, PRIV_VFS_MOUNT)) != 0)
return (error);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Dec 19, 12:25 AM (20 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15498070
Default Alt Text
D37741.id115280.diff (6 KB)
Attached To
Mode
D37741: Modify vfs_mount.c so that mountd can run in a vnet prison
Attached
Detach File
Event Timeline
Log In to Comment