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 \ - ${_tmp_jail} 2>&1 \ + ${_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.* ##