Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 Feb 2012 18:51:24 +0000 (UTC)
From:      Martin Matuska <mm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r232059 - in head: sys/fs/devfs sys/fs/nullfs sys/kern sys/sys usr.sbin/jail
Message-ID:  <201202231851.q1NIpOxH018329@svn.freebsd.org>

index | next in thread | raw e-mail

Author: mm
Date: Thu Feb 23 18:51:24 2012
New Revision: 232059
URL: http://svn.freebsd.org/changeset/base/232059

Log:
  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.
  
  Reviewed by:	jamie
  Suggested by:	pjd
  MFC after:	2 weeks

Modified:
  head/sys/fs/devfs/devfs_vfsops.c
  head/sys/fs/nullfs/null_vfsops.c
  head/sys/kern/kern_jail.c
  head/sys/sys/jail.h
  head/usr.sbin/jail/jail.8

Modified: head/sys/fs/devfs/devfs_vfsops.c
==============================================================================
--- head/sys/fs/devfs/devfs_vfsops.c	Thu Feb 23 18:50:19 2012	(r232058)
+++ head/sys/fs/devfs/devfs_vfsops.c	Thu Feb 23 18:51:24 2012	(r232059)
@@ -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) {

Modified: head/sys/fs/nullfs/null_vfsops.c
==============================================================================
--- head/sys/fs/nullfs/null_vfsops.c	Thu Feb 23 18:50:19 2012	(r232058)
+++ head/sys/fs/nullfs/null_vfsops.c	Thu Feb 23 18:51:24 2012	(r232059)
@@ -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);
 	/*

Modified: head/sys/kern/kern_jail.c
==============================================================================
--- head/sys/kern/kern_jail.c	Thu Feb 23 18:50:19 2012	(r232058)
+++ head/sys/kern/kern_jail.c	Thu Feb 23 18:51:24 2012	(r232059)
@@ -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 
 		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 
 	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 
 		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, 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/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, 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/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)

Modified: head/sys/sys/jail.h
==============================================================================
--- head/sys/sys/jail.h	Thu Feb 23 18:50:19 2012	(r232058)
+++ head/sys/sys/jail.h	Thu Feb 23 18:51:24 2012	(r232059)
@@ -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",	\

Modified: head/usr.sbin/jail/jail.8
==============================================================================
--- head/usr.sbin/jail/jail.8	Thu Feb 23 18:50:19 2012	(r232058)
+++ head/usr.sbin/jail/jail.8	Thu Feb 23 18:51:24 2012	(r232059)
@@ -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, an
 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


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202231851.q1NIpOxH018329>