diff --git a/sys/kern/vfs_export.c.vnet b/sys/kern/vfs_export.c --- a/sys/kern/vfs_export.c.vnet +++ b/sys/kern/vfs_export.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -301,6 +302,7 @@ { struct netexport *nep; int error; + bool injail; if ((argp->ex_flags & (MNT_DELEXPORT | MNT_EXPORTED)) == 0) return (EINVAL); @@ -311,6 +313,7 @@ return (EINVAL); error = 0; + injail = jailed(curthread->td_ucred); lockmgr(&mp->mnt_explock, LK_EXCLUSIVE, NULL); nep = mp->mnt_export; if (argp->ex_flags & MNT_DELEXPORT) { @@ -318,6 +321,15 @@ error = ENOENT; goto out; } + if (injail && (mp->mnt_flag & MNT_EXJAIL) == 0) { + /* EPERM will get logged by mountd(8). */ + error = EPERM; + goto out; + } else if (!injail && (mp->mnt_flag & MNT_EXJAIL) != 0) { + /* EXDEV will not get logged by mountd(8). */ + error = EXDEV; + goto out; + } if (mp->mnt_flag & MNT_EXPUBLIC) { vfs_setpublicfs(NULL, NULL, NULL); MNT_ILOCK(mp); @@ -329,13 +341,17 @@ free(nep, M_MOUNT); nep = NULL; MNT_ILOCK(mp); - mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED); + mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED | MNT_EXJAIL); MNT_IUNLOCK(mp); } if (argp->ex_flags & MNT_EXPORTED) { if (nep == NULL) { nep = malloc(sizeof(struct netexport), M_MOUNT, M_WAITOK | M_ZERO); mp->mnt_export = nep; + } else if ((injail && (mp->mnt_flag & MNT_EXJAIL) == 0) || + (!injail && (mp->mnt_flag & MNT_EXJAIL) != 0)) { + error = EPERM; + goto out; } if (argp->ex_flags & MNT_EXPUBLIC) { if ((error = vfs_setpublicfs(mp, nep, argp)) != 0) @@ -352,6 +368,8 @@ goto out; MNT_ILOCK(mp); mp->mnt_flag |= MNT_EXPORTED; + if (injail) + mp->mnt_flag |= MNT_EXJAIL; MNT_IUNLOCK(mp); } diff --git a/sys/sys/mount.h.vnet b/sys/sys/mount.h --- a/sys/sys/mount.h.vnet +++ b/sys/sys/mount.h @@ -399,6 +399,7 @@ #define MNT_EXTLS 0x0000004000000000ULL /* require TLS */ #define MNT_EXTLSCERT 0x0000008000000000ULL /* require TLS with client cert */ #define MNT_EXTLSCERTUSER 0x0000010000000000ULL /* require TLS with user cert */ +#define MNT_EXJAIL 0x0000020000000000ULL /* exported in a jail */ /* * Flags set by internal operations, but visible to the user.