Make it easier for filesystems to count themselves as jail-enabled,

by doing most of the work in a new function prison_add_vfs in kern_jail.c
Now a jail-enabled filesystem need only mark itself with VFCF_JAIL, and
the rest is taken care of.  This includes adding a jail parameter like
allow.mount.foofs, and a sysctl like security.jail.mount_foofs_allowed.
Both of these used to be a static list of known filesystems, with
predefined permission bits.

Reviewed by:	kib
Differential Revision:	D14681
This commit is contained in:
Jamie Gritton 2018-05-04 20:54:27 +00:00
parent d55f0e89c8
commit 0e5c6bd436
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=333263
17 changed files with 191 additions and 144 deletions

View File

@ -1048,7 +1048,13 @@ kldload_param(const char *name)
else if (strcmp(name, "sysvmsg") == 0 || strcmp(name, "sysvsem") == 0 || else if (strcmp(name, "sysvmsg") == 0 || strcmp(name, "sysvsem") == 0 ||
strcmp(name, "sysvshm") == 0) strcmp(name, "sysvshm") == 0)
kl = kldload(name); kl = kldload(name);
else { else if (strncmp(name, "allow.mount.", 12) == 0) {
/* Load the matching filesystem */
kl = kldload(name + 12);
if (kl < 0 && errno == ENOENT &&
strncmp(name + 12, "no", 2) == 0)
kl = kldload(name + 14);
} else {
errno = ENOENT; errno = ENOENT;
return (-1); return (-1);
} }

View File

@ -1640,9 +1640,6 @@ zfs_mount(vfs_t *vfsp)
osname = spn.pn_path; osname = spn.pn_path;
#else /* !illumos */ #else /* !illumos */
if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_ZFS))
return (SET_ERROR(EPERM));
if (vfs_getopt(vfsp->mnt_optnew, "from", (void **)&osname, NULL)) if (vfs_getopt(vfsp->mnt_optnew, "from", (void **)&osname, NULL))
return (SET_ERROR(EINVAL)); return (SET_ERROR(EINVAL));

View File

@ -1652,7 +1652,7 @@ linprocfs_uninit(PFS_INIT_ARGS)
return (0); return (0);
} }
PSEUDOFS(linprocfs, 1, PR_ALLOW_MOUNT_LINPROCFS); PSEUDOFS(linprocfs, 1, VFCF_JAIL);
#if defined(__amd64__) #if defined(__amd64__)
MODULE_DEPEND(linprocfs, linux_common, 1, 1, 1); MODULE_DEPEND(linprocfs, linux_common, 1, 1, 1);
#else #else

View File

@ -556,7 +556,7 @@ linsysfs_uninit(PFS_INIT_ARGS)
return (0); return (0);
} }
PSEUDOFS(linsysfs, 1, PR_ALLOW_MOUNT_LINSYSFS); PSEUDOFS(linsysfs, 1, VFCF_JAIL);
#if defined(__amd64__) #if defined(__amd64__)
MODULE_DEPEND(linsysfs, linux_common, 1, 1, 1); MODULE_DEPEND(linsysfs, linux_common, 1, 1, 1);
#else #else

View File

@ -83,9 +83,6 @@ devfs_mount(struct mount *mp)
if (mp->mnt_flag & MNT_ROOTFS) if (mp->mnt_flag & MNT_ROOTFS)
return (EOPNOTSUPP); return (EOPNOTSUPP);
if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_DEVFS))
return (EPERM);
rsnum = 0; rsnum = 0;
injail = jailed(td->td_ucred); injail = jailed(td->td_ucred);

View File

@ -81,13 +81,9 @@ static int
fdesc_mount(struct mount *mp) fdesc_mount(struct mount *mp)
{ {
struct fdescmount *fmp; struct fdescmount *fmp;
struct thread *td = curthread;
struct vnode *rvp; struct vnode *rvp;
int error; int error;
if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_FDESCFS))
return (EPERM);
/* /*
* Update is a no-op * Update is a no-op
*/ */

View File

@ -78,15 +78,12 @@ nullfs_mount(struct mount *mp)
struct vnode *lowerrootvp, *vp; struct vnode *lowerrootvp, *vp;
struct vnode *nullm_rootvp; struct vnode *nullm_rootvp;
struct null_mount *xmp; struct null_mount *xmp;
struct thread *td = curthread;
char *target; char *target;
int isvnunlocked = 0, len; int isvnunlocked = 0, len;
struct nameidata nd, *ndp = &nd; struct nameidata nd, *ndp = &nd;
NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp); NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp);
if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_NULLFS))
return (EPERM);
if (mp->mnt_flag & MNT_ROOTFS) if (mp->mnt_flag & MNT_ROOTFS)
return (EOPNOTSUPP); return (EOPNOTSUPP);

View File

@ -215,4 +215,4 @@ procfs_uninit(PFS_INIT_ARGS)
return (0); return (0);
} }
PSEUDOFS(procfs, 1, PR_ALLOW_MOUNT_PROCFS); PSEUDOFS(procfs, 1, VFCF_JAIL);

View File

@ -272,7 +272,7 @@ int pfs_destroy (struct pfs_node *pn);
/* /*
* Now for some initialization magic... * Now for some initialization magic...
*/ */
#define PSEUDOFS(name, version, jflag) \ #define PSEUDOFS(name, version, flags) \
\ \
static struct pfs_info name##_info = { \ static struct pfs_info name##_info = { \
#name, \ #name, \
@ -282,8 +282,6 @@ static struct pfs_info name##_info = { \
\ \
static int \ static int \
_##name##_mount(struct mount *mp) { \ _##name##_mount(struct mount *mp) { \
if (jflag && !prison_allow(curthread->td_ucred, jflag)) \
return (EPERM); \
return (pfs_mount(&name##_info, mp)); \ return (pfs_mount(&name##_info, mp)); \
} \ } \
\ \
@ -306,7 +304,7 @@ static struct vfsops name##_vfsops = { \
.vfs_uninit = _##name##_uninit, \ .vfs_uninit = _##name##_uninit, \
.vfs_unmount = pfs_unmount, \ .vfs_unmount = pfs_unmount, \
}; \ }; \
VFS_SET(name##_vfsops, name, VFCF_SYNTHETIC | (jflag ? VFCF_JAIL : 0)); \ VFS_SET(name##_vfsops, name, VFCF_SYNTHETIC | flags); \
MODULE_VERSION(name, version); \ MODULE_VERSION(name, version); \
MODULE_DEPEND(name, pseudofs, 1, 1, 1); MODULE_DEPEND(name, pseudofs, 1, 1, 1);

View File

@ -141,7 +141,6 @@ tmpfs_mount(struct mount *mp)
sizeof(struct tmpfs_dirent) + sizeof(struct tmpfs_node)); sizeof(struct tmpfs_dirent) + sizeof(struct tmpfs_node));
struct tmpfs_mount *tmp; struct tmpfs_mount *tmp;
struct tmpfs_node *root; struct tmpfs_node *root;
struct thread *td = curthread;
int error; int error;
bool nonc; bool nonc;
/* Size counters. */ /* Size counters. */
@ -155,9 +154,6 @@ tmpfs_mount(struct mount *mp)
struct vattr va; struct vattr va;
if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_TMPFS))
return (EPERM);
if (vfs_filteropt(mp->mnt_optnew, tmpfs_opts)) if (vfs_filteropt(mp->mnt_optnew, tmpfs_opts))
return (EINVAL); return (EINVAL);

View File

@ -111,7 +111,7 @@ struct prison prison0 = {
#else #else
.pr_flags = PR_HOST|_PR_IP_SADDRSEL, .pr_flags = PR_HOST|_PR_IP_SADDRSEL,
#endif #endif
.pr_allow = PR_ALLOW_ALL, .pr_allow = PR_ALLOW_ALL_STATIC,
}; };
MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF); MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF);
@ -181,7 +181,8 @@ static struct jailsys_flags pr_flag_jailsys[] = {
}; };
const size_t pr_flag_jailsys_size = sizeof(pr_flag_jailsys); const size_t pr_flag_jailsys_size = sizeof(pr_flag_jailsys);
static struct bool_flags pr_flag_allow[] = { /* Make this array full-size so dynamic parameters can be added. */
static struct bool_flags pr_flag_allow[NBBY * NBPW] = {
{"allow.set_hostname", "allow.noset_hostname", PR_ALLOW_SET_HOSTNAME}, {"allow.set_hostname", "allow.noset_hostname", PR_ALLOW_SET_HOSTNAME},
{"allow.sysvipc", "allow.nosysvipc", PR_ALLOW_SYSVIPC}, {"allow.sysvipc", "allow.nosysvipc", PR_ALLOW_SYSVIPC},
{"allow.raw_sockets", "allow.noraw_sockets", PR_ALLOW_RAW_SOCKETS}, {"allow.raw_sockets", "allow.noraw_sockets", PR_ALLOW_RAW_SOCKETS},
@ -189,17 +190,6 @@ static struct bool_flags pr_flag_allow[] = {
{"allow.mount", "allow.nomount", PR_ALLOW_MOUNT}, {"allow.mount", "allow.nomount", PR_ALLOW_MOUNT},
{"allow.quotas", "allow.noquotas", PR_ALLOW_QUOTAS}, {"allow.quotas", "allow.noquotas", PR_ALLOW_QUOTAS},
{"allow.socket_af", "allow.nosocket_af", PR_ALLOW_SOCKET_AF}, {"allow.socket_af", "allow.nosocket_af", PR_ALLOW_SOCKET_AF},
{"allow.mount.devfs", "allow.mount.nodevfs", PR_ALLOW_MOUNT_DEVFS},
{"allow.mount.nullfs", "allow.mount.nonullfs", PR_ALLOW_MOUNT_NULLFS},
{"allow.mount.zfs", "allow.mount.nozfs", PR_ALLOW_MOUNT_ZFS},
{"allow.mount.procfs", "allow.mount.noprocfs", PR_ALLOW_MOUNT_PROCFS},
{"allow.mount.tmpfs", "allow.mount.notmpfs", PR_ALLOW_MOUNT_TMPFS},
{"allow.mount.fdescfs", "allow.mount.nofdescfs",
PR_ALLOW_MOUNT_FDESCFS},
{"allow.mount.linprocfs", "allow.mount.nolinprocfs",
PR_ALLOW_MOUNT_LINPROCFS},
{"allow.mount.linsysfs", "allow.mount.nolinsysfs",
PR_ALLOW_MOUNT_LINSYSFS},
{"allow.reserved_ports", "allow.noreserved_ports", {"allow.reserved_ports", "allow.noreserved_ports",
PR_ALLOW_RESERVED_PORTS}, PR_ALLOW_RESERVED_PORTS},
}; };
@ -318,7 +308,8 @@ kern_jail(struct thread *td, struct jail *j)
/* Set permissions for top-level jails from sysctls. */ /* Set permissions for top-level jails from sysctls. */
if (!jailed(td->td_ucred)) { if (!jailed(td->td_ucred)) {
for (bf = pr_flag_allow; for (bf = pr_flag_allow;
bf < pr_flag_allow + nitems(pr_flag_allow); bf < pr_flag_allow + nitems(pr_flag_allow) &&
bf->flag != 0;
bf++) { bf++) {
optiov[opt.uio_iovcnt].iov_base = __DECONST(char *, optiov[opt.uio_iovcnt].iov_base = __DECONST(char *,
(jail_default_allow & bf->flag) (jail_default_allow & bf->flag)
@ -654,7 +645,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
pr_allow = ch_allow = 0; pr_allow = ch_allow = 0;
for (bf = pr_flag_allow; for (bf = pr_flag_allow;
bf < pr_flag_allow + nitems(pr_flag_allow); bf < pr_flag_allow + nitems(pr_flag_allow) && bf->flag != 0;
bf++) { bf++) {
vfs_flagopt(opts, bf->name, &pr_allow, bf->flag); vfs_flagopt(opts, bf->name, &pr_allow, bf->flag);
vfs_flagopt(opts, bf->noname, &ch_allow, bf->flag); vfs_flagopt(opts, bf->noname, &ch_allow, bf->flag);
@ -2115,7 +2106,7 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
goto done_deref; goto done_deref;
} }
for (bf = pr_flag_allow; for (bf = pr_flag_allow;
bf < pr_flag_allow + nitems(pr_flag_allow); bf < pr_flag_allow + nitems(pr_flag_allow) && bf->flag != 0;
bf++) { bf++) {
i = (pr->pr_allow & bf->flag) ? 1 : 0; i = (pr->pr_allow & bf->flag) ? 1 : 0;
error = vfs_setopt(opts, bf->name, &i, sizeof(i)); error = vfs_setopt(opts, bf->name, &i, sizeof(i));
@ -3615,38 +3606,6 @@ SYSCTL_PROC(_security_jail, OID_AUTO, mount_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT, sysctl_jail_default_allow, "I", NULL, PR_ALLOW_MOUNT, sysctl_jail_default_allow, "I",
"Processes in jail can mount/unmount jail-friendly file systems (deprecated)"); "Processes in jail can mount/unmount jail-friendly file systems (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_devfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_DEVFS, sysctl_jail_default_allow, "I",
"Processes in jail can mount the devfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_fdescfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_FDESCFS, sysctl_jail_default_allow, "I",
"Processes in jail can mount the fdescfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_nullfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_NULLFS, sysctl_jail_default_allow, "I",
"Processes in jail can mount the nullfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_procfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_PROCFS, sysctl_jail_default_allow, "I",
"Processes in jail can mount the procfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_linprocfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_LINPROCFS, sysctl_jail_default_allow, "I",
"Processes in jail can mount the linprocfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_linsysfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_LINSYSFS, sysctl_jail_default_allow, "I",
"Processes in jail can mount the linsysfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_tmpfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_TMPFS, sysctl_jail_default_allow, "I",
"Processes in jail can mount the tmpfs file system (deprecated)");
SYSCTL_PROC(_security_jail, OID_AUTO, mount_zfs_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT_ZFS, sysctl_jail_default_allow, "I",
"Processes in jail can mount the zfs file system (deprecated)");
static int static int
sysctl_jail_default_level(SYSCTL_HANDLER_ARGS) sysctl_jail_default_level(SYSCTL_HANDLER_ARGS)
@ -3799,22 +3758,110 @@ SYSCTL_JAIL_PARAM(_allow, reserved_ports, CTLTYPE_INT | CTLFLAG_RW,
SYSCTL_JAIL_PARAM_SUBNODE(allow, mount, "Jail mount/unmount permission flags"); SYSCTL_JAIL_PARAM_SUBNODE(allow, mount, "Jail mount/unmount permission flags");
SYSCTL_JAIL_PARAM(_allow_mount, , CTLTYPE_INT | CTLFLAG_RW, SYSCTL_JAIL_PARAM(_allow_mount, , CTLTYPE_INT | CTLFLAG_RW,
"B", "Jail may mount/unmount jail-friendly file systems in general"); "B", "Jail may mount/unmount jail-friendly file systems in general");
SYSCTL_JAIL_PARAM(_allow_mount, devfs, CTLTYPE_INT | CTLFLAG_RW,
"B", "Jail may mount the devfs file system"); /*
SYSCTL_JAIL_PARAM(_allow_mount, fdescfs, CTLTYPE_INT | CTLFLAG_RW, * The VFS system will register jail-aware filesystems here. They each get
"B", "Jail may mount the fdescfs file system"); * a parameter allow.mount.xxxfs and a flag to check when a jailed user
SYSCTL_JAIL_PARAM(_allow_mount, nullfs, CTLTYPE_INT | CTLFLAG_RW, * attempts to mount.
"B", "Jail may mount the nullfs file system"); */
SYSCTL_JAIL_PARAM(_allow_mount, procfs, CTLTYPE_INT | CTLFLAG_RW, void
"B", "Jail may mount the procfs file system"); prison_add_vfs(struct vfsconf *vfsp)
SYSCTL_JAIL_PARAM(_allow_mount, linprocfs, CTLTYPE_INT | CTLFLAG_RW, {
"B", "Jail may mount the linprocfs file system"); char *allow_name, *allow_noname, *mount_allowed;
SYSCTL_JAIL_PARAM(_allow_mount, linsysfs, CTLTYPE_INT | CTLFLAG_RW, struct bool_flags *bf;
"B", "Jail may mount the linsysfs file system"); #ifndef NO_SYSCTL_DESCR
SYSCTL_JAIL_PARAM(_allow_mount, tmpfs, CTLTYPE_INT | CTLFLAG_RW, char *descr;
"B", "Jail may mount the tmpfs file system"); #endif
SYSCTL_JAIL_PARAM(_allow_mount, zfs, CTLTYPE_INT | CTLFLAG_RW, unsigned allow_flag;
"B", "Jail may mount the zfs file system");
if (asprintf(&allow_name, M_PRISON, "allow.mount.%s", vfsp->vfc_name) <
0 || asprintf(&allow_noname, M_PRISON, "allow.mount.no%s",
vfsp->vfc_name) < 0) {
free(allow_name, M_PRISON);
return;
}
/*
* See if this parameter has already beed added, i.e. if the filesystem
* was previously loaded/unloaded.
*/
mtx_lock(&prison0.pr_mtx);
for (bf = pr_flag_allow;
bf < pr_flag_allow + nitems(pr_flag_allow) && bf->flag != 0;
bf++) {
if (strcmp(bf->name, allow_name) == 0) {
vfsp->vfc_prison_flag = bf->flag;
goto no_add;
}
}
/*
* Find a free bit in prison0's pr_allow, failing if there are none
* (which shouldn't happen as long as we keep track of how many
* filesystems are jail-aware).
*/
for (allow_flag = 1;; allow_flag <<= 1) {
if (allow_flag == 0)
goto no_add;
if ((prison0.pr_allow & allow_flag) == 0)
break;
}
/*
* Note the parameter in the next open slot in pr_flag_allow.
* Set the flag last so code that checks pr_flag_allow can do so
* without locking.
*/
for (bf = pr_flag_allow; bf->flag != 0; bf++)
if (bf == pr_flag_allow + nitems(pr_flag_allow)) {
/* This should never happen, but is not fatal. */
goto no_add;
}
prison0.pr_allow |= allow_flag;
bf->name = allow_name;
bf->noname = allow_noname;
bf->flag = allow_flag;
vfsp->vfc_prison_flag = allow_flag;
mtx_unlock(&prison0.pr_mtx);
/*
* Create sysctls for the paramter, and the back-compat global
* permission.
*/
#ifndef NO_SYSCTL_DESCR
(void)asprintf(&descr, M_TEMP, "Jail may mount the %s file system",
vfsp->vfc_name);
#endif
(void)SYSCTL_ADD_PROC(NULL,
SYSCTL_CHILDREN(&sysctl___security_jail_param_allow_mount),
OID_AUTO, vfsp->vfc_name, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, 0, sysctl_jail_param, "B", descr);
#ifndef NO_SYSCTL_DESCR
free(descr, M_TEMP);
#endif
if (asprintf(&mount_allowed, M_TEMP, "mount_%s_allowed",
vfsp->vfc_name) >= 0) {
#ifndef NO_SYSCTL_DESCR
(void)asprintf(&descr, M_TEMP,
"Processes in jail can mount the %s file system (deprecated)",
vfsp->vfc_name);
#endif
(void)SYSCTL_ADD_PROC(NULL,
SYSCTL_CHILDREN(&sysctl___security_jail), OID_AUTO,
mount_allowed, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, allow_flag, sysctl_jail_default_allow, "I", descr);
#ifndef NO_SYSCTL_DESCR
free(descr, M_TEMP);
#endif
free(mount_allowed, M_TEMP);
}
return;
no_add:
mtx_unlock(&prison0.pr_mtx);
free(allow_name, M_PRISON);
free(allow_noname, M_PRISON);
}
#ifdef RACCT #ifdef RACCT
void void
@ -4050,7 +4097,7 @@ db_show_prison(struct prison *pr)
} }
db_printf(" allow = 0x%x", pr->pr_allow); db_printf(" allow = 0x%x", pr->pr_allow);
for (bf = pr_flag_allow; for (bf = pr_flag_allow;
bf < pr_flag_allow + nitems(pr_flag_allow); bf < pr_flag_allow + nitems(pr_flag_allow) && bf->flag != 0;
bf++) bf++)
if (pr->pr_allow & bf->flag) if (pr->pr_allow & bf->flag)
db_printf(" %s", bf->name); db_printf(" %s", bf->name);

View File

@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/fnv_hash.h> #include <sys/fnv_hash.h>
#include <sys/jail.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/linker.h> #include <sys/linker.h>
#include <sys/mount.h> #include <sys/mount.h>
@ -277,6 +278,9 @@ vfs_register(struct vfsconf *vfc)
if (vfsops->vfs_sysctl == NULL) if (vfsops->vfs_sysctl == NULL)
vfsops->vfs_sysctl = vfs_stdsysctl; vfsops->vfs_sysctl = vfs_stdsysctl;
if (vfc->vfc_flags & VFCF_JAIL)
prison_add_vfs(vfc);
/* /*
* Call init function for this VFS... * Call init function for this VFS...
*/ */

View File

@ -842,6 +842,16 @@ vfs_domount_first(
ASSERT_VOP_ELOCKED(vp, __func__); ASSERT_VOP_ELOCKED(vp, __func__);
KASSERT((fsflags & MNT_UPDATE) == 0, ("MNT_UPDATE shouldn't be here")); KASSERT((fsflags & MNT_UPDATE) == 0, ("MNT_UPDATE shouldn't be here"));
/*
* If the jail of the calling thread lacks permission for this type of
* file system, deny immediately.
*/
if (jailed(td->td_ucred) && !prison_allow(td->td_ucred,
vfsp->vfc_prison_flag)) {
vput(vp);
return (EPERM);
}
/* /*
* If the user is not root, ensure that they own the directory * If the user is not root, ensure that they own the directory
* onto which we are attempting to mount. * onto which we are attempting to mount.
@ -1149,8 +1159,6 @@ vfs_domount(
vfsp = vfs_byname_kld(fstype, td, &error); vfsp = vfs_byname_kld(fstype, td, &error);
if (vfsp == NULL) if (vfsp == NULL)
return (ENODEV); return (ENODEV);
if (jailed(td->td_ucred) && !(vfsp->vfc_flags & VFCF_JAIL))
return (EPERM);
} }
/* /*

View File

@ -683,19 +683,21 @@ vfs_suser(struct mount *mp, struct thread *td)
{ {
int error; int error;
if (jailed(td->td_ucred)) {
/* /*
* If the thread is jailed, but this is not a jail-friendly file * If the jail of the calling thread lacks permission for
* system, deny immediately. * this type of file system, deny immediately.
*/ */
if (!(mp->mnt_vfc->vfc_flags & VFCF_JAIL) && jailed(td->td_ucred)) if (!prison_allow(td->td_ucred, mp->mnt_vfc->vfc_prison_flag))
return (EPERM); return (EPERM);
/* /*
* If the file system was mounted outside the jail of the calling * If the file system was mounted outside the jail of the
* thread, deny immediately. * calling thread, deny immediately.
*/ */
if (prison_check(td->td_ucred, mp->mnt_cred) != 0) if (prison_check(td->td_ucred, mp->mnt_cred) != 0)
return (EPERM); return (EPERM);
}
/* /*
* If file system supports delegated administration, we don't check * If file system supports delegated administration, we don't check

View File

@ -216,7 +216,10 @@ struct prison_racct {
#define PR_IP6 0x04000000 /* IPv6 restricted or disabled */ #define PR_IP6 0x04000000 /* IPv6 restricted or disabled */
/* by this jail or an ancestor */ /* by this jail or an ancestor */
/* Flags for pr_allow */ /*
* Flags for pr_allow
* Bits not noted here may be used for dynamic allow.mount.xxxfs.
*/
#define PR_ALLOW_SET_HOSTNAME 0x00000001 #define PR_ALLOW_SET_HOSTNAME 0x00000001
#define PR_ALLOW_SYSVIPC 0x00000002 #define PR_ALLOW_SYSVIPC 0x00000002
#define PR_ALLOW_RAW_SOCKETS 0x00000004 #define PR_ALLOW_RAW_SOCKETS 0x00000004
@ -224,17 +227,9 @@ struct prison_racct {
#define PR_ALLOW_MOUNT 0x00000010 #define PR_ALLOW_MOUNT 0x00000010
#define PR_ALLOW_QUOTAS 0x00000020 #define PR_ALLOW_QUOTAS 0x00000020
#define PR_ALLOW_SOCKET_AF 0x00000040 #define PR_ALLOW_SOCKET_AF 0x00000040
#define PR_ALLOW_MOUNT_DEVFS 0x00000080
#define PR_ALLOW_MOUNT_NULLFS 0x00000100
#define PR_ALLOW_MOUNT_ZFS 0x00000200
#define PR_ALLOW_MOUNT_PROCFS 0x00000400
#define PR_ALLOW_MOUNT_TMPFS 0x00000800
#define PR_ALLOW_MOUNT_FDESCFS 0x00001000
#define PR_ALLOW_MOUNT_LINPROCFS 0x00002000
#define PR_ALLOW_MOUNT_LINSYSFS 0x00004000
#define PR_ALLOW_RESERVED_PORTS 0x00008000 #define PR_ALLOW_RESERVED_PORTS 0x00008000
#define PR_ALLOW_KMEM_ACCESS 0x00010000 /* reserved, not used yet */ #define PR_ALLOW_KMEM_ACCESS 0x00010000 /* reserved, not used yet */
#define PR_ALLOW_ALL 0x0001ffff #define PR_ALLOW_ALL_STATIC 0x0001807f
/* /*
* OSD methods * OSD methods
@ -364,6 +359,7 @@ struct ucred;
struct mount; struct mount;
struct sockaddr; struct sockaddr;
struct statfs; struct statfs;
struct vfsconf;
int jailed(struct ucred *cred); int jailed(struct ucred *cred);
int jailed_without_vnet(struct ucred *); int jailed_without_vnet(struct ucred *);
void getcredhostname(struct ucred *, char *, size_t); void getcredhostname(struct ucred *, char *, size_t);
@ -413,6 +409,7 @@ int prison_if(struct ucred *cred, struct sockaddr *sa);
char *prison_name(struct prison *, struct prison *); char *prison_name(struct prison *, struct prison *);
int prison_priv_check(struct ucred *cred, int priv); int prison_priv_check(struct ucred *cred, int priv);
int sysctl_jail_param(SYSCTL_HANDLER_ARGS); int sysctl_jail_param(SYSCTL_HANDLER_ARGS);
void prison_add_vfs(struct vfsconf *vfsp);
void prison_racct_foreach(void (*callback)(struct racct *racct, void prison_racct_foreach(void (*callback)(struct racct *racct,
void *arg2, void *arg3), void (*pre)(void), void (*post)(void), void *arg2, void *arg3), void (*pre)(void), void (*post)(void),
void *arg2, void *arg3); void *arg2, void *arg3);

View File

@ -516,6 +516,7 @@ struct vfsconf {
int vfc_typenum; /* historic filesystem type number */ int vfc_typenum; /* historic filesystem type number */
int vfc_refcount; /* number mounted of this type */ int vfc_refcount; /* number mounted of this type */
int vfc_flags; /* permanent flags */ int vfc_flags; /* permanent flags */
int vfc_prison_flag; /* prison allow.mount.* flag */
struct vfsoptdecl *vfc_opts; /* mount options */ struct vfsoptdecl *vfc_opts; /* mount options */
TAILQ_ENTRY(vfsconf) vfc_list; /* list of vfscons */ TAILQ_ENTRY(vfsconf) vfc_list; /* list of vfscons */
}; };
@ -851,7 +852,8 @@ vfs_statfs_t __vfs_statfs;
*/ */
#define VFS_VERSION_00 0x19660120 #define VFS_VERSION_00 0x19660120
#define VFS_VERSION_01 0x20121030 #define VFS_VERSION_01 0x20121030
#define VFS_VERSION VFS_VERSION_01 #define VFS_VERSION_02 0x20180504
#define VFS_VERSION VFS_VERSION_02
#define VFS_SET(vfsops, fsname, flags) \ #define VFS_SET(vfsops, fsname, flags) \
static struct vfsconf fsname ## _vfsconf = { \ static struct vfsconf fsname ## _vfsconf = { \

View File

@ -25,7 +25,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd June 5, 2017 .Dd May 4, 2018
.Dt JAIL 8 .Dt JAIL 8
.Os .Os
.Sh NAME .Sh NAME
@ -545,6 +545,33 @@ is set to a value lower than 2.
The devfs ruleset should be restricted from the default by using the The devfs ruleset should be restricted from the default by using the
.Va devfs_ruleset .Va devfs_ruleset
option. option.
.It Va allow.quotas
The jail root may administer quotas on the jail's filesystem(s).
This includes filesystems that the jail may share with other jails or
with non-jailed parts of the system.
.It Va allow.socket_af
Sockets within a jail are normally restricted to IPv4, IPv6, local
(UNIX), and route. This allows access to other protocol stacks that
have not had jail functionality added to them.
.It Va allow.reserved_ports
The jail root may bind to ports lower than 1024.
.El
.El
.Pp
Kernel modules may add their own parameters, which only exist when the
module is loaded.
These are typically headed under a parameter named after the module,
with values of
.Dq inherit
to give the jail full use of the module,
.Dq new
to encapsulate the jail in some module-specific way,
and
.Dq disable
to make the module unavailable to the jail.
There also may be other parameters to define jail behavior within the module.
Module-specific parameters include:
.Bl -tag -width indent
.It Va allow.mount.fdescfs .It Va allow.mount.fdescfs
privileged users inside the jail will be able to mount and unmount the privileged users inside the jail will be able to mount and unmount the
fdescfs file system. fdescfs file system.
@ -605,33 +632,6 @@ See
.Xr zfs 8 .Xr zfs 8
for information on how to configure the ZFS filesystem to operate from for information on how to configure the ZFS filesystem to operate from
within a jail. within a jail.
.It Va allow.quotas
The jail root may administer quotas on the jail's filesystem(s).
This includes filesystems that the jail may share with other jails or
with non-jailed parts of the system.
.It Va allow.socket_af
Sockets within a jail are normally restricted to IPv4, IPv6, local
(UNIX), and route. This allows access to other protocol stacks that
have not had jail functionality added to them.
.It Va allow.reserved_ports
The jail root may bind to ports lower than 1024.
.El
.El
.Pp
Kernel modules may add their own parameters, which only exist when the
module is loaded.
These are typically headed under a parameter named after the module,
with values of
.Dq inherit
to give the jail full use of the module,
.Dq new
to encapsulate the jail in some module-specific way,
and
.Dq disable
to make the module unavailable to the jail.
There also may be other parameters to define jail behavior within the module.
Module-specific parameters include:
.Bl -tag -width indent
.It Va linux .It Va linux
Determine how a jail's Linux emulation environment appears. Determine how a jail's Linux emulation environment appears.
A value of A value of