freebsd-skq/etc/rc.d/jail

282 lines
7.7 KiB
Plaintext
Raw Normal View History

#!/bin/sh
#
# $FreeBSD$
#
# PROVIDE: jail
# REQUIRE: LOGIN cleanvar
# BEFORE: securelevel
# KEYWORD: nojail shutdown
. /etc/rc.subr
name="jail"
rcvar=`set_rcvar`
start_cmd="jail_start"
stop_cmd="jail_stop"
# init_variables _j
# Initialize the various jail variables for jail _j.
#
init_variables()
{
_j="$1"
if [ -z "$_j" ]; then
warn "init_variables: you must specify a jail"
return
fi
eval jail_rootdir=\"\$jail_${_j}_rootdir\"
jail_devdir="${jail_rootdir}/dev"
jail_fdescdir="${jail_devdir}/fd"
jail_procdir="${jail_rootdir}/proc"
eval jail_hostname=\"\$jail_${_j}_hostname\"
eval jail_ip=\"\$jail_${_j}_ip\"
eval jail_interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
eval jail_exec=\"\$jail_${_j}_exec\"
eval jail_exec_start=\"\${jail_${_j}_exec_start:-${jail_exec_start}}\"
eval jail_exec_stop=\"\${jail_${_j}_exec_stop:-${jail_exec_stop}}\"
Improve the RC framework for the clean booting/shutdown of Jails: 1. Feature: for flexibility reasons and as a prerequisite to clean shutdowns, allow the configuration of a stop/shutdown command via rc.conf variable "jail_<name>_exec_stop" in addition to the start/boot command (rc.conf variable "jail_<name>_exec_start"). For backward compatibility reasons, rc.conf variable "jail_<name>_exec" is still supported, too. 2. Debug: Add the used boot/shutdown commands to the debug output of the /etc/rc.d/jail script, too. 3. Security: Run the Jail start/boot command in a cleaned environment to not leak information from the host to the Jail during startup. 4. Feature: Run the Jail stop/shutdown command "jail_<name>_exec_stop" on "/etc/rc.d/jail stop <name>" to allow a graceful shutdown of the Jail before its processes are just killed. 5. Bugfix: When killing the remaining Jail processes give the processes time to actually perform their termination sequence. Without this the subsequent umount(8) operations usually fail because the resources are still in use. Additionally, if after trying to TERM-inate the processes there are still processes hanging around, finally just KILL them. 6. Bugfix: In rc.shutdown, if running inside a Jail, skip the /etc/rc.d/* scripts which are flagged with the KEYWORD "nojail" to allow the correct operation of rc.shutdown under jail_<name>_exec_stop="/bin/sh /etc/rc.shutdown". This is analogous to what /etc/rc does inside a Jail. Now the following typical host-configuration for two Jails works as expected and correctly boots and shutdowns the Jails: ----------------------------------------------------------- # /etc/rc.conf: jail_enable="YES" jail_list="foo bar" jail_foo_rootdir="/j/foo" jail_foo_hostname="foo.example.com" jail_foo_ip="192.168.0.1" jail_foo_devfs_enable="YES" jail_foo_mount_enable="YES" jail_foo_exec_start="/bin/sh /etc/rc" jail_foo_exec_stop="/bin/sh /etc/rc.shutdown" jail_bar_rootdir="/j/bar" jail_bar_hostname="bar.example.com" jail_bar_ip="192.168.0.2" jail_bar_devfs_enable="YES" jail_bar_mount_enable="YES" jail_bar_exec_start="/path/to/kjailer -v" jail_bar_exec_stop="/bin/sh -c 'killall kjailer && sleep 60'" ----------------------------------------------------------- # /etc/fstab.foo /v/foo /j/foo/v/foo nullfs rw 0 0 ----------------------------------------------------------- # /etc/fstab.bar /v/bar /j/bar/v/bar nullfs rw 0 0 ----------------------------------------------------------- Reviewed by: freebsd-hackers MFC after: 2 weeks
2004-12-14 14:36:35 +00:00
if [ -n "${jail_exec}" ]; then
# simple/backward-compatible execution
jail_exec_start="${jail_exec}"
jail_exec_stop=""
else
# flexible execution
if [ -z "${jail_exec_start}" ]; then
jail_exec_start="/bin/sh /etc/rc"
if [ -z "${jail_exec_stop}" ]; then
jail_exec_stop="/bin/sh /etc/rc.shutdown"
fi
fi
fi
# The default jail ruleset will be used by rc.subr if none is specified.
eval jail_ruleset=\"\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}\"
eval jail_devfs=\"\${jail_${_j}_devfs_enable:-${jail_devfs_enable}}\"
[ -z "${jail_devfs}" ] && jail_devfs="NO"
eval jail_fdescfs=\"\${jail_${_j}_fdescfs_enable:-${jail_fdescfs_enable}}\"
[ -z "${jail_fdescfs}" ] && jail_fdescfs="NO"
eval jail_procfs=\"\${jail_${_j}_procfs_enable:-${jail_procfs_enable}}\"
[ -z "${jail_procfs}" ] && jail_procfs="NO"
eval jail_mount=\"\${jail_${_j}_mount_enable:-${jail_mount_enable}}\"
[ -z "${jail_mount}" ] && jail_mount="NO"
# "/etc/fstab.${_j}" will be used for {,u}mount(8) if none is specified.
eval jail_fstab=\"\${jail_${_j}_fstab:-${jail_fstab}}\"
[ -z "${jail_fstab}" ] && jail_fstab="/etc/fstab.${_j}"
eval jail_flags=\"\${jail_${_j}_flags:-${jail_flags}}\"
[ -z "${jail_flags}" ] && jail_flags="-l -U root"
# Debugging aid
#
debug "$_j devfs enable: $jail_devfs"
debug "$_j fdescfs enable: $jail_fdescfs"
debug "$_j procfs enable: $jail_procfs"
debug "$_j mount enable: $jail_mount"
debug "$_j hostname: $jail_hostname"
debug "$_j ip: $jail_ip"
debug "$_j interface: $jail_interface"
debug "$_j root: $jail_rootdir"
debug "$_j devdir: $jail_devdir"
debug "$_j fdescdir: $jail_fdescdir"
debug "$_j procdir: $jail_procdir"
debug "$_j ruleset: $jail_ruleset"
debug "$_j fstab: $jail_fstab"
Improve the RC framework for the clean booting/shutdown of Jails: 1. Feature: for flexibility reasons and as a prerequisite to clean shutdowns, allow the configuration of a stop/shutdown command via rc.conf variable "jail_<name>_exec_stop" in addition to the start/boot command (rc.conf variable "jail_<name>_exec_start"). For backward compatibility reasons, rc.conf variable "jail_<name>_exec" is still supported, too. 2. Debug: Add the used boot/shutdown commands to the debug output of the /etc/rc.d/jail script, too. 3. Security: Run the Jail start/boot command in a cleaned environment to not leak information from the host to the Jail during startup. 4. Feature: Run the Jail stop/shutdown command "jail_<name>_exec_stop" on "/etc/rc.d/jail stop <name>" to allow a graceful shutdown of the Jail before its processes are just killed. 5. Bugfix: When killing the remaining Jail processes give the processes time to actually perform their termination sequence. Without this the subsequent umount(8) operations usually fail because the resources are still in use. Additionally, if after trying to TERM-inate the processes there are still processes hanging around, finally just KILL them. 6. Bugfix: In rc.shutdown, if running inside a Jail, skip the /etc/rc.d/* scripts which are flagged with the KEYWORD "nojail" to allow the correct operation of rc.shutdown under jail_<name>_exec_stop="/bin/sh /etc/rc.shutdown". This is analogous to what /etc/rc does inside a Jail. Now the following typical host-configuration for two Jails works as expected and correctly boots and shutdowns the Jails: ----------------------------------------------------------- # /etc/rc.conf: jail_enable="YES" jail_list="foo bar" jail_foo_rootdir="/j/foo" jail_foo_hostname="foo.example.com" jail_foo_ip="192.168.0.1" jail_foo_devfs_enable="YES" jail_foo_mount_enable="YES" jail_foo_exec_start="/bin/sh /etc/rc" jail_foo_exec_stop="/bin/sh /etc/rc.shutdown" jail_bar_rootdir="/j/bar" jail_bar_hostname="bar.example.com" jail_bar_ip="192.168.0.2" jail_bar_devfs_enable="YES" jail_bar_mount_enable="YES" jail_bar_exec_start="/path/to/kjailer -v" jail_bar_exec_stop="/bin/sh -c 'killall kjailer && sleep 60'" ----------------------------------------------------------- # /etc/fstab.foo /v/foo /j/foo/v/foo nullfs rw 0 0 ----------------------------------------------------------- # /etc/fstab.bar /v/bar /j/bar/v/bar nullfs rw 0 0 ----------------------------------------------------------- Reviewed by: freebsd-hackers MFC after: 2 weeks
2004-12-14 14:36:35 +00:00
debug "$_j exec start: $jail_exec_start"
debug "$_j exec stop: $jail_exec_stop"
debug "$_j flags: $jail_flags"
if [ -z "${jail_hostname}" ]; then
err 3 "$name: No hostname has been defined for ${_j}"
fi
if [ -z "${jail_rootdir}" ]; then
err 3 "$name: No root directory has been defined for ${_j}"
fi
if [ -z "${jail_ip}" ]; then
err 3 "$name: No IP address has been defined for ${_j}"
fi
}
# set_sysctl rc_knob mib msg
# If the mib sysctl is set according to what rc_knob
# specifies, this function does nothing. However if
# rc_knob is set differently than mib, then the mib
# is set accordingly and msg is displayed followed by
# an '=" sign and the word 'YES' or 'NO'.
#
set_sysctl()
{
_knob="$1"
_mib="$2"
_msg="$3"
_current=`${SYSCTL} -n $_mib 2>/dev/null`
if checkyesno $_knob ; then
if [ "$_current" -ne 1 ]; then
echo -n " ${_msg}=YES"
${SYSCTL_W} 1>/dev/null ${_mib}=1
fi
else
if [ "$_current" -ne 0 ]; then
echo -n " ${_msg}=NO"
${SYSCTL_W} 1>/dev/null ${_mib}=0
fi
fi
}
# jail_umount_fs
# This function unmounts certain special filesystems in the
# currently selected jail. The caller must call the init_variables()
# routine before calling this one.
#
jail_umount_fs()
{
if checkyesno jail_fdescfs; then
if [ -d "${jail_fdescdir}" ] ; then
umount -f ${jail_fdescdir} >/dev/null 2>&1
fi
fi
if checkyesno jail_devfs; then
if [ -d "${jail_devdir}" ] ; then
umount -f ${jail_devdir} >/dev/null 2>&1
fi
fi
if checkyesno jail_procfs; then
if [ -d "${jail_procdir}" ] ; then
umount -f ${jail_procdir} >/dev/null 2>&1
fi
fi
if checkyesno jail_mount; then
[ -f "${jail_fstab}" ] || warn "${jail_fstab} does not exist"
umount -a -F "${jail_fstab}" >/dev/null 2>&1
fi
}
jail_start()
{
echo -n 'Configuring jails:'
set_sysctl jail_set_hostname_allow security.jail.set_hostname_allowed \
set_hostname_allow
set_sysctl jail_socket_unixiproute_only \
security.jail.socket_unixiproute_only unixiproute_only
set_sysctl jail_sysvipc_allow security.jail.sysvipc_allowed \
sysvipc_allow
echo '.'
echo -n 'Starting jails:'
_tmp_dir=`mktemp -d /tmp/jail.XXXXXXXX` || \
err 3 "$name: Can't create temp dir, exiting..."
2003-10-13 08:20:55 +00:00
for _jail in ${jail_list}
do
init_variables $_jail
if [ -f /var/run/jail_${_jail}.id ]; then
echo -n " [${jail_hostname} already running (/var/run/jail_${_jail}.id exists)]"
continue;
fi
if [ -n "${jail_interface}" ]; then
ifconfig ${jail_interface} alias ${jail_ip} netmask 255.255.255.255
fi
if checkyesno jail_mount; then
info "Mounting fstab for jail ${_jail} (${jail_fstab})"
if [ ! -f "${jail_fstab}" ]; then
err 3 "$name: ${jail_fstab} does not exist"
fi
mount -a -F "${jail_fstab}"
fi
if checkyesno jail_devfs; then
# If devfs is already mounted here, skip it.
df -t devfs "${jail_devdir}" >/dev/null
if [ $? -ne 0 ]; then
info "Mounting devfs on ${jail_devdir}"
devfs_mount_jail "${jail_devdir}" ${jail_ruleset}
# Transitional symlink for old binaries
if [ ! -L "${jail_devdir}/log" ]; then
__pwd="`pwd`"
cd "${jail_devdir}"
ln -sf ../var/run/log log
cd "$__pwd"
fi
fi
# XXX - It seems symlinks don't work when there
# is a devfs(5) device of the same name.
# Jail console output
# __pwd="`pwd`"
# cd "${jail_devdir}"
# ln -sf ../var/log/console console
# cd "$__pwd"
fi
if checkyesno jail_fdescfs; then
info "Mounting fdescfs on ${jail_fdescdir}"
mount -t fdescfs fdesc "${jail_fdescdir}"
fi
if checkyesno jail_procfs; then
info "Mounting procfs onto ${jail_procdir}"
if [ -d "${jail_procdir}" ] ; then
mount -t procfs proc "${jail_procdir}"
fi
fi
_tmp_jail=${_tmp_dir}/jail.$$
eval jail ${jail_flags} -i ${jail_rootdir} ${jail_hostname} \
Improve the RC framework for the clean booting/shutdown of Jails: 1. Feature: for flexibility reasons and as a prerequisite to clean shutdowns, allow the configuration of a stop/shutdown command via rc.conf variable "jail_<name>_exec_stop" in addition to the start/boot command (rc.conf variable "jail_<name>_exec_start"). For backward compatibility reasons, rc.conf variable "jail_<name>_exec" is still supported, too. 2. Debug: Add the used boot/shutdown commands to the debug output of the /etc/rc.d/jail script, too. 3. Security: Run the Jail start/boot command in a cleaned environment to not leak information from the host to the Jail during startup. 4. Feature: Run the Jail stop/shutdown command "jail_<name>_exec_stop" on "/etc/rc.d/jail stop <name>" to allow a graceful shutdown of the Jail before its processes are just killed. 5. Bugfix: When killing the remaining Jail processes give the processes time to actually perform their termination sequence. Without this the subsequent umount(8) operations usually fail because the resources are still in use. Additionally, if after trying to TERM-inate the processes there are still processes hanging around, finally just KILL them. 6. Bugfix: In rc.shutdown, if running inside a Jail, skip the /etc/rc.d/* scripts which are flagged with the KEYWORD "nojail" to allow the correct operation of rc.shutdown under jail_<name>_exec_stop="/bin/sh /etc/rc.shutdown". This is analogous to what /etc/rc does inside a Jail. Now the following typical host-configuration for two Jails works as expected and correctly boots and shutdowns the Jails: ----------------------------------------------------------- # /etc/rc.conf: jail_enable="YES" jail_list="foo bar" jail_foo_rootdir="/j/foo" jail_foo_hostname="foo.example.com" jail_foo_ip="192.168.0.1" jail_foo_devfs_enable="YES" jail_foo_mount_enable="YES" jail_foo_exec_start="/bin/sh /etc/rc" jail_foo_exec_stop="/bin/sh /etc/rc.shutdown" jail_bar_rootdir="/j/bar" jail_bar_hostname="bar.example.com" jail_bar_ip="192.168.0.2" jail_bar_devfs_enable="YES" jail_bar_mount_enable="YES" jail_bar_exec_start="/path/to/kjailer -v" jail_bar_exec_stop="/bin/sh -c 'killall kjailer && sleep 60'" ----------------------------------------------------------- # /etc/fstab.foo /v/foo /j/foo/v/foo nullfs rw 0 0 ----------------------------------------------------------- # /etc/fstab.bar /v/bar /j/bar/v/bar nullfs rw 0 0 ----------------------------------------------------------- Reviewed by: freebsd-hackers MFC after: 2 weeks
2004-12-14 14:36:35 +00:00
${jail_ip} ${jail_exec_start} > ${_tmp_jail} 2>&1
if [ "$?" -eq 0 ] ; then
echo -n " $jail_hostname"
_jail_id=$(head -1 ${_tmp_jail})
tail +2 ${_tmp_jail} >${jail_rootdir}/var/log/console.log
echo ${_jail_id} > /var/run/jail_${_jail}.id
else
jail_umount_fs
if [ -n "${jail_interface}" ]; then
ifconfig ${jail_interface} -alias ${jail_ip}
fi
echo " cannot start jail \"${_jail}\": "
tail +2 ${_tmp_jail}
fi
rm -f ${_tmp_jail}
done
rmdir ${_tmp_dir}
echo '.'
}
jail_stop()
{
echo -n 'Stopping jails:'
for _jail in ${jail_list}
do
if [ -f "/var/run/jail_${_jail}.id" ]; then
_jail_id=$(cat /var/run/jail_${_jail}.id)
if [ ! -z "${_jail_id}" ]; then
init_variables $_jail
Improve the RC framework for the clean booting/shutdown of Jails: 1. Feature: for flexibility reasons and as a prerequisite to clean shutdowns, allow the configuration of a stop/shutdown command via rc.conf variable "jail_<name>_exec_stop" in addition to the start/boot command (rc.conf variable "jail_<name>_exec_start"). For backward compatibility reasons, rc.conf variable "jail_<name>_exec" is still supported, too. 2. Debug: Add the used boot/shutdown commands to the debug output of the /etc/rc.d/jail script, too. 3. Security: Run the Jail start/boot command in a cleaned environment to not leak information from the host to the Jail during startup. 4. Feature: Run the Jail stop/shutdown command "jail_<name>_exec_stop" on "/etc/rc.d/jail stop <name>" to allow a graceful shutdown of the Jail before its processes are just killed. 5. Bugfix: When killing the remaining Jail processes give the processes time to actually perform their termination sequence. Without this the subsequent umount(8) operations usually fail because the resources are still in use. Additionally, if after trying to TERM-inate the processes there are still processes hanging around, finally just KILL them. 6. Bugfix: In rc.shutdown, if running inside a Jail, skip the /etc/rc.d/* scripts which are flagged with the KEYWORD "nojail" to allow the correct operation of rc.shutdown under jail_<name>_exec_stop="/bin/sh /etc/rc.shutdown". This is analogous to what /etc/rc does inside a Jail. Now the following typical host-configuration for two Jails works as expected and correctly boots and shutdowns the Jails: ----------------------------------------------------------- # /etc/rc.conf: jail_enable="YES" jail_list="foo bar" jail_foo_rootdir="/j/foo" jail_foo_hostname="foo.example.com" jail_foo_ip="192.168.0.1" jail_foo_devfs_enable="YES" jail_foo_mount_enable="YES" jail_foo_exec_start="/bin/sh /etc/rc" jail_foo_exec_stop="/bin/sh /etc/rc.shutdown" jail_bar_rootdir="/j/bar" jail_bar_hostname="bar.example.com" jail_bar_ip="192.168.0.2" jail_bar_devfs_enable="YES" jail_bar_mount_enable="YES" jail_bar_exec_start="/path/to/kjailer -v" jail_bar_exec_stop="/bin/sh -c 'killall kjailer && sleep 60'" ----------------------------------------------------------- # /etc/fstab.foo /v/foo /j/foo/v/foo nullfs rw 0 0 ----------------------------------------------------------- # /etc/fstab.bar /v/bar /j/bar/v/bar nullfs rw 0 0 ----------------------------------------------------------- Reviewed by: freebsd-hackers MFC after: 2 weeks
2004-12-14 14:36:35 +00:00
if [ -n "${jail_exec_stop}" ]; then
eval env -i /usr/sbin/jexec ${_jail_id} ${jail_exec_stop} \
>> ${jail_rootdir}/var/log/console.log 2>&1
fi
killall -j ${_jail_id} -TERM > /dev/null 2>&1
Improve the RC framework for the clean booting/shutdown of Jails: 1. Feature: for flexibility reasons and as a prerequisite to clean shutdowns, allow the configuration of a stop/shutdown command via rc.conf variable "jail_<name>_exec_stop" in addition to the start/boot command (rc.conf variable "jail_<name>_exec_start"). For backward compatibility reasons, rc.conf variable "jail_<name>_exec" is still supported, too. 2. Debug: Add the used boot/shutdown commands to the debug output of the /etc/rc.d/jail script, too. 3. Security: Run the Jail start/boot command in a cleaned environment to not leak information from the host to the Jail during startup. 4. Feature: Run the Jail stop/shutdown command "jail_<name>_exec_stop" on "/etc/rc.d/jail stop <name>" to allow a graceful shutdown of the Jail before its processes are just killed. 5. Bugfix: When killing the remaining Jail processes give the processes time to actually perform their termination sequence. Without this the subsequent umount(8) operations usually fail because the resources are still in use. Additionally, if after trying to TERM-inate the processes there are still processes hanging around, finally just KILL them. 6. Bugfix: In rc.shutdown, if running inside a Jail, skip the /etc/rc.d/* scripts which are flagged with the KEYWORD "nojail" to allow the correct operation of rc.shutdown under jail_<name>_exec_stop="/bin/sh /etc/rc.shutdown". This is analogous to what /etc/rc does inside a Jail. Now the following typical host-configuration for two Jails works as expected and correctly boots and shutdowns the Jails: ----------------------------------------------------------- # /etc/rc.conf: jail_enable="YES" jail_list="foo bar" jail_foo_rootdir="/j/foo" jail_foo_hostname="foo.example.com" jail_foo_ip="192.168.0.1" jail_foo_devfs_enable="YES" jail_foo_mount_enable="YES" jail_foo_exec_start="/bin/sh /etc/rc" jail_foo_exec_stop="/bin/sh /etc/rc.shutdown" jail_bar_rootdir="/j/bar" jail_bar_hostname="bar.example.com" jail_bar_ip="192.168.0.2" jail_bar_devfs_enable="YES" jail_bar_mount_enable="YES" jail_bar_exec_start="/path/to/kjailer -v" jail_bar_exec_stop="/bin/sh -c 'killall kjailer && sleep 60'" ----------------------------------------------------------- # /etc/fstab.foo /v/foo /j/foo/v/foo nullfs rw 0 0 ----------------------------------------------------------- # /etc/fstab.bar /v/bar /j/bar/v/bar nullfs rw 0 0 ----------------------------------------------------------- Reviewed by: freebsd-hackers MFC after: 2 weeks
2004-12-14 14:36:35 +00:00
sleep 1
killall -j ${_jail_id} -KILL > /dev/null 2>&1
jail_umount_fs
echo -n " $jail_hostname"
fi
if [ -n "${jail_interface}" ]; then
ifconfig ${jail_interface} -alias ${jail_ip}
fi
rm /var/run/jail_${_jail}.id
else
echo " cannot stop jail ${_jail}. No jail id in /var/run"
fi
done
echo '.'
}
load_rc_config $name
cmd="$1"
if [ $# -gt 0 ]; then
shift
fi
if [ -n "$*" ]; then
jail_list="$*"
fi
run_rc_command "${cmd}"