svn commit: r232728 - in stable/9: lib/libjail share/man/man5 sys/cddl/contrib/opensolaris/uts/common/fs/zfs sys/compat/linprocfs sys/compat/linsysfs sys/fs/devfs sys/fs/nullfs sys/fs/procfs sys/fs...

Martin Matuska mm at FreeBSD.org
Fri Mar 9 16:17:47 UTC 2012


Author: mm
Date: Fri Mar  9 16:17:46 2012
New Revision: 232728
URL: http://svn.freebsd.org/changeset/base/232728

Log:
  Jail-mount MFC:	r231265,r231267,r231269,r232059,r232186,r232247,
  		r232278,r232307,r232342
  
  MFC r231265:
  Introduce the "ruleset=number" option for devfs(5) mounts.
  Add support for updating the devfs mount (currently only changing the
  ruleset number is supported).
  Check mnt_optnew with vfs_filteropt(9).
  
  This new option sets the specified ruleset number as the active ruleset
  of the new devfs mount and applies all its rules at mount time. If the
  specified ruleset doesn't exist, a new empty ruleset is created.
  
  MFC r231267 [1]:
  Add support for mounting devfs inside jails.
  
  A new jail(8) option "devfs_ruleset" defines the ruleset enforcement for
  mounting devfs inside jails. A value of -1 disables mounting devfs in
  jails, a value of zero means no restrictions. Nested jails can only
  have mounting devfs disabled or inherit parent's enforcement as jails are
  not allowed to view or manipulate devfs(8) rules.
  
  Utilizes new functions introduced in r231265.
  
  MFC r231269:
  Allow mounting nullfs(5) inside jails.
  
  This is now possible thanks to r230129.
  
  MFC r232059 [1]:
  To improve control over the use of mount(8) inside a jail(8), introduce
  a new jail parameter node with the following parameters:
  
  allow.mount.devfs:
  	allow mounting the devfs filesystem inside a jail
  
  allow.mount.nullfs:
  	allow mounting the nullfs filesystem inside a jail
  
  Both parameters are disabled by default (equals the behavior before
  devfs and nullfs in jails). Administrators have to explicitly allow
  mounting devfs and nullfs for each jail. The value "-1" of the
  devfs_ruleset parameter is removed in favor of the new allow setting.
  
  MFC r232186:
  Analogous to r232059, add a parameter for the ZFS file system:
  
  allow.mount.zfs:
  	allow mounting the zfs filesystem inside a jail
  
  This way the permssions for mounting all current VFCF_JAIL filesystems
  inside a jail are controlled wia allow.mount.* jail parameters.
  
  Update sysctl descriptions.
  Update jail(8) and zfs(8) manpages.
  
  MFC r232247:
  mdoc(7) stype - start new sentences on new line
  
  MFC r232278 [1]:
  Add procfs to jail-mountable filesystems.
  
  MFC r232291:
  Bump .Dd to reflect latest update
  
  MFC r232307:
  Add "export" to devfs_opts[] and return EOPNOTSUPP if called with it.
  Fixes mountd warnings.
  
  MFC r232342 (jamie) [2]:
  Handle the case where a boolean parameter is also a node.
  
  PR:	bin/165515 [2]
  Reviewed by:	jamie [1]

Modified:
  stable/9/lib/libjail/jail.c
  stable/9/share/man/man5/devfs.5
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
  stable/9/sys/compat/linprocfs/linprocfs.c
  stable/9/sys/compat/linsysfs/linsysfs.c
  stable/9/sys/fs/devfs/devfs.h
  stable/9/sys/fs/devfs/devfs_rule.c
  stable/9/sys/fs/devfs/devfs_vfsops.c
  stable/9/sys/fs/nullfs/null_vfsops.c
  stable/9/sys/fs/procfs/procfs.c
  stable/9/sys/fs/pseudofs/pseudofs.h
  stable/9/sys/kern/kern_jail.c
  stable/9/sys/sys/jail.h
  stable/9/sys/sys/param.h
  stable/9/usr.sbin/jail/jail.8
Directory Properties:
  stable/9/lib/libjail/   (props changed)
  stable/9/share/man/man5/   (props changed)
  stable/9/sys/   (props changed)
  stable/9/sys/cddl/contrib/opensolaris/   (props changed)
  stable/9/usr.sbin/jail/   (props changed)

Modified: stable/9/lib/libjail/jail.c
==============================================================================
--- stable/9/lib/libjail/jail.c	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/lib/libjail/jail.c	Fri Mar  9 16:17:46 2012	(r232728)
@@ -885,36 +885,20 @@ jailparam_type(struct jailparam *jp)
 		 * the "no" counterpart to a boolean.
 		 */
 		nname = nononame(jp->jp_name);
-		if (nname != NULL) {
-			snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", nname);
-			free(nname);
-			miblen = sizeof(mib) - 2 * sizeof(int);
-			if (sysctl(mib, 2, mib + 2, &miblen, desc.s,
-			    strlen(desc.s)) >= 0) {
-				mib[1] = 4;
-				desclen = sizeof(desc);
-				if (sysctl(mib, (miblen / sizeof(int)) + 2,
-				    &desc, &desclen, NULL, 0) < 0) {
-					snprintf(jail_errmsg,
-					    JAIL_ERRMSGLEN,
-					    "sysctl(0.4.%s): %s", desc.s,
-					    strerror(errno));
-					return (-1);
-				}
-				if ((desc.i & CTLTYPE) == CTLTYPE_INT &&
-				    desc.s[0] == 'B') {
-					jp->jp_ctltype = desc.i;
-					jp->jp_flags |= JP_NOBOOL;
-					jp->jp_valuelen = sizeof(int);
-					return (0);
-				}
-			}
+		if (nname == NULL) {
+		unknown_parameter:
+			snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+			    "unknown parameter: %s", jp->jp_name);
+			errno = ENOENT;
+			return (-1);
 		}
-	unknown_parameter:
-		snprintf(jail_errmsg, JAIL_ERRMSGLEN,
-		    "unknown parameter: %s", jp->jp_name);
-		errno = ENOENT;
-		return (-1);
+		snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", nname);
+		free(nname);
+		miblen = sizeof(mib) - 2 * sizeof(int);
+		if (sysctl(mib, 2, mib + 2, &miblen, desc.s,
+		    strlen(desc.s)) < 0)
+			goto unknown_parameter;
+		jp->jp_flags |= JP_NOBOOL;
 	}
  mib_desc:
 	mib[1] = 4;
@@ -925,6 +909,16 @@ jailparam_type(struct jailparam *jp)
 		    "sysctl(0.4.%s): %s", jp->jp_name, strerror(errno));
 		return (-1);
 	}
+	jp->jp_ctltype = desc.i;
+	/* If this came from removing a "no", it better be a boolean. */
+	if (jp->jp_flags & JP_NOBOOL) {
+		if ((desc.i & CTLTYPE) == CTLTYPE_INT && desc.s[0] == 'B') {
+			jp->jp_valuelen = sizeof(int);
+			return (0);
+		}
+		else if ((desc.i & CTLTYPE) != CTLTYPE_NODE)
+			goto unknown_parameter;
+	}
 	/* See if this is an array type. */
 	p = strchr(desc.s, '\0');
 	isarray  = 0;
@@ -935,7 +929,6 @@ jailparam_type(struct jailparam *jp)
 		p[-2] = 0;
 	}
 	/* Look for types we understand. */
-	jp->jp_ctltype = desc.i;
 	switch (desc.i & CTLTYPE) {
 	case CTLTYPE_INT:
 		if (desc.s[0] == 'B')

Modified: stable/9/share/man/man5/devfs.5
==============================================================================
--- stable/9/share/man/man5/devfs.5	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/share/man/man5/devfs.5	Fri Mar  9 16:17:46 2012	(r232728)
@@ -38,7 +38,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 18, 2010
+.Dd February 9, 2012
 .Dt DEVFS 5
 .Os
 .Sh NAME
@@ -90,6 +90,30 @@ and
 .Pa 2 .
 .Xr fdescfs 5
 creates files for all open descriptors.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl o Ar options
+Use the specified mount
+.Ar options ,
+as described in
+.Xr mount 8 .
+The following devfs file system-specific options are available:
+.Bl -tag -width indent
+.It Cm ruleset Ns No = Ns Ar ruleset
+Set ruleset number
+.Ar ruleset
+as the current ruleset for the mount-point and apply all its rules.
+If the ruleset number
+.Ar ruleset
+does not exist, an empty ruleset with the number
+.Ar ruleset
+is created.
+See
+.Xr devfs 8
+for more information on working with devfs rulesets.
+.El
+.El
 .Sh FILES
 .Bl -tag -width /dev/XXXX -compact
 .It Pa /dev

Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Fri Mar  9 16:17:46 2012	(r232728)
@@ -60,6 +60,7 @@
 #include <sys/dmu_objset.h>
 #include <sys/spa_boot.h>
 #include <sys/sa.h>
+#include <sys/jail.h>
 #include "zfs_comutil.h"
 
 struct mtx zfs_debug_mtx;
@@ -1533,6 +1534,9 @@ zfs_mount(vfs_t *vfsp)
 	int		error = 0;
 	int		canwrite;
 
+	if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_ZFS))
+		return (EPERM);
+
 	if (vfs_getopt(vfsp->mnt_optnew, "from", (void **)&osname, NULL))
 		return (EINVAL);
 

Modified: stable/9/sys/compat/linprocfs/linprocfs.c
==============================================================================
--- stable/9/sys/compat/linprocfs/linprocfs.c	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/compat/linprocfs/linprocfs.c	Fri Mar  9 16:17:46 2012	(r232728)
@@ -1460,7 +1460,7 @@ linprocfs_uninit(PFS_INIT_ARGS)
 	return (0);
 }
 
-PSEUDOFS(linprocfs, 1);
+PSEUDOFS(linprocfs, 1, 0);
 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);

Modified: stable/9/sys/compat/linsysfs/linsysfs.c
==============================================================================
--- stable/9/sys/compat/linsysfs/linsysfs.c	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/compat/linsysfs/linsysfs.c	Fri Mar  9 16:17:46 2012	(r232728)
@@ -280,5 +280,5 @@ linsysfs_uninit(PFS_INIT_ARGS)
 	return (0);
 }
 
-PSEUDOFS(linsysfs, 1);
+PSEUDOFS(linsysfs, 1, 0);
 MODULE_DEPEND(linsysfs, linux, 1, 1, 1);

Modified: stable/9/sys/fs/devfs/devfs.h
==============================================================================
--- stable/9/sys/fs/devfs/devfs.h	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/fs/devfs/devfs.h	Fri Mar  9 16:17:46 2012	(r232728)
@@ -182,6 +182,8 @@ void	devfs_rules_apply(struct devfs_moun
 void	devfs_rules_cleanup(struct devfs_mount *);
 int	devfs_rules_ioctl(struct devfs_mount *, u_long, caddr_t,
 	    struct thread *);
+void	devfs_ruleset_set(devfs_rsnum rsnum, struct devfs_mount *dm);
+void	devfs_ruleset_apply(struct devfs_mount *dm);
 int	devfs_allocv(struct devfs_dirent *, struct mount *, int,
 	    struct vnode **);
 char	*devfs_fqpn(char *, struct devfs_mount *, struct devfs_dirent *,

Modified: stable/9/sys/fs/devfs/devfs_rule.c
==============================================================================
--- stable/9/sys/fs/devfs/devfs_rule.c	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/fs/devfs/devfs_rule.c	Fri Mar  9 16:17:46 2012	(r232728)
@@ -771,3 +771,38 @@ devfs_rules_cleanup(struct devfs_mount *
 		devfs_ruleset_reap(ds);
 	}
 }
+
+/*
+ * Make rsnum the active ruleset for dm (locked)
+ */
+void
+devfs_ruleset_set(devfs_rsnum rsnum, struct devfs_mount *dm)
+{
+
+	sx_assert(&dm->dm_lock, SX_XLOCKED);
+
+	sx_xlock(&sx_rules);
+	devfs_ruleset_use(rsnum, dm);
+	sx_xunlock(&sx_rules);
+}
+
+/*
+ * Apply the current active ruleset on a mount
+ */
+void
+devfs_ruleset_apply(struct devfs_mount *dm)
+{
+	struct devfs_ruleset *ds;
+
+	sx_assert(&dm->dm_lock, SX_XLOCKED);
+
+	sx_xlock(&sx_rules);
+	if (dm->dm_ruleset == 0) {
+		sx_xunlock(&sx_rules);
+		return;
+	}
+	ds = devfs_ruleset_bynum(dm->dm_ruleset);
+	if (ds != NULL)
+		devfs_ruleset_applydm(ds, dm);
+	sx_xunlock(&sx_rules);
+}

Modified: stable/9/sys/fs/devfs/devfs_vfsops.c
==============================================================================
--- stable/9/sys/fs/devfs/devfs_vfsops.c	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/fs/devfs/devfs_vfsops.c	Fri Mar  9 16:17:46 2012	(r232728)
@@ -44,6 +44,7 @@
 #include <sys/sx.h>
 #include <sys/vnode.h>
 #include <sys/limits.h>
+#include <sys/jail.h>
 
 #include <fs/devfs/devfs.h>
 
@@ -56,6 +57,10 @@ static vfs_unmount_t	devfs_unmount;
 static vfs_root_t	devfs_root;
 static vfs_statfs_t	devfs_statfs;
 
+static const char *devfs_opts[] = {
+	"from", "export", "ruleset", NULL
+};
+
 /*
  * Mount the filesystem
  */
@@ -65,15 +70,60 @@ devfs_mount(struct mount *mp)
 	int error;
 	struct devfs_mount *fmp;
 	struct vnode *rvp;
+	struct thread *td = curthread;
+	int injail, rsnum;
 
 	if (devfs_unr == NULL)
 		devfs_unr = new_unrhdr(0, INT_MAX, NULL);
 
 	error = 0;
 
-	if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS))
+	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))
+			return (EINVAL);
+
+		if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0))
+			return (EOPNOTSUPP);
+
+		if (vfs_getopt(mp->mnt_optnew, "ruleset", NULL, NULL) == 0 &&
+		    (vfs_scanopt(mp->mnt_optnew, "ruleset", "%d",
+		    &rsnum) != 1 || rsnum < 0 || rsnum > 65535)) {
+			vfs_mount_error(mp, "%s",
+			    "invalid ruleset specification");
+			return (EINVAL);
+		}
+
+		if (injail && rsnum != 0 &&
+		    rsnum != td->td_ucred->cr_prison->pr_devfs_rsnum)
+			return (EPERM);
+	}
+
+	/* jails enforce their ruleset */
+	if (injail)
+		rsnum = td->td_ucred->cr_prison->pr_devfs_rsnum;
+
+	if (mp->mnt_flag & MNT_UPDATE) {
+		if (rsnum != 0) {
+			fmp = mp->mnt_data;
+			if (fmp != NULL) {
+				sx_xlock(&fmp->dm_lock);
+				devfs_ruleset_set((devfs_rsnum)rsnum, fmp);
+				devfs_ruleset_apply(fmp);
+				sx_xunlock(&fmp->dm_lock);
+			}
+		}
+		return (0);
+	}
+
 	fmp = malloc(sizeof *fmp, M_DEVFS, M_WAITOK | M_ZERO);
 	fmp->dm_idx = alloc_unr(devfs_unr);
 	sx_init(&fmp->dm_lock, "devfsmount");
@@ -101,6 +151,12 @@ devfs_mount(struct mount *mp)
 		return (error);
 	}
 
+	if (rsnum != 0) {
+		sx_xlock(&fmp->dm_lock);
+		devfs_ruleset_set((devfs_rsnum)rsnum, fmp);
+		sx_xunlock(&fmp->dm_lock);
+	}
+
 	VOP_UNLOCK(rvp, 0);
 
 	vfs_mountedfrom(mp, "devfs");
@@ -186,4 +242,4 @@ static struct vfsops devfs_vfsops = {
 	.vfs_unmount =		devfs_unmount,
 };
 
-VFS_SET(devfs_vfsops, devfs, VFCF_SYNTHETIC);
+VFS_SET(devfs_vfsops, devfs, VFCF_SYNTHETIC | VFCF_JAIL);

Modified: stable/9/sys/fs/nullfs/null_vfsops.c
==============================================================================
--- stable/9/sys/fs/nullfs/null_vfsops.c	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/fs/nullfs/null_vfsops.c	Fri Mar  9 16:17:46 2012	(r232728)
@@ -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);
 	/*
@@ -364,4 +369,4 @@ static struct vfsops null_vfsops = {
 	.vfs_vget =		nullfs_vget,
 };
 
-VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK);
+VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK | VFCF_JAIL);

Modified: stable/9/sys/fs/procfs/procfs.c
==============================================================================
--- stable/9/sys/fs/procfs/procfs.c	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/fs/procfs/procfs.c	Fri Mar  9 16:17:46 2012	(r232728)
@@ -209,4 +209,4 @@ procfs_uninit(PFS_INIT_ARGS)
 	return (0);
 }
 
-PSEUDOFS(procfs, 1);
+PSEUDOFS(procfs, 1, PR_ALLOW_MOUNT_PROCFS);

Modified: stable/9/sys/fs/pseudofs/pseudofs.h
==============================================================================
--- stable/9/sys/fs/pseudofs/pseudofs.h	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/fs/pseudofs/pseudofs.h	Fri Mar  9 16:17:46 2012	(r232728)
@@ -31,6 +31,8 @@
 #ifndef _PSEUDOFS_H_INCLUDED
 #define _PSEUDOFS_H_INCLUDED
 
+#include <sys/jail.h>
+
 /*
  * Opaque structures
  */
@@ -271,7 +273,7 @@ int		 pfs_destroy	(struct pfs_node *pn);
 /*
  * Now for some initialization magic...
  */
-#define PSEUDOFS(name, version)						\
+#define PSEUDOFS(name, version, jflag)					\
 									\
 static struct pfs_info name##_info = {					\
 	#name,								\
@@ -281,6 +283,8 @@ static struct pfs_info name##_info = {		
 									\
 static int								\
 _##name##_mount(struct mount *mp) {					\
+        if (jflag && !prison_allow(curthread->td_ucred, jflag))		\
+                return (EPERM);						\
 	return pfs_mount(&name##_info, mp);				\
 }									\
 									\
@@ -303,7 +307,7 @@ static struct vfsops name##_vfsops = {		
 	.vfs_uninit =		_##name##_uninit,			\
 	.vfs_unmount =		pfs_unmount,				\
 };									\
-VFS_SET(name##_vfsops, name, VFCF_SYNTHETIC);				\
+VFS_SET(name##_vfsops, name, VFCF_SYNTHETIC | (jflag ? VFCF_JAIL : 0));	\
 MODULE_VERSION(name, version);						\
 MODULE_DEPEND(name, pseudofs, 1, 1, 1);
 

Modified: stable/9/sys/kern/kern_jail.c
==============================================================================
--- stable/9/sys/kern/kern_jail.c	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/kern/kern_jail.c	Fri Mar  9 16:17:46 2012	(r232728)
@@ -103,6 +103,7 @@ struct prison prison0 = {
 	.pr_uref	= 1,
 	.pr_path	= "/",
 	.pr_securelevel	= -1,
+	.pr_devfs_rsnum = 0,
 	.pr_childmax	= JAIL_MAX,
 	.pr_hostuuid	= DEFAULT_HOSTUUID,
 	.pr_children	= LIST_HEAD_INITIALIZER(prison0.pr_children),
@@ -200,6 +201,10 @@ static char *pr_allow_names[] = {
 	"allow.mount",
 	"allow.quotas",
 	"allow.socket_af",
+	"allow.mount.devfs",
+	"allow.mount.nullfs",
+	"allow.mount.zfs",
+	"allow.mount.procfs",
 };
 const size_t pr_allow_names_size = sizeof(pr_allow_names);
 
@@ -211,13 +216,19 @@ static char *pr_allow_nonames[] = {
 	"allow.nomount",
 	"allow.noquotas",
 	"allow.nosocket_af",
+	"allow.mount.nodevfs",
+	"allow.mount.nonullfs",
+	"allow.mount.nozfs",
+	"allow.mount.noprocfs",
 };
 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	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;
 #if defined(INET) || defined(INET6)
 static unsigned jail_max_af_ips = 255;
 #endif
@@ -529,9 +540,9 @@ kern_jail_set(struct thread *td, struct 
 	unsigned long hid;
 	size_t namelen, onamelen;
 	int created, cuflags, descend, enforce, error, errmsg_len, errmsg_pos;
-	int gotchildmax, gotenforce, gothid, gotslevel;
+	int gotchildmax, gotenforce, gothid, gotrsnum, gotslevel;
 	int fi, jid, jsys, len, level;
-	int childmax, slevel, vfslocked;
+	int childmax, rsnum, slevel, vfslocked;
 	int fullpath_disabled;
 #if defined(INET) || defined(INET6)
 	int ii, ij;
@@ -612,6 +623,14 @@ kern_jail_set(struct thread *td, struct 
 	} else
 		gotenforce = 1;
 
+	error = vfs_copyopt(opts, "devfs_ruleset", &rsnum, sizeof(rsnum));
+	if (error == ENOENT)
+		gotrsnum = 0;
+	else if (error != 0)
+		goto done_free;
+	else
+		gotrsnum = 1;
+
 	pr_flags = ch_flags = 0;
 	for (fi = 0; fi < sizeof(pr_flag_names) / sizeof(pr_flag_names[0]);
 	    fi++) {
@@ -1268,6 +1287,7 @@ kern_jail_set(struct thread *td, struct 
 		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 = ppr->pr_devfs_rsnum;
 
 		LIST_INIT(&pr->pr_children);
 		mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF | MTX_DUPOK);
@@ -1346,6 +1366,25 @@ kern_jail_set(struct thread *td, struct 
 			goto done_deref_locked;
 		}
 	}
+	if (gotrsnum) {
+		/*
+		 * devfs_rsnum is a uint16_t
+		 */
+		if (rsnum < 0 || rsnum > 65535) {
+			error = EINVAL;
+			goto done_deref_locked;
+		}
+		/*
+		 * 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
+				rsnum = ppr->pr_devfs_rsnum;
+		}
+	}
 #ifdef INET
 	if (ip4s > 0) {
 		if (ppr->pr_flags & PR_IP4) {
@@ -1586,6 +1625,12 @@ kern_jail_set(struct thread *td, struct 
 			if (tpr->pr_enforce_statfs < enforce)
 				tpr->pr_enforce_statfs = enforce;
 	}
+	if (gotrsnum) {
+		pr->pr_devfs_rsnum = rsnum;
+		/* Pass this restriction on to the children. */
+		FOREACH_PRISON_DESCENDANT_LOCKED(pr, tpr, descend)
+			tpr->pr_devfs_rsnum = rsnum;
+	}
 	if (name != NULL) {
 		if (ppr == &prison0)
 			strlcpy(pr->pr_name, name, sizeof(pr->pr_name));
@@ -2020,6 +2065,10 @@ kern_jail_get(struct thread *td, struct 
 	    sizeof(pr->pr_enforce_statfs));
 	if (error != 0 && error != ENOENT)
 		goto done_deref;
+	error = vfs_setopt(opts, "devfs_ruleset", &pr->pr_devfs_rsnum,
+	    sizeof(pr->pr_devfs_rsnum));
+	if (error != 0 && error != ENOENT)
+		goto done_deref;
 	for (fi = 0; fi < sizeof(pr_flag_names) / sizeof(pr_flag_names[0]);
 	    fi++) {
 		if (pr_flag_names[fi] == NULL)
@@ -4151,6 +4200,22 @@ SYSCTL_PROC(_security_jail, OID_AUTO, mo
     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 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 the nullfs file system");
+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");
+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");
 
 static int
 sysctl_jail_default_level(SYSCTL_HANDLER_ARGS)
@@ -4173,6 +4238,12 @@ SYSCTL_PROC(_security_jail, OID_AUTO, en
     sysctl_jail_default_level, "I",
     "Processes in jail cannot see all mounted file systems");
 
+SYSCTL_PROC(_security_jail, OID_AUTO, devfs_ruleset,
+    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+    &jail_default_devfs_rsnum, offsetof(struct prison, pr_devfs_rsnum),
+    sysctl_jail_default_level, "I",
+    "Ruleset for the devfs filesystem in jail");
+
 /*
  * Nodes to describe jail parameters.  Maximum length of string parameters
  * is returned in the string itself, and the other parameters exist merely
@@ -4221,6 +4292,8 @@ SYSCTL_JAIL_PARAM(, securelevel, CTLTYPE
     "I", "Jail secure level");
 SYSCTL_JAIL_PARAM(, enforce_statfs, CTLTYPE_INT | CTLFLAG_RW,
     "I", "Jail cannot see all mounted file systems");
+SYSCTL_JAIL_PARAM(, devfs_ruleset, CTLTYPE_INT | CTLFLAG_RW,
+    "I", "Ruleset for in-jail devfs mounts");
 SYSCTL_JAIL_PARAM(, persist, CTLTYPE_INT | CTLFLAG_RW,
     "B", "Jail persistence");
 #ifdef VIMAGE
@@ -4277,13 +4350,23 @@ SYSCTL_JAIL_PARAM(_allow, raw_sockets, C
     "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 the devfs file system");
+SYSCTL_JAIL_PARAM(_allow_mount, nullfs, CTLTYPE_INT | CTLFLAG_RW,
+    "B", "Jail may mount the nullfs file system");
+SYSCTL_JAIL_PARAM(_allow_mount, procfs, CTLTYPE_INT | CTLFLAG_RW,
+    "B", "Jail may mount the procfs file system");
+SYSCTL_JAIL_PARAM(_allow_mount, zfs, CTLTYPE_INT | CTLFLAG_RW,
+    "B", "Jail may mount the zfs file system");
+
 void
 prison_racct_foreach(void (*callback)(struct racct *racct,
     void *arg2, void *arg3), void *arg2, void *arg3)
@@ -4413,6 +4496,7 @@ db_show_prison(struct prison *pr)
 #endif
 	db_printf(" root            = %p\n", pr->pr_root);
 	db_printf(" securelevel     = %d\n", pr->pr_securelevel);
+	db_printf(" devfs_rsnum     = %d\n", pr->pr_devfs_rsnum);
 	db_printf(" children.max    = %d\n", pr->pr_childmax);
 	db_printf(" children.cur    = %d\n", pr->pr_childcount);
 	db_printf(" child           = %p\n", LIST_FIRST(&pr->pr_children));

Modified: stable/9/sys/sys/jail.h
==============================================================================
--- stable/9/sys/sys/jail.h	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/sys/jail.h	Fri Mar  9 16:17:46 2012	(r232728)
@@ -176,7 +176,8 @@ struct prison {
 	unsigned	 pr_allow;			/* (p) PR_ALLOW_* flags */
 	int		 pr_securelevel;		/* (p) securelevel */
 	int		 pr_enforce_statfs;		/* (p) statfs permission */
-	int		 pr_spare[5];
+	int		 pr_devfs_rsnum;		/* (p) devfs ruleset */
+	int		 pr_spare[4];
 	unsigned long	 pr_hostid;			/* (p) jail hostid */
 	char		 pr_name[MAXHOSTNAMELEN];	/* (p) admin jail name */
 	char		 pr_path[MAXPATHLEN];		/* (c) chroot path */
@@ -222,7 +223,11 @@ 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_MOUNT_ZFS		0x0200
+#define	PR_ALLOW_MOUNT_PROCFS		0x0400
+#define	PR_ALLOW_ALL			0x07ff
 
 /*
  * OSD methods
@@ -337,6 +342,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",	\

Modified: stable/9/sys/sys/param.h
==============================================================================
--- stable/9/sys/sys/param.h	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/sys/sys/param.h	Fri Mar  9 16:17:46 2012	(r232728)
@@ -58,7 +58,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 900503	/* Master, propagated to newvers */
+#define __FreeBSD_version 900504	/* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

Modified: stable/9/usr.sbin/jail/jail.8
==============================================================================
--- stable/9/usr.sbin/jail/jail.8	Fri Mar  9 16:05:11 2012	(r232727)
+++ stable/9/usr.sbin/jail/jail.8	Fri Mar  9 16:17:46 2012	(r232728)
@@ -34,7 +34,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 23, 2011
+.Dd February 29, 2012
 .Dt JAIL 8
 .Os
 .Sh NAME
@@ -301,6 +301,19 @@ A jail never has a lower securelevel tha
 setting this parameter it may have a higher one.
 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.
+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
+and
+.Va allow.mount.devfs
+permissions are effective and
+.Va enforce_statfs
+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).
@@ -396,6 +409,45 @@ 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.mount.procfs
+privileged users inside the jail will be able to mount and unmount the
+procfs 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.mount.zfs
+privileged users inside the jail will be able to mount and unmount the
+ZFS 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.
+See
+.Xr zfs 8
+for information on how to configure the ZFS filesystem to operate from
+within a jail.
 .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


More information about the svn-src-stable-9 mailing list