summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2012-02-23 18:51:24 +0000
committerMartin Matuska <mm@FreeBSD.org>2012-02-23 18:51:24 +0000
commitbf3db8aa6581ef04796d719aa54df39e3915617e (patch)
tree9a2a88cb10722db25dcb45d3c1ae2c34dec88614
parent0a50333302b6aff8d8a59daf0b2ba3d72718e51b (diff)
Notes
-rw-r--r--sys/fs/devfs/devfs_vfsops.c30
-rw-r--r--sys/fs/nullfs/null_vfsops.c5
-rw-r--r--sys/kern/kern_jail.c37
-rw-r--r--sys/sys/jail.h6
-rw-r--r--usr.sbin/jail/jail.836
5 files changed, 79 insertions, 35 deletions
diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c
index 96069747e39e3..f73b229efa814 100644
--- a/sys/fs/devfs/devfs_vfsops.c
+++ b/sys/fs/devfs/devfs_vfsops.c
@@ -71,7 +71,7 @@ devfs_mount(struct mount *mp)
struct devfs_mount *fmp;
struct vnode *rvp;
struct thread *td = curthread;
- int rsnum;
+ int injail, rsnum;
if (devfs_unr == NULL)
devfs_unr = new_unrhdr(0, INT_MAX, NULL);
@@ -81,7 +81,11 @@ devfs_mount(struct mount *mp)
if (mp->mnt_flag & MNT_ROOTFS)
return (EOPNOTSUPP);
+ if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_DEVFS))
+ return (EPERM);
+
rsnum = 0;
+ injail = jailed(td->td_ucred);
if (mp->mnt_optnew != NULL) {
if (vfs_filteropt(mp->mnt_optnew, devfs_opts))
@@ -89,24 +93,20 @@ devfs_mount(struct mount *mp)
if (vfs_getopt(mp->mnt_optnew, "ruleset", NULL, NULL) == 0 &&
(vfs_scanopt(mp->mnt_optnew, "ruleset", "%d",
- &rsnum) != 1 || rsnum < 0 || rsnum > 65535))
- error = EINVAL;
- }
+ &rsnum) != 1 || rsnum < 0 || rsnum > 65535)) {
+ vfs_mount_error(mp, "%s",
+ "invalid ruleset specification");
+ return (EINVAL);
+ }
- /* jails enforce their ruleset, prison0 has no restrictions */
- if (td->td_ucred->cr_prison->pr_devfs_rsnum != 0) {
- rsnum = td->td_ucred->cr_prison->pr_devfs_rsnum;
- if (rsnum == -1)
+ if (injail && rsnum != 0 &&
+ rsnum != td->td_ucred->cr_prison->pr_devfs_rsnum)
return (EPERM);
- /* check rsnum for sanity, devfs_rsnum is uint16_t */
- if (rsnum < 0 || rsnum > 65535)
- error = EINVAL;
}
- if (error) {
- vfs_mount_error(mp, "%s", "invalid ruleset specification");
- return (error);
- }
+ /* jails enforce their ruleset */
+ if (injail)
+ rsnum = td->td_ucred->cr_prison->pr_devfs_rsnum;
if (mp->mnt_flag & MNT_UPDATE) {
if (rsnum != 0) {
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index 97874b3e0deaa..b422077f0cf03 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -50,6 +50,7 @@
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/vnode.h>
+#include <sys/jail.h>
#include <fs/nullfs/null.h>
@@ -75,12 +76,16 @@ nullfs_mount(struct mount *mp)
struct vnode *lowerrootvp, *vp;
struct vnode *nullm_rootvp;
struct null_mount *xmp;
+ struct thread *td = curthread;
char *target;
int isvnunlocked = 0, len;
struct nameidata nd, *ndp = &nd;
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)
return (EOPNOTSUPP);
/*
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index b800eaa29089b..3ba565b558929 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -201,6 +201,8 @@ static char *pr_allow_names[] = {
"allow.mount",
"allow.quotas",
"allow.socket_af",
+ "allow.mount.devfs",
+ "allow.mount.nullfs",
};
const size_t pr_allow_names_size = sizeof(pr_allow_names);
@@ -212,12 +214,14 @@ static char *pr_allow_nonames[] = {
"allow.nomount",
"allow.noquotas",
"allow.nosocket_af",
+ "allow.mount.nodevfs",
+ "allow.mount.nonullfs",
};
const size_t pr_allow_nonames_size = sizeof(pr_allow_nonames);
#define JAIL_DEFAULT_ALLOW PR_ALLOW_SET_HOSTNAME
#define JAIL_DEFAULT_ENFORCE_STATFS 2
-#define JAIL_DEFAULT_DEVFS_RSNUM -1
+#define JAIL_DEFAULT_DEVFS_RSNUM 0
static unsigned jail_default_allow = JAIL_DEFAULT_ALLOW;
static int jail_default_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS;
static int jail_default_devfs_rsnum = JAIL_DEFAULT_DEVFS_RSNUM;
@@ -1279,7 +1283,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
pr->pr_securelevel = ppr->pr_securelevel;
pr->pr_allow = JAIL_DEFAULT_ALLOW & ppr->pr_allow;
pr->pr_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS;
- pr->pr_devfs_rsnum = JAIL_DEFAULT_DEVFS_RSNUM;
+ pr->pr_devfs_rsnum = ppr->pr_devfs_rsnum;
LIST_INIT(&pr->pr_children);
mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF | MTX_DUPOK);
@@ -1361,21 +1365,19 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
if (gotrsnum) {
/*
* devfs_rsnum is a uint16_t
- * value of -1 disables devfs mounts
*/
- if (rsnum < -1 || rsnum > 65535) {
+ if (rsnum < 0 || rsnum > 65535) {
error = EINVAL;
goto done_deref_locked;
}
/*
- * Nested jails may inherit parent's devfs ruleset
- * or disable devfs
+ * Nested jails always inherit parent's devfs ruleset
*/
if (jailed(td->td_ucred)) {
if (rsnum > 0 && rsnum != ppr->pr_devfs_rsnum) {
error = EPERM;
goto done_deref_locked;
- } else if (rsnum == 0)
+ } else
rsnum = ppr->pr_devfs_rsnum;
}
}
@@ -1623,8 +1625,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
pr->pr_devfs_rsnum = rsnum;
/* Pass this restriction on to the children. */
FOREACH_PRISON_DESCENDANT_LOCKED(pr, tpr, descend)
- if (tpr->pr_devfs_rsnum != -1)
- tpr->pr_devfs_rsnum = rsnum;
+ tpr->pr_devfs_rsnum = rsnum;
}
if (name != NULL) {
if (ppr == &prison0)
@@ -4195,6 +4196,14 @@ SYSCTL_PROC(_security_jail, OID_AUTO, mount_allowed,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
NULL, PR_ALLOW_MOUNT, sysctl_jail_default_allow, "I",
"Processes in jail can mount/unmount jail-friendly file systems");
+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/unmount the devfs file system");
+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/unmount the nullfs file system");
static int
sysctl_jail_default_level(SYSCTL_HANDLER_ARGS)
@@ -4329,13 +4338,19 @@ SYSCTL_JAIL_PARAM(_allow, raw_sockets, CTLTYPE_INT | CTLFLAG_RW,
"B", "Jail may create raw sockets");
SYSCTL_JAIL_PARAM(_allow, chflags, CTLTYPE_INT | CTLFLAG_RW,
"B", "Jail may alter system file flags");
-SYSCTL_JAIL_PARAM(_allow, mount, CTLTYPE_INT | CTLFLAG_RW,
- "B", "Jail may mount/unmount jail-friendly file systems");
SYSCTL_JAIL_PARAM(_allow, quotas, CTLTYPE_INT | CTLFLAG_RW,
"B", "Jail may set file quotas");
SYSCTL_JAIL_PARAM(_allow, socket_af, CTLTYPE_INT | CTLFLAG_RW,
"B", "Jail may create sockets other than just UNIX/IPv4/IPv6/route");
+SYSCTL_JAIL_PARAM_SUBNODE(allow, mount, "Jail mount/unmount permission flags");
+SYSCTL_JAIL_PARAM(_allow_mount, , CTLTYPE_INT | CTLFLAG_RW,
+ "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/unmount the devfs file system");
+SYSCTL_JAIL_PARAM(_allow_mount, nullfs, CTLTYPE_INT | CTLFLAG_RW,
+ "B", "Jail may mount/unmount the nullfs file system");
+
void
prison_racct_foreach(void (*callback)(struct racct *racct,
void *arg2, void *arg3), void *arg2, void *arg3)
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
index 565efa86dccd9..7d87b84bc0d4b 100644
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -223,7 +223,9 @@ struct prison_racct {
#define PR_ALLOW_MOUNT 0x0010
#define PR_ALLOW_QUOTAS 0x0020
#define PR_ALLOW_SOCKET_AF 0x0040
-#define PR_ALLOW_ALL 0x007f
+#define PR_ALLOW_MOUNT_DEVFS 0x0080
+#define PR_ALLOW_MOUNT_NULLFS 0x0100
+#define PR_ALLOW_ALL 0x01ff
/*
* OSD methods
@@ -338,6 +340,8 @@ SYSCTL_DECL(_security_jail_param);
sysctl_jail_param, fmt, descr)
#define SYSCTL_JAIL_PARAM_NODE(module, descr) \
SYSCTL_NODE(_security_jail_param, OID_AUTO, module, 0, 0, descr)
+#define SYSCTL_JAIL_PARAM_SUBNODE(parent, module, descr) \
+ SYSCTL_NODE(_security_jail_param_##parent, OID_AUTO, module, 0, 0, descr)
#define SYSCTL_JAIL_PARAM_SYS_NODE(module, access, descr) \
SYSCTL_JAIL_PARAM_NODE(module, descr); \
SYSCTL_JAIL_PARAM(_##module, , CTLTYPE_INT | (access), "E,jailsys", \
diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8
index 5cd77fc705c3e..e1d3b2d2b79cf 100644
--- a/usr.sbin/jail/jail.8
+++ b/usr.sbin/jail/jail.8
@@ -34,7 +34,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 9, 2012
+.Dd February 23, 2012
.Dt JAIL 8
.Os
.Sh NAME
@@ -303,15 +303,16 @@ If the system securelevel is changed, any jail securelevels will be at
least as secure.
.It Va devfs_ruleset
The number of the devfs ruleset that is enforced for mounting devfs in
-this jail and its descendants. A value of zero means no ruleset is enforced
-or if set inside a jail for a descendant jail, the parent jails's devfs
-ruleset enforcement is inherited. A value of -1 (default) means mounting a
-devfs filesystem is not allowed. Mounting devfs inside a jail is possible
-only if the
+this jail. A value of zero (default) means no ruleset is enforced. Descendant
+jails inherit the parent jail's devfs ruleset enforcement. Mounting devfs
+inside a jail is possible only if the
.Va allow.mount
-permission is effective and
+and
+.Va allow.mount.devfs
+permissions are effective and
.Va enforce_statfs
-is set to a value lower than 2.
+is set to a value lower than 2. Devfs rules and rulesets cannot be viewed or
+modified from inside a jail.
.It Va children.max
The number of child jails allowed to be created by this jail (or by
other jails under this jail).
@@ -407,6 +408,25 @@ within a jail.
This permission is effective only if
.Va enforce_statfs
is set to a value lower than 2.
+.It Va allow.mount.devfs
+privileged users inside the jail will be able to mount and unmount the
+devfs file system.
+This permission is effective only together with
+.Va allow.mount
+and if
+.Va enforce_statfs
+is set to a value lower than 2. Please consider restricting the devfs ruleset
+with the
+.Va devfs_ruleset
+option.
+.It Va allow.mount.nullfs
+privileged users inside the jail will be able to mount and unmount the
+nullfs file system.
+This permission is effective only together with
+.Va allow.mount
+and if
+.Va enforce_statfs
+is set to a value lower than 2.
.It Va allow.quotas
The prison root may administer quotas on the jail's filesystem(s).
This includes filesystems that the jail may share with other jails or