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:
parent
d55f0e89c8
commit
0e5c6bd436
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=333263
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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...
|
||||||
*/
|
*/
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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 = { \
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user