mirror of
https://git.FreeBSD.org/ports.git
synced 2025-02-06 11:41:52 +00:00
Jailrc is an improved startup/shutdown script for FreeBSD jails.
It contains the following changes to the original /etc/rc.d/jail script: - parameters support: you can specify any parameters supported by jail(8) - ZFS support: you can deletate ZFS datasets to jails - jails are not identified by a file in /var/spool/jail anymore - two new commands "create" and "remove" to manage persistent jails Please refer to the README file for more information. Martin Matuska <mm_at_FreeBSD_dot_org>
This commit is contained in:
parent
c5f3e737c1
commit
daad2691f8
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=285300
@ -378,6 +378,7 @@
|
||||
SUBDIR += jailctl
|
||||
SUBDIR += jailer
|
||||
SUBDIR += jailme
|
||||
SUBDIR += jailrc
|
||||
SUBDIR += jailuser
|
||||
SUBDIR += jailutils
|
||||
SUBDIR += javaservicewrapper
|
||||
|
30
sysutils/jailrc/Makefile
Normal file
30
sysutils/jailrc/Makefile
Normal file
@ -0,0 +1,30 @@
|
||||
# New ports collection makefile for: jailrc
|
||||
# Date created: 8 November 2011
|
||||
# Whom: Martin Matuska <mm@FreeBSD.org>
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
PORTNAME= jailrc
|
||||
PORTVERSION= 1.0
|
||||
CATEGORIES= sysutils
|
||||
MASTER_SITES= #
|
||||
DISTFILES= #
|
||||
|
||||
MAINTAINER= mm@FreeBSD.org
|
||||
COMMENT= Improved jail startup/shutdown script
|
||||
|
||||
NO_BUILD= yes
|
||||
NO_INSTALL= yes
|
||||
|
||||
USE_RC_SUBR= jailrc
|
||||
|
||||
PORTDOCS= *
|
||||
|
||||
post-install:
|
||||
.if !defined(NOPORTDOCS)
|
||||
@${MKDIR} ${DOCSDIR}
|
||||
@${INSTALL_DATA} ${FILESDIR}/README ${DOCSDIR}/README
|
||||
.endif
|
||||
|
||||
.include <bsd.port.mk>
|
53
sysutils/jailrc/files/README
Normal file
53
sysutils/jailrc/files/README
Normal file
@ -0,0 +1,53 @@
|
||||
# Jailrc README
|
||||
# Martin Matuska <mm@FreeBSD.org>
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
Jailrc is an improved startup/shutdown script for FreeBSD jails.
|
||||
|
||||
It contains the following changes to the original /etc/rc.d/jail script:
|
||||
|
||||
- parameters support: you can specify parameters supported by jail(8)
|
||||
- ZFS support: you can deletate ZFS datasets to jails
|
||||
- jails are not identified by a file in /var/spool/jail anymore
|
||||
- two new commands "create" and "remove" to manage persistent jails
|
||||
|
||||
To start jails with the jailrc script instead of /etc/rc.d/jail, use
|
||||
instead of jail_enable="YES" the keyword jailrc_enable="YES".
|
||||
|
||||
------------------------------------------------------------------
|
||||
Jailrc reads all settings supported by /etc/rc.d/jail
|
||||
(see /etc/defaults/rc.conf) and the following additional settings:
|
||||
|
||||
jail_example_name="" # Set to desired jail name
|
||||
# defaults to the name in "jail_list"
|
||||
jail_example_persist="" # Set to YES 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.
|
||||
|
||||
------------------------------------------------------------------
|
||||
Example rc.conf configuration with IPv4, IPv6 and a fixed jail ID:
|
||||
|
||||
jail_enable="NO"
|
||||
jailrc_enable="YES"
|
||||
jail_list="test"
|
||||
jail_test_hostname="test.bb.cc"
|
||||
jail_test_rootdir="/jail/test"
|
||||
jail_test_ip="192.168.0.2,2001:db8:2:1::2"
|
||||
jail_test_devfs_enable="YES"
|
||||
jail_test_params="jid=8 enforce_statfs=1 allow.raw_sockets=1"
|
||||
|
||||
------------------------------------------------------------------
|
||||
To enable the ZFS device (/dev/zfs) in jails, add the following lines
|
||||
to your devfs.rules configuration file:
|
||||
|
||||
[devfsrules_jail_zfs=5]
|
||||
add include $devfsrules_jail
|
||||
add path zfs unhide
|
923
sysutils/jailrc/files/jailrc.in
Normal file
923
sysutils/jailrc/files/jailrc.in
Normal file
@ -0,0 +1,923 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
# PROVIDE: jail
|
||||
# REQUIRE: LOGIN cleanvar
|
||||
# BEFORE: securelevel
|
||||
# KEYWORD: nojail shutdown
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="jailrc"
|
||||
rcvar=`set_rcvar`
|
||||
|
||||
start_precmd="jail_prestart"
|
||||
start_cmd="jail_start"
|
||||
stop_cmd="jail_stop"
|
||||
extra_commands="status create remove"
|
||||
status_cmd="jail_status"
|
||||
create_cmd="jail_create"
|
||||
remove_cmd="jail_remove"
|
||||
|
||||
# init_name _j
|
||||
# Initialize the name variable for jail _j.
|
||||
#
|
||||
init_name()
|
||||
{
|
||||
_j="$1"
|
||||
|
||||
if [ -z "$_j" ]; then
|
||||
warn "init_name: you must specify a jail"
|
||||
return
|
||||
fi
|
||||
|
||||
eval _name=\"\$jail_${_j}_name\"
|
||||
|
||||
if [ -z "${_name}" ]; then
|
||||
_name=${_j}
|
||||
fi
|
||||
|
||||
# Debugging aid
|
||||
debug "$_j name: $_name"
|
||||
}
|
||||
|
||||
# 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 _rootdir=\"\$jail_${_j}_rootdir\"
|
||||
_devdir="${_rootdir}/dev"
|
||||
_fdescdir="${_devdir}/fd"
|
||||
_procdir="${_rootdir}/proc"
|
||||
eval _hostname=\"\$jail_${_j}_hostname\"
|
||||
eval _ip=\"\$jail_${_j}_ip\"
|
||||
eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
|
||||
eval _exec=\"\$jail_${_j}_exec\"
|
||||
eval _params=\"\${jail_${_j}_params:-${jail_params}}\"
|
||||
eval _zfs=\"\${jail_${_j}_zfs:-}\"
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval _exec_prestart${i}=\"\${jail_${_j}_exec_prestart${i}:-\${jail_exec_prestart${i}}}\"
|
||||
[ -z "$(eval echo \"\$_exec_prestart${i}\")" ] && break
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
eval _exec_start=\"\${jail_${_j}_exec_start:-${jail_exec_start}}\"
|
||||
|
||||
i=1
|
||||
while : ; do
|
||||
eval _exec_afterstart${i}=\"\${jail_${_j}_exec_afterstart${i}:-\${jail_exec_afterstart${i}}}\"
|
||||
[ -z "$(eval echo \"\$_exec_afterstart${i}\")" ] && break
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval _exec_poststart${i}=\"\${jail_${_j}_exec_poststart${i}:-\${jail_exec_poststart${i}}}\"
|
||||
[ -z "$(eval echo \"\$_exec_poststart${i}\")" ] && break
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval _exec_prestop${i}=\"\${jail_${_j}_exec_prestop${i}:-\${jail_exec_prestop${i}}}\"
|
||||
[ -z "$(eval echo \"\$_exec_prestop${i}\")" ] && break
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
eval _exec_stop=\"\${jail_${_j}_exec_stop:-${jail_exec_stop}}\"
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval _exec_poststop${i}=\"\${jail_${_j}_exec_poststop${i}:-\${jail_exec_poststop${i}}}\"
|
||||
[ -z "$(eval echo \"\$_exec_poststop${i}\")" ] && break
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
if [ -n "${_exec}" ]; then
|
||||
# simple/backward-compatible execution
|
||||
_exec_start="${_exec}"
|
||||
_exec_stop=""
|
||||
else
|
||||
# flexible execution
|
||||
if [ -z "${_exec_start}" ]; then
|
||||
_exec_start="/bin/sh /etc/rc"
|
||||
if [ -z "${_exec_stop}" ]; then
|
||||
_exec_stop="/bin/sh /etc/rc.shutdown"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# The default jail ruleset will be used by rc.subr if none is specified.
|
||||
if [ -n "${_zfs}" ]; then
|
||||
eval jail_devfs_ruleset=\"${jail_devfs_ruleset:-devfsrules_jail_zfs}\"
|
||||
else
|
||||
eval jail_devfs_ruleset=\"${jail_devfs_ruleset:-devfsrules_jail}\"
|
||||
fi
|
||||
eval _ruleset=\"\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}\"
|
||||
eval _devfs=\"\${jail_${_j}_devfs_enable:-${jail_devfs_enable}}\"
|
||||
[ -z "${_devfs}" ] && _devfs="NO"
|
||||
eval _fdescfs=\"\${jail_${_j}_fdescfs_enable:-${jail_fdescfs_enable}}\"
|
||||
[ -z "${_fdescfs}" ] && _fdescfs="NO"
|
||||
eval _procfs=\"\${jail_${_j}_procfs_enable:-${jail_procfs_enable}}\"
|
||||
[ -z "${_procfs}" ] && _procfs="NO"
|
||||
|
||||
eval _mount=\"\${jail_${_j}_mount_enable:-${jail_mount_enable}}\"
|
||||
[ -z "${_mount}" ] && _mount="NO"
|
||||
# "/etc/fstab.${_j}" will be used for {,u}mount(8) if none is specified.
|
||||
eval _fstab=\"\${jail_${_j}_fstab:-${jail_fstab}}\"
|
||||
[ -z "${_fstab}" ] && _fstab="/etc/fstab.${_j}"
|
||||
eval _flags=\"\${jail_${_j}_flags:-${jail_flags}}\"
|
||||
[ -z "${_flags}" ] && _flags="-l -U root"
|
||||
eval _consolelog=\"\${jail_${_j}_consolelog:-${jail_consolelog}}\"
|
||||
[ -z "${_consolelog}" ] && _consolelog="/var/log/jail_${_j}_console.log"
|
||||
eval _fib=\"\${jail_${_j}_fib:-${jail_fib}}\"
|
||||
eval _persist=\"\${jail_${_j}_persist:-${jail_persist}}\"
|
||||
[ -z "${_persist}" ] && _persist="NO"
|
||||
|
||||
# Debugging aid
|
||||
#
|
||||
debug "$_j devfs enable: $_devfs"
|
||||
debug "$_j fdescfs enable: $_fdescfs"
|
||||
debug "$_j procfs enable: $_procfs"
|
||||
debug "$_j mount enable: $_mount"
|
||||
debug "$_j hostname: $_hostname"
|
||||
debug "$_j ip: $_ip"
|
||||
jail_show_addresses ${_j}
|
||||
debug "$_j interface: $_interface"
|
||||
debug "$_j fib: $_fib"
|
||||
debug "$_j root: $_rootdir"
|
||||
debug "$_j devdir: $_devdir"
|
||||
debug "$_j fdescdir: $_fdescdir"
|
||||
debug "$_j procdir: $_procdir"
|
||||
debug "$_j ruleset: $_ruleset"
|
||||
debug "$_j fstab: $_fstab"
|
||||
debug "$_j persist: $_persist"
|
||||
debug "$_j params: $_params"
|
||||
debug "$_j zfs: $_zfs"
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval out=\"\${_exec_prestart${i}:-''}\"
|
||||
if [ -z "$out" ]; then
|
||||
break
|
||||
fi
|
||||
debug "$_j exec pre-start #${i}: ${out}"
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
debug "$_j exec start: $_exec_start"
|
||||
|
||||
i=1
|
||||
while : ; do
|
||||
eval out=\"\${_exec_afterstart${i}:-''}\"
|
||||
|
||||
if [ -z "$out" ]; then
|
||||
break;
|
||||
fi
|
||||
|
||||
debug "$_j exec after start #${i}: ${out}"
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval out=\"\${_exec_poststart${i}:-''}\"
|
||||
if [ -z "$out" ]; then
|
||||
break
|
||||
fi
|
||||
debug "$_j exec post-start #${i}: ${out}"
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval out=\"\${_exec_prestop${i}:-''}\"
|
||||
if [ -z "$out" ]; then
|
||||
break
|
||||
fi
|
||||
debug "$_j exec pre-stop #${i}: ${out}"
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
debug "$_j exec stop: $_exec_stop"
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval out=\"\${_exec_poststop${i}:-''}\"
|
||||
if [ -z "$out" ]; then
|
||||
break
|
||||
fi
|
||||
debug "$_j exec post-stop #${i}: ${out}"
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
debug "$_j flags: $_flags"
|
||||
debug "$_j consolelog: $_consolelog"
|
||||
|
||||
_params="${_params} name=${_name}"
|
||||
[ -n "${_hostname}" ] && _params="${_params} host.hostname=${_hostname}"
|
||||
|
||||
if [ -z "${_rootdir}" ]; then
|
||||
err 3 "$name: No root directory has been defined for ${_j}"
|
||||
else
|
||||
_params="${_params} path=${_rootdir}"
|
||||
fi
|
||||
|
||||
# Compatibility with old sysctl knobs
|
||||
#
|
||||
eval _set_hostname_allow="\${jail_${_j}_set_hostname_allow:-${jail_set_hostname_allow}}"
|
||||
eval _socket_unixiproute_only="\${jail_${_j}_socket_unixiproute_only:-${jail_socket_unixiproute_only}}"
|
||||
eval _sysvipc_allow="\${jail_${_j}_sysvipc_allow:-${jail_sysvipc_allow}}"
|
||||
[ -z "${_set_hostname_allow}" ] && _set_hostname_allow="YES"
|
||||
[ -z "${_socket_unixiproute_only}" ] && _socket_unixiproute_only="YES"
|
||||
[ -z "${_sysvipc_allow}" ] && _sysvipc_allow="NO"
|
||||
|
||||
if ! checkyesno _set_hostname_allow; then
|
||||
_params="${_params} allow.set_hostname=0"
|
||||
fi
|
||||
|
||||
if ! checkyesno _socket_unixiproute_only; then
|
||||
_params="${_params} allow.socket_af=1"
|
||||
fi
|
||||
|
||||
if checkyesno _sysvipc_allow; then
|
||||
_params="${_params} allow.sysvipc=1"
|
||||
fi
|
||||
}
|
||||
|
||||
# is_current_mountpoint()
|
||||
# Is the directory mount point for a currently mounted file
|
||||
# system?
|
||||
#
|
||||
is_current_mountpoint()
|
||||
{
|
||||
local _dir _dir2
|
||||
|
||||
_dir=$1
|
||||
|
||||
_dir=`echo $_dir | sed -Ee 's#//+#/#g' -e 's#/$##'`
|
||||
[ ! -d "${_dir}" ] && return 1
|
||||
_dir2=`df ${_dir} | tail +2 | awk '{ print $6 }'`
|
||||
[ "${_dir}" = "${_dir2}" ]
|
||||
return $?
|
||||
}
|
||||
|
||||
# is_symlinked_mountpoint()
|
||||
# Is a mount point, or any of its parent directories, a symlink?
|
||||
#
|
||||
is_symlinked_mountpoint()
|
||||
{
|
||||
local _dir
|
||||
|
||||
_dir=$1
|
||||
|
||||
[ -L "$_dir" ] && return 0
|
||||
[ "$_dir" = "/" ] && return 1
|
||||
is_symlinked_mountpoint `dirname $_dir`
|
||||
return $?
|
||||
}
|
||||
|
||||
# secure_umount
|
||||
# Try to unmount a mount point without being vulnerable to
|
||||
# symlink attacks.
|
||||
#
|
||||
secure_umount()
|
||||
{
|
||||
local _dir
|
||||
|
||||
_dir=$1
|
||||
|
||||
if is_current_mountpoint ${_dir}; then
|
||||
umount -f ${_dir} >/dev/null 2>&1
|
||||
else
|
||||
debug "Nothing mounted on ${_dir} - not unmounting"
|
||||
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()
|
||||
{
|
||||
local _device _mountpt _rest
|
||||
|
||||
if checkyesno _fdescfs; then
|
||||
if [ -d "${_fdescdir}" ] ; then
|
||||
secure_umount ${_fdescdir}
|
||||
fi
|
||||
fi
|
||||
if checkyesno _devfs; then
|
||||
if [ -d "${_devdir}" ] ; then
|
||||
secure_umount ${_devdir}
|
||||
fi
|
||||
fi
|
||||
if checkyesno _procfs; then
|
||||
if [ -d "${_procdir}" ] ; then
|
||||
secure_umount ${_procdir}
|
||||
fi
|
||||
fi
|
||||
if checkyesno _mount; then
|
||||
[ -f "${_fstab}" ] || warn "${_fstab} does not exist"
|
||||
tail -r ${_fstab} | while read _device _mountpt _rest; do
|
||||
case ":${_device}" in
|
||||
:#* | :)
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
secure_umount ${_mountpt}
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# jail_mount_fstab()
|
||||
# Mount file systems from a per jail fstab while trying to
|
||||
# secure against symlink attacks at the mount points.
|
||||
#
|
||||
# If we are certain we cannot secure against symlink attacks we
|
||||
# do not mount all of the file systems (since we cannot just not
|
||||
# mount the file system with the problematic mount point).
|
||||
#
|
||||
# The caller must call the init_variables() routine before
|
||||
# calling this one.
|
||||
#
|
||||
jail_mount_fstab()
|
||||
{
|
||||
local _device _mountpt _field3 _field4 _field5 _field6
|
||||
|
||||
while read _device _mountpt _field3 _field4 _field5 _field6; do
|
||||
case ":${_device}:" in
|
||||
:#*:|::)
|
||||
# empty line or comment
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
if [ -z "${_field5}" ]; then
|
||||
# a fstab entry needs at least 5 fields
|
||||
# everything else is suspicious
|
||||
warn "${_device} ${_mountpt} ${_field3} ${_field4} ${_field5} ${_field6} not conforming to 5 or more whitespace separated fields"
|
||||
return
|
||||
fi
|
||||
if is_symlinked_mountpoint ${_mountpt}; then
|
||||
warn "${_mountpt} has symlink as parent - not mounting from ${_fstab}"
|
||||
return
|
||||
fi
|
||||
done <${_fstab}
|
||||
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
|
||||
debug "${j} jailing zfs dataset: ${_ds}"
|
||||
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
|
||||
debug "${j} unjailing zfs dataset: ${_ds}"
|
||||
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().
|
||||
#
|
||||
jail_show_addresses()
|
||||
{
|
||||
local _j _type alias
|
||||
_j="$1"
|
||||
alias=0
|
||||
|
||||
if [ -z "${_j}" ]; then
|
||||
warn "jail_show_addresses: you must specify a jail"
|
||||
return
|
||||
fi
|
||||
|
||||
while : ; do
|
||||
eval _addr=\"\$jail_${_j}_ip_multi${alias}\"
|
||||
if [ -n "${_addr}" ]; then
|
||||
debug "${_j} ip_multi${alias}: $_addr"
|
||||
alias=$((${alias} + 1))
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# jail_extract_address argument
|
||||
# The second argument is the string from one of the _ip
|
||||
# or the _multi variables. In case of a comma separated list
|
||||
# only one argument must be passed in at a time.
|
||||
# The function alters the _type, _iface, _addr and _mask variables.
|
||||
#
|
||||
jail_extract_address()
|
||||
{
|
||||
local _i
|
||||
_i=$1
|
||||
|
||||
if [ -z "${_i}" ]; then
|
||||
warn "jail_extract_address: called without input"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if we have an interface prefix given and split into
|
||||
# iFace and rest.
|
||||
case "${_i}" in
|
||||
*\|*) # ifN|.. prefix there
|
||||
_iface=${_i%%|*}
|
||||
_r=${_i##*|}
|
||||
;;
|
||||
*) _iface=""
|
||||
_r=${_i}
|
||||
;;
|
||||
esac
|
||||
|
||||
# In case the IP has no interface given, check if we have a global one.
|
||||
_iface=${_iface:-${_interface}}
|
||||
|
||||
# Set address, cut off any prefix/netmask/prefixlen.
|
||||
_addr=${_r}
|
||||
_addr=${_addr%%[/ ]*}
|
||||
|
||||
# Theoretically we can return here if interface is not set,
|
||||
# as we only care about the _mask if we call ifconfig.
|
||||
# This is not done because we may want to santize IP addresses
|
||||
# based on _type later, and optionally change the type as well.
|
||||
|
||||
# Extract the prefix/netmask/prefixlen part by cutting off the address.
|
||||
_mask=${_r}
|
||||
_mask=`expr "${_mask}" : "${_addr}\(.*\)"`
|
||||
|
||||
# Identify type {inet,inet6}.
|
||||
case "${_addr}" in
|
||||
*\.*\.*\.*) _type="inet" ;;
|
||||
*:*) _type="inet6" ;;
|
||||
*) warn "jail_extract_address: type not identified"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Handle the special /netmask instead of /prefix or
|
||||
# "netmask xxx" case for legacy IP.
|
||||
# We do NOT support shortend class-full netmasks.
|
||||
if [ "${_type}" = "inet" ]; then
|
||||
case "${_mask}" in
|
||||
/*\.*\.*\.*) _mask=" netmask ${_mask#/}" ;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
# In case _mask is still not set use /32.
|
||||
_mask=${_mask:-/32}
|
||||
|
||||
elif [ "${_type}" = "inet6" ]; then
|
||||
# In case _maske is not set for IPv6, use /128.
|
||||
_mask=${_mask:-/128}
|
||||
fi
|
||||
}
|
||||
|
||||
# jail_handle_ips_option {add,del} input
|
||||
# Handle a single argument imput which can be a comma separated
|
||||
# list of addresses (theoretically with an option interface and
|
||||
# prefix/netmask/prefixlen).
|
||||
#
|
||||
jail_handle_ips_option()
|
||||
{
|
||||
local _x _action _type _i
|
||||
_action=$1
|
||||
_x=$2
|
||||
|
||||
if [ -z "${_x}" ]; then
|
||||
# No IP given. This can happen for the primary address
|
||||
# of each address family.
|
||||
return
|
||||
fi
|
||||
|
||||
# Loop, in case we find a comma separated list, we need to handle
|
||||
# each argument on its own.
|
||||
while [ ${#_x} -gt 0 ]; do
|
||||
case "${_x}" in
|
||||
*,*) # Extract the first argument and strip it off the list.
|
||||
_i=`expr "${_x}" : '^\([^,]*\)'`
|
||||
_x=`expr "${_x}" : "^[^,]*,\(.*\)"`
|
||||
;;
|
||||
*) _i=${_x}
|
||||
_x=""
|
||||
;;
|
||||
esac
|
||||
|
||||
_type=""
|
||||
_iface=""
|
||||
_addr=""
|
||||
_mask=""
|
||||
jail_extract_address "${_i}"
|
||||
|
||||
# make sure we got an address.
|
||||
case "${_addr}" in
|
||||
"") continue ;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
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
|
||||
# and if we could correctly parse everything.
|
||||
case "${_iface}" in
|
||||
"") continue ;;
|
||||
esac
|
||||
|
||||
case "${_action}" in
|
||||
add) ifconfig ${_iface} ${_type} ${_addr}${_mask} alias
|
||||
;;
|
||||
del) # When removing the IP, ignore the _mask.
|
||||
ifconfig ${_iface} ${_type} ${_addr} -alias
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# jail_ips {add,del}
|
||||
# Extract the comma separated list of addresses and return them
|
||||
# for the jail command.
|
||||
# Handle more than one address via the _multi option as well.
|
||||
# If an interface is given also add/remove an alias for the
|
||||
# address with an optional netmask.
|
||||
#
|
||||
jail_ips()
|
||||
{
|
||||
local _action
|
||||
_action=$1
|
||||
|
||||
case "${_action}" in
|
||||
add) ;;
|
||||
del) ;;
|
||||
*) warn "jail_ips: invalid action '${_action}'"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
# Handle addresses.
|
||||
jail_handle_ips_option ${_action} "${_ip}"
|
||||
# Handle jail_xxx_ip_multi<N>
|
||||
alias=0
|
||||
while : ; do
|
||||
eval _x=\"\$jail_${_jail}_ip_multi${alias}\"
|
||||
case "${_x}" in
|
||||
"") break ;;
|
||||
*) jail_handle_ips_option ${_action} "${_x}"
|
||||
alias=$((${alias} + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
jail_prestart()
|
||||
{
|
||||
if checkyesno jail_parallel_start; then
|
||||
command_args='&'
|
||||
fi
|
||||
}
|
||||
|
||||
jail_init()
|
||||
{
|
||||
_jail=$1
|
||||
init_name $_jail
|
||||
init_variables $_jail
|
||||
_jail_id="$(jls -j ${_name} jid 2>/dev/null)"
|
||||
if [ -n "${_jail_id}" ]; then
|
||||
return 1
|
||||
fi
|
||||
_addrl=""
|
||||
_addrl6=""
|
||||
jail_ips "add"
|
||||
|
||||
[ -n "${_addrl}" ] && _params="${_params} ip4.addr=${_addrl}"
|
||||
[ -n "${_addrl6}" ] && _params="${_params} ip6.addr=${_addrl6}"
|
||||
|
||||
if [ -n "${_fib}" ]; then
|
||||
_setfib="setfib -F '${_fib}'"
|
||||
else
|
||||
_setfib=""
|
||||
fi
|
||||
if checkyesno _mount; then
|
||||
info "Mounting fstab for jail ${_jail} (${_fstab})"
|
||||
if [ ! -f "${_fstab}" ]; then
|
||||
err 3 "$name: ${_fstab} does not exist"
|
||||
fi
|
||||
jail_mount_fstab
|
||||
fi
|
||||
if checkyesno _devfs; then
|
||||
# If devfs is already mounted here, skip it.
|
||||
df -t devfs "${_devdir}" >/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
if is_symlinked_mountpoint ${_devdir}; then
|
||||
warn "${_devdir} has symlink as parent - not starting jail ${_jail}"
|
||||
return 2
|
||||
fi
|
||||
info "Mounting devfs on ${_devdir}"
|
||||
devfs_mount_jail "${_devdir}" ${_ruleset}
|
||||
# Transitional symlink for old binaries
|
||||
if [ ! -L "${_devdir}/log" ]; then
|
||||
__pwd="`pwd`"
|
||||
cd "${_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 "${_devdir}"
|
||||
# ln -sf ../var/log/console console
|
||||
# cd "$__pwd"
|
||||
fi
|
||||
if checkyesno _fdescfs; then
|
||||
if is_symlinked_mountpoint ${_fdescdir}; then
|
||||
warn "${_fdescdir} has symlink as parent, not mounting"
|
||||
else
|
||||
info "Mounting fdescfs on ${_fdescdir}"
|
||||
mount -t fdescfs fdesc "${_fdescdir}"
|
||||
fi
|
||||
fi
|
||||
if checkyesno _procfs; then
|
||||
if is_symlinked_mountpoint ${_procdir}; then
|
||||
warn "${_procdir} has symlink as parent, not mounting"
|
||||
else
|
||||
info "Mounting procfs onto ${_procdir}"
|
||||
if [ -d "${_procdir}" ] ; then
|
||||
mount -t procfs proc "${_procdir}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
_jail_id=`${_setfib} jail -i ${_flags} -c \
|
||||
${_params} persist=1`
|
||||
|
||||
if [ -n "${_jail_id}" ]; then
|
||||
jail_zfs_jailin
|
||||
return 0
|
||||
else
|
||||
return 2
|
||||
fi
|
||||
}
|
||||
|
||||
jail_destroy()
|
||||
{
|
||||
_jail=$1
|
||||
init_name $_jail
|
||||
init_variables $_jail
|
||||
_jail_id="$(jls -j ${_name} jid 2>/dev/null)"
|
||||
if [ -z "${_jail_id}" ]; then
|
||||
return 1
|
||||
fi
|
||||
jail -m jid=${_jail_id} persist=1
|
||||
killall -j ${_jail_id} -TERM > /dev/null 2>&1
|
||||
sleep 1
|
||||
killall -j ${_jail_id} -KILL > /dev/null 2>&1
|
||||
|
||||
jail_umount_fs
|
||||
jail_zfs_jailout
|
||||
jail -m jid="${_jail_id}" persist=0
|
||||
return 0
|
||||
}
|
||||
|
||||
jail_create()
|
||||
{
|
||||
echo -n 'Creating jails:'
|
||||
for _jail in ${jail_list}
|
||||
do
|
||||
init_name $_jail
|
||||
init_variables $_jail
|
||||
jail_init $_jail
|
||||
_ret=$?
|
||||
if [ "$_ret" -eq 0 ]; then
|
||||
echo -n " ${_jail}"
|
||||
elif [ "$_ret" -eq 1 ]; then
|
||||
echo -n " [${_jail} already exists (JID: ${_jail_id})]"
|
||||
else
|
||||
echo -n "[${_jail} init error]"
|
||||
fi
|
||||
done
|
||||
echo "."
|
||||
}
|
||||
|
||||
jail_remove()
|
||||
{
|
||||
echo -n 'Removing jails:'
|
||||
for _jail in ${jail_list}
|
||||
do
|
||||
init_name $_jail
|
||||
_jail_id="$(jls -j ${_name} jid 2>/dev/null)"
|
||||
if [ -z "${_jail_id}" ]; then
|
||||
continue
|
||||
elif `pgrep -j ${_jail_id} >/dev/null 2>&1`; then
|
||||
echo -n " [${_jail} has running processes (JID: ${_jail_id})]"
|
||||
continue
|
||||
fi
|
||||
jail_destroy $_jail
|
||||
if [ "$?" -eq 0 ] ; then
|
||||
echo -n " ${_jail}"
|
||||
fi
|
||||
done
|
||||
echo "."
|
||||
}
|
||||
|
||||
jail_start()
|
||||
{
|
||||
echo -n 'Starting jails:'
|
||||
_tmp_dir=`mktemp -d /tmp/jail.XXXXXXXX` || \
|
||||
err 3 "$name: Can't create temp dir, exiting..."
|
||||
|
||||
for _jail in ${jail_list}
|
||||
do
|
||||
init_name $_jail
|
||||
init_variables $_jail
|
||||
_jail_id="$(jls -j ${_name} jid 2>/dev/null)"
|
||||
if [ -n "${_jail_id}" ]; then
|
||||
if `pgrep -j ${_jail_id} >/dev/null 2>&1`; then
|
||||
echo -n " [${_jail} already running (JID: ${_jail_id})]"
|
||||
continue
|
||||
fi
|
||||
else
|
||||
jail_init $_jail
|
||||
if [ "$?" -ne 0 ] ; then
|
||||
echo -n " [${_jail} initialization error]"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
_tmp_jail=${_tmp_dir}/jail.$$
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval out=\"\${_exec_prestart${i}:-''}\"
|
||||
[ -z "$out" ] && break
|
||||
${out}
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
eval jail ${_flags} -m jid="${_jail_id}" \
|
||||
command="${_exec_start}" > ${_tmp_jail} 2>&1 \
|
||||
</dev/null
|
||||
if [ "$?" -eq 0 ] ; then
|
||||
if ! checkyesno _persist; then
|
||||
jail -m jid="${_jail_id}" persist=0
|
||||
fi
|
||||
i=1
|
||||
while : ; do
|
||||
eval out=\"\${_exec_afterstart${i}:-''}\"
|
||||
|
||||
if [ -z "$out" ]; then
|
||||
break;
|
||||
fi
|
||||
|
||||
jexec "${_jail_id}" ${out}
|
||||
i=$((i + 1))
|
||||
done
|
||||
echo -n " $_jail"
|
||||
tail +2 ${_tmp_jail} >${_consolelog}
|
||||
else
|
||||
echo " cannot start jail \"${_jail}\": "
|
||||
tail +2 ${_tmp_jail}
|
||||
fi
|
||||
rm -f ${_tmp_jail}
|
||||
done
|
||||
echo "."
|
||||
}
|
||||
|
||||
jail_stop()
|
||||
{
|
||||
echo -n 'Stopping jails:'
|
||||
for _jail in ${jail_list}
|
||||
do
|
||||
init_name $_jail
|
||||
_jail_id=$(jls -j ${_name} jid 2>/dev/null)
|
||||
if [ -n "${_jail_id}" ]; then
|
||||
init_variables $_jail
|
||||
|
||||
if ! `pgrep -j ${_jail_id} >/dev/null 2>&1`; then
|
||||
echo -n " [${_jail} has no running processes (JID: ${_jail_id})]"
|
||||
continue
|
||||
fi
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval out=\"\${_exec_prestop${i}:-''}\"
|
||||
[ -z "$out" ] && break
|
||||
${out}
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
if [ -n "${_exec_stop}" ]; then
|
||||
eval env -i /usr/sbin/jexec ${_jail_id} ${_exec_stop} \
|
||||
>> ${_consolelog} 2>&1
|
||||
fi
|
||||
|
||||
jail -m jid=${_jail_id} persist=1
|
||||
killall -j ${_jail_id} -TERM > /dev/null 2>&1
|
||||
sleep 1
|
||||
killall -j ${_jail_id} -KILL > /dev/null 2>&1
|
||||
|
||||
if ! checkyesno _persist; then
|
||||
jail_destroy $_jail
|
||||
fi
|
||||
echo -n " $_jail"
|
||||
|
||||
i=0
|
||||
while : ; do
|
||||
eval out=\"\${_exec_poststop${i}:-''}\"
|
||||
[ -z "$out" ] && break
|
||||
${out}
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
fi
|
||||
jail_ips "del"
|
||||
done
|
||||
echo '.'
|
||||
}
|
||||
|
||||
jail_status()
|
||||
{
|
||||
for _jail in ${jail_list}
|
||||
do
|
||||
init_name $_jail
|
||||
_jail_id="$(jls -j ${_name} jid 2>/dev/null)"
|
||||
if [ -n "${_jail_id}" ]; then
|
||||
_procs=`pgrep -j ${_jail_id} | grep -c .`
|
||||
if [ "${_procs}" -gt 0 ]; then
|
||||
_procs=$((${_procs} - 1))
|
||||
fi
|
||||
echo "${_jail} online (JID: ${_jail_id}, processes: ${_procs})"
|
||||
else
|
||||
echo "${_jail} offline"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
load_rc_config $name
|
||||
: ${jailrc_enable="NO"}
|
||||
cmd="$1"
|
||||
if [ $# -gt 0 ]; then
|
||||
shift
|
||||
fi
|
||||
if [ -n "$*" ]; then
|
||||
jail_list="$*"
|
||||
fi
|
||||
|
||||
run_rc_command "${cmd}"
|
12
sysutils/jailrc/pkg-descr
Normal file
12
sysutils/jailrc/pkg-descr
Normal file
@ -0,0 +1,12 @@
|
||||
Jailrc is an improved startup/shutdown script for FreeBSD jails.
|
||||
|
||||
It contains the following changes to the original /etc/rc.d/jail script:
|
||||
|
||||
- parameters support: you can specify any parameters supported by jail(8)
|
||||
- ZFS support: you can deletate ZFS datasets to jails
|
||||
- jails are not identified by a file in /var/spool/jail anymore
|
||||
- two new commands "create" and "remove" to manage persistent jails
|
||||
|
||||
Please refer to the README file for more information.
|
||||
|
||||
Martin Matuska <mm_at_FreeBSD_dot_org>
|
Loading…
x
Reference in New Issue
Block a user