[PATCH] updated /etc/rc.d/jail and added ZFS support

Martin Matuska mm at FreeBSD.org
Fri Jul 29 20:53:22 UTC 2011


So what do you think about this updated patch (attached)?
Here we leave everything possible for jail_example_params.
Btw. you can also set jid=xxx in params to have a "static" jail id for
this jail.

Also stopping a persistent jail doesn't delete it (but you cannot start
it again).

Dňa 28. 7. 2011 20:47, Jamie Gritton  wrote / napísal(a):
> Yes, it was intentional to move away from the global sysctls and to
> the per-jail parameters instead.  It makes more sense once config
> files come into play, which can do a better job of providing global
> defaults as well as per-jail parameters.
>
> The connection between ZFS and persist makes sense.  So for ZFS-based
> jail you'd want to set (and then reset) persist.  For others, this
> could be left to the user.  The changes to jail(8) for config files
> also sets persist when creating jails, and then clears it at a later
> stage unless the user specifies to keep it set.  It looks like I might
> want to add some ZFS support to the new jail(8).
>
> I would prefer to keep things simpler regarding create/start and
> remove/stop, and keep them tied together.
>
> - Jamie
>
>
> On 07/28/11 12:00, Martin Matuska wrote:
>> If you start jail(8) witth "-c" (the new "param" way,) the values of the
>> actual security.jail. variables are not initialized inside the jail,
>> default values are used instead. I don't know if this is intentional,
>> but probably yes. Default enforce_statfs=2, allow.mount=0.
>> As of me we can leave everything for ${_params}, but then ${_zfs} makes
>> sense only if enforce_statfs<2 and allow.mount=1.
>>
>> Regarding zfs, if you want to operate zfs from the very start of a jail
>> (and e.g. make use of /etc/rc.d/zfs which has jail support), you have to
>> pair datasets with an existing jail. In simple words, you have to create
>> a process-less jail (persist=1), attach zfs datasets and then run the
>> command. The persist option can be made optional - but we always start
>> with persist=1, then we can set (or not) persist=0 depending on user
>> setting.
>>
>> The question that opens, should we remove a persisting jail on "stop"?
>> Or should we support new commands "create" and "remove" in addition to
>> "start" and "stop"? Create would just make a processless jail, remove
>> would wipe out a jail and start/stop would just deal with the processes
>> (if persist=0 the old way, of course)?
>>
>> Cheers,
>> mm
>>
>> Dňa 28. 7. 2011 18:25, Jamie Gritton wrote / napísal(a):
>>> Since I missed the 9.0 boat with jail config file capability, something
>>> like this seems necessary; rc.d/jail has long been unable to handle the
>>> full scale of what jail(8) can do.
>>>
>>> I gather that setting persist is necessary for the ZFS operation. As
>>> long as we're making the parameter setting more generic from rc, we
>>> should handle the case where persist is specified in ${_params}, and
>>> not
>>> always set/reset it around the jail creation unless ZFS is used.
>>>
>>> Also, why the specific inclusion of the security-related parameters?
>>> They could just be folded into ${_params}, and if left unspecified then
>>> jail(8) should by default do the right thing.
>>>
>>> - Jamie
>>>
>>>
>>> On 07/28/11 08:11, Martin Matuska wrote:
>>>> 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

-------------- next part --------------
Index: etc/rc.d/jail
===================================================================
--- etc/rc.d/jail	(revision 224494)
+++ etc/rc.d/jail	(working copy)
@@ -43,6 +43,9 @@
 	eval _ip=\"\$jail_${_j}_ip\"
 	eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
 	eval _exec=\"\$jail_${_j}_exec\"
+	eval _params=\"\$jail_${_j}_params\"
+	eval _persist=\"\$jail_${_j}_persist\"
+	eval _zfs=\"\${jail_${_j}_zfs:-}\"
 
 	i=0
 	while : ; do
@@ -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"
@@ -345,6 +351,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 +519,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 +547,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 +622,7 @@
 			continue;
 		fi
 		_addrl=""
+		_addrl6=""
 		jail_ips "add"
 		if [ -n "${_fib}" ]; then
 			_setfib="setfib -F '${_fib}'"
@@ -644,42 +691,56 @@
 			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}" \
+			${_params} \
+			persist=1`
 
-		if [ "$?" -eq 0 ] ; then
-			_jail_id=$(head -1 ${_tmp_jail})
-			i=1
-			while : ; do
-				eval out=\"\${_exec_afterstart${i}:-''}\"
-
-				if [ -z "$out" ]; then
-					break;
+		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
+				if [ "${_persist}" != "1" ]; then
+					jail -m jid="${_jail_id}" persist=0
 				fi
+				i=1
+				while : ; do
+					eval out=\"\${_exec_afterstart${i}:-''}\"
 
-				jexec "${_jail_id}" ${out}
-				i=$((i + 1))
-			done
+					if [ -z "$out" ]; then
+						break;
+					fi
 
-			echo -n " $_hostname"
-			tail +2 ${_tmp_jail} >${_consolelog}
-			echo ${_jail_id} > /var/run/jail_${_jail}.id
+					jexec "${_jail_id}" ${out}
+					i=$((i + 1))
+				done
 
-			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}
+				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_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 +768,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,15 @@
 #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_persist=""			# Set to 1 to create a persistent jail
+#jail_example_params=""				# Space-separated list of additional
+						# user-supplied parameters for jail(8)
+#jail_example_zfs=""				# Space-separated list of ZFS datasets to be
+						# managed from this jail. For proper operation,
+						# allow.mount=1 and enforce_statfs=1 (or 0)
+						# must be added to jail_example_params.
+						# The "jailed" property must be set to "on"
+						# on desired datasets before starting the jail.
 
 ##############################################################
 ### Define source_rc_confs, the mechanism used by /etc/rc.* ##


More information about the freebsd-current mailing list