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
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.* ##
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "[email protected]"