Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Jul 2011 16:11:37 +0200
From:      Martin Matuska <mm@FreeBSD.org>
To:        freebsd-current@FreeBSD.org
Subject:   [PATCH] updated /etc/rc.d/jail and added ZFS support
Message-ID:  <4E316E19.9040309@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------000605040303080100060003
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit

The attached patch allows better fine-tuning of jails started via
/etc/rc.d, uses the new jail(8) flags (-c -m), the persist parameter and
adds ZFS support.
Patch is fully backward compatible.

Please review, comment and/or test my attached patch.

Cheers,
mm

-- 
Martin Matuska
FreeBSD committer
http://blog.vx.sk


--------------000605040303080100060003
Content-Type: text/x-patch;
 name="etc_jail.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="etc_jail.patch"

Index: etc/rc.d/jail
===================================================================
--- etc/rc.d/jail	(revision 224471)
+++ etc/rc.d/jail	(working copy)
@@ -43,6 +43,7 @@
 	eval _ip=\"\$jail_${_j}_ip\"
 	eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
 	eval _exec=\"\$jail_${_j}_exec\"
+	eval _params=\"\$jail_${_j}_params\"
 
 	i=0
 	while : ; do
@@ -83,6 +84,8 @@
 		i=$((i + 1))
 	done
 
+	eval _zfs=\"\${jail_${_j}_zfs:-}\"
+
 	if [ -n "${_exec}" ]; then
 		#   simple/backward-compatible execution
 		_exec_start="${_exec}"
@@ -98,6 +101,9 @@
 	fi
 
 	# The default jail ruleset will be used by rc.subr if none is specified.
+	if [ -n "jail_devfs_ruleset" -a -n "_zfs" ]; then
+		jail_devfs_ruleset="devfsrules_jail_zfs"
+	fi
 	eval _ruleset=\"\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}\"
 	eval _devfs=\"\${jail_${_j}_devfs_enable:-${jail_devfs_enable}}\"
 	[ -z "${_devfs}" ] && _devfs="NO"
@@ -200,6 +206,58 @@
 	if [ -z "${_rootdir}" ]; then
 		err 3 "$name: No root directory has been defined for ${_j}"
 	fi
+
+	# Security-related parameters
+	eval _enforce_statfs=\"\$jail_${_j}_enforce_statfs\"
+	eval _allow_set_hostname=\"\$jail_${_j}_allow_set_hostname\"
+	eval _allow_sysvipc=\"\$jail_${_j}_allow_sysvipc\"
+	eval _allow_raw_sockets=\"\$jail_${_j}_allow_raw_sockets\"
+	eval _allow_chflags=\"\$jail_${_j}_allow_chflags\"
+	eval _allow_mount=\"\$jail_${_j}_allow_mount\"
+	eval _allow_socket_af=\"\$jail_${_j}_allow_socket_af\"
+	eval _allow_quotas=\"\$jail_${_j}_allow_quotas:-0\"
+
+	if [ -z "${_enforce_statfs}" ]; then
+		_enforce_statfs=`${SYSCTL} -n security.jail.enforce_statfs`
+	fi
+
+	if [ -z "${_allow_set_hostname}" ]; then
+		_allow_set_hostname=`${SYSCTL} -n security.jail.set_hostname_allowed`
+	fi
+
+	if [ -z "${_allow_sysvipc}" ]; then
+		_allow_sysvipc=`${SYSCTL} -n security.jail.sysvipc_allowed`
+	fi
+
+	if [ -z "${_allow_raw_sockets}" ]; then
+		_allow_raw_sockets=`${SYSCTL} -n security.jail.allow_raw_sockets`
+	fi
+
+	if [ -z "${_allow_chflags}" ]; then
+		_allow_chflags=`${SYSCTL} -n security.jail.chflags_allowed`
+	fi
+
+	if [ -z "${_allow_mount}" ]; then
+		_allow_mount=`${SYSCTL} -n security.jail.mount_allowed`
+	fi
+
+	if [ -z "${_allow_socket_af}" ]; then
+		_tmpval=`${SYSCTL} -n security.jail.socket_unixiproute_only`
+		if [ "${_tmpval}" = "0" ]; then
+			_allow_socket_af=1
+		else
+			_allow_socket_af=0
+		fi
+	fi
+
+	_security_params="enforce_statfs=${_enforce_statfs} \
+	    allow.set_hostname=${_allow_set_hostname} \
+	    allow.sysvipc=${_allow_sysvipc} \
+	    allow.raw_sockets=${_allow_raw_sockets} \
+	    allow.chflags=${_allow_chflags} \
+	    allow.mount=${_allow_mount} \
+	    allow.socket_af=${_allow_socket_af} \
+	    allow.quotas=${allow_quotas}"
 }
 
 # set_sysctl rc_knob mib msg
@@ -345,6 +403,36 @@
 	mount -a -F "${_fstab}"
 }
 
+# jail_zfs_jailin
+#	Make zfs datasets manageable from inside a jail
+#	the "jailed" dataset property must be set to "on"
+jail_zfs_jailin()
+{
+	if [ -n "${_zfs}" ]; then
+		for _ds in ${_zfs}; do
+			_jailed=`zfs get -H jailed ${_ds} 2>/dev/null | awk '{ print $3 }'`
+			if [ "$_jailed" = "on" ]; then
+				zfs jail "${_jail_id}" ${_ds} 2>/dev/null
+			fi
+		done
+	fi
+}
+
+# jail_zfs_jailout
+#	Unjail zfs datasets
+#	the "jailed" dataset property must be set to "on"
+jail_zfs_jailout()
+{
+	if [ -n "${_zfs}" ]; then
+		for _ds in ${_zfs}; do
+			_jailed=`zfs get -H jailed ${_ds} 2>/dev/null | awk '{ print $3 }'`
+			if [ "$_jailed" = "on" ]; then
+				zfs unjail "${_jail_id}" ${_ds} 2>/dev/null
+			fi
+		done
+	fi
+}
+
 # jail_show_addresses jail
 #	Debug print the input for the given _multi aliases
 #	for a jail for init_variables().
@@ -483,10 +571,27 @@
 		*)	;;
 		esac
 
-		# Append address to list of addresses for the jail command.
-		case "${_addrl}" in
-		"")	_addrl="${_addr}" ;;
-		*)	_addrl="${_addrl},${_addr}" ;;
+		case "${_type}" in
+		inet)
+			# Append address to list of ipv4 addresses for the
+			# jail command.
+			case "${_addrl}" in
+			"")	_addrl="${_addr}" ;;
+			*)	_addrl="${_addrl},${_addr}" ;;
+			esac
+			;;
+		inet6)
+			# Append address to list of ipv6 addresses for the
+			# jail command.
+			case "${_addrl6}" in
+			"")	_addrl6="${_addr}" ;;
+			*)	_addrl6="${_addrl6},${_addr}" ;;
+			esac
+			;;
+		*)	warn "Could not determine address family.  Not going" \
+			    "to set address '${_addr}' for ${_jail}."
+			continue
+			;;
 		esac
 
 		# Configure interface alias if requested by a given interface
@@ -494,14 +599,7 @@
 		case "${_iface}" in
 		"")	continue ;;
 		esac
-		case "${_type}" in
-		inet)	;;
-		inet6)	;;
-		*)	warn "Could not determine address family.  Not going" \
-			    "to ${_action} address '${_addr}' for ${_jail}."
-			continue
-			;;
-		esac
+
 		case "${_action}" in
 		add)	ifconfig ${_iface} ${_type} ${_addr}${_mask} alias
 			;;
@@ -576,6 +674,7 @@
 			continue;
 		fi
 		_addrl=""
+		_addrl6=""
 		jail_ips "add"
 		if [ -n "${_fib}" ]; then
 			_setfib="setfib -F '${_fib}'"
@@ -644,42 +743,54 @@
 			i=$((i + 1))
 		done
 
-		eval ${_setfib} jail ${_flags} -i ${_rootdir} ${_hostname} \
-			\"${_addrl}\" ${_exec_start} > ${_tmp_jail} 2>&1 \
-			</dev/null
+		_jail_id=`${_setfib} jail -i ${_flags} -c \
+			path="${_rootdir}" \
+			host.hostname="${_hostname}" \
+			ip4.addr="${_addrl}" \
+			ip6.addr="${_addrl6}" \
+			persist=1 \
+			${_security_params} ${_params}`
 
-		if [ "$?" -eq 0 ] ; then
-			_jail_id=$(head -1 ${_tmp_jail})
-			i=1
-			while : ; do
-				eval out=\"\${_exec_afterstart${i}:-''}\"
+		if [ -n "$_jail_id" ]; then
+			jail_zfs_jailin
+			eval jail ${_flags} -m jid="${_jail_id}" \
+			    command="${_exec_start}" > ${_tmp_jail} 2>&1 \
+			    </dev/null
+			if [ "$?" -eq 0 ] ; then
+				jail -m jid="${_jail_id}" persist=0
+				i=1
+				while : ; do
+					eval out=\"\${_exec_afterstart${i}:-''}\"
 
-				if [ -z "$out" ]; then
-					break;
-				fi
+					if [ -z "$out" ]; then
+						break;
+					fi
 
-				jexec "${_jail_id}" ${out}
-				i=$((i + 1))
-			done
+					jexec "${_jail_id}" ${out}
+					i=$((i + 1))
+				done
 
-			echo -n " $_hostname"
-			tail +2 ${_tmp_jail} >${_consolelog}
-			echo ${_jail_id} > /var/run/jail_${_jail}.id
+				echo -n " $_hostname"
+				tail +2 ${_tmp_jail} >${_consolelog}
+				echo ${_jail_id} > /var/run/jail_${_jail}.id
 
-			i=0
-			while : ; do
-				eval out=\"\${_exec_poststart${i}:-''}\"
-				[ -z "$out" ] && break
-				${out}
-				i=$((i + 1))
-			done
-		else
-			jail_umount_fs
-			jail_ips "del"
-			echo " cannot start jail \"${_jail}\": "
-			tail +2 ${_tmp_jail}
+				i=0
+				while : ; do
+					eval out=\"\${_exec_poststart${i}:-''}\"
+					[ -z "$out" ] && break
+					${out}
+					i=$((i + 1))
+				done
+			else
+				jail_zfs_jailout
+				jail -m jid="${_jail_id}" persist=0
+				jail_umount_fs
+				jail_ips "del"
+				echo " cannot start jail \"${_jail}\": "
+				tail +2 ${_tmp_jail}
+			fi
+			rm -f ${_tmp_jail}
 		fi
-		rm -f ${_tmp_jail}
 	done
 	rmdir ${_tmp_dir}
 	echo '.'
@@ -707,6 +818,7 @@
 					eval env -i /usr/sbin/jexec ${_jail_id} ${_exec_stop} \
 						>> ${_consolelog} 2>&1
 				fi
+				jail_zfs_jailout
 				killall -j ${_jail_id} -TERM > /dev/null 2>&1
 				sleep 1
 				killall -j ${_jail_id} -KILL > /dev/null 2>&1
Index: etc/defaults/devfs.rules
===================================================================
--- etc/defaults/devfs.rules	(revision 224471)
+++ etc/defaults/devfs.rules	(working copy)
@@ -83,3 +83,9 @@
 add include $devfsrules_hide_all
 add include $devfsrules_unhide_basic
 add include $devfsrules_unhide_login
+
+# Jail with zfs support
+#
+[devfsrules_jail_zfs=5]
+add include $devfsrules_jail
+add path zfs unhide
Index: etc/defaults/rc.conf
===================================================================
--- etc/defaults/rc.conf	(revision 224471)
+++ etc/defaults/rc.conf	(working copy)
@@ -695,6 +695,21 @@
 #jail_example_mount_enable="NO"			# mount/umount jail's fs
 #jail_example_fstab=""				# fstab(5) for mount/umount
 #jail_example_flags="-l -U root"		# flags for jail(8)
+#jail_example_params=""				# additional parameters for jail(8)
+#jail_example_enforce_statfs=""			# jail(8) enforce_statfs parameter
+#jail_example_allow_set_hostname=""		# jail(8) allow.set_hostname parameter
+#jail_example_allow_sysvipc=""			# jail(8) allow.sysvipc parameter
+#jail_example_allow_raw_sockets=""		# jail(8) allow.raw_sockets parameter
+#jail_example_allow_chflags=""			# jail(8) allow.chflags parameter
+#jail_example_allow_mount=""			# jail(8) allow.mount parameter
+#jail_example_allow_socket_af=""		# jail(8) allow.socket_af parameter
+#jail_example_allow_quotas=""			# jail(8) allow.quotas parameter
+#jail_example_zfs=""				# Space-separated list of ZFS datasets to be
+						# managed from this jail. For proper operation,
+						# allow_mount must be defined and enforce_statfs
+						# must be lower than 2. The "jailed" property
+						# must be set to "on" on these datasets before starting
+						# the jail.
 
 ##############################################################
 ### Define source_rc_confs, the mechanism used by /etc/rc.* ##

--------------000605040303080100060003--



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