jail revision 158363
1#!/bin/sh
2#
3# $FreeBSD: head/etc/rc.d/jail 158363 2006-05-08 17:32:45Z flz $
4#
5
6# PROVIDE: jail
7# REQUIRE: LOGIN cleanvar
8# BEFORE: securelevel
9# KEYWORD: nojail shutdown
10
11. /etc/rc.subr
12
13name="jail"
14rcvar=`set_rcvar`
15start_cmd="jail_start"
16stop_cmd="jail_stop"
17
18# init_variables _j
19#	Initialize the various jail variables for jail _j.
20#
21init_variables()
22{
23	_j="$1"
24
25	if [ -z "$_j" ]; then
26		warn "init_variables: you must specify a jail"
27		return
28	fi
29
30	eval jail_rootdir=\"\$jail_${_j}_rootdir\"
31	jail_devdir="${jail_rootdir}/dev"
32	jail_fdescdir="${jail_devdir}/fd"
33	jail_procdir="${jail_rootdir}/proc"
34	eval jail_hostname=\"\$jail_${_j}_hostname\"
35	eval jail_ip=\"\$jail_${_j}_ip\"
36	eval jail_interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
37	eval jail_exec=\"\$jail_${_j}_exec\"
38	eval jail_exec_start=\"\${jail_${_j}_exec_start:-${jail_exec_start}}\"
39	eval jail_exec_stop=\"\${jail_${_j}_exec_stop:-${jail_exec_stop}}\"
40	if [ -n "${jail_exec}" ]; then
41		#   simple/backward-compatible execution
42		jail_exec_start="${jail_exec}"
43		jail_exec_stop=""
44	else
45		#   flexible execution
46		if [ -z "${jail_exec_start}" ]; then
47			jail_exec_start="/bin/sh /etc/rc"
48			if [ -z "${jail_exec_stop}" ]; then
49				jail_exec_stop="/bin/sh /etc/rc.shutdown"
50			fi
51		fi
52	fi
53
54	# The default jail ruleset will be used by rc.subr if none is specified.
55	eval jail_ruleset=\"\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}\"
56	eval jail_devfs=\"\${jail_${_j}_devfs_enable:-${jail_devfs_enable}}\"
57	[ -z "${jail_devfs}" ] && jail_devfs="NO"
58	eval jail_fdescfs=\"\${jail_${_j}_fdescfs_enable:-${jail_fdescfs_enable}}\"
59	[ -z "${jail_fdescfs}" ] && jail_fdescfs="NO"
60	eval jail_procfs=\"\${jail_${_j}_procfs_enable:-${jail_procfs_enable}}\"
61	[ -z "${jail_procfs}" ] && jail_procfs="NO"
62
63	eval jail_mount=\"\${jail_${_j}_mount_enable:-${jail_mount_enable}}\"
64	[ -z "${jail_mount}" ] && jail_mount="NO"
65	# "/etc/fstab.${_j}" will be used for {,u}mount(8) if none is specified.
66	eval jail_fstab=\"\${jail_${_j}_fstab:-${jail_fstab}}\"
67	[ -z "${jail_fstab}" ] && jail_fstab="/etc/fstab.${_j}"
68	eval jail_flags=\"\${jail_${_j}_flags:-${jail_flags}}\"
69	[ -z "${jail_flags}" ] && jail_flags="-l -U root"
70
71	# Debugging aid
72	#
73	debug "$_j devfs enable: $jail_devfs"
74	debug "$_j fdescfs enable: $jail_fdescfs"
75	debug "$_j procfs enable: $jail_procfs"
76	debug "$_j mount enable: $jail_mount"
77	debug "$_j hostname: $jail_hostname"
78	debug "$_j ip: $jail_ip"
79	debug "$_j interface: $jail_interface"
80	debug "$_j root: $jail_rootdir"
81	debug "$_j devdir: $jail_devdir"
82	debug "$_j fdescdir: $jail_fdescdir"
83	debug "$_j procdir: $jail_procdir"
84	debug "$_j ruleset: $jail_ruleset"
85	debug "$_j fstab: $jail_fstab"
86	debug "$_j exec start: $jail_exec_start"
87	debug "$_j exec stop: $jail_exec_stop"
88	debug "$_j flags: $jail_flags"
89
90	if [ -z "${jail_hostname}" ]; then
91		err 3 "$name: No hostname has been defined for ${_j}"
92	fi
93	if [ -z "${jail_rootdir}" ]; then
94		err 3 "$name: No root directory has been defined for ${_j}"
95	fi
96	if [ -z "${jail_ip}" ]; then
97		err 3 "$name: No IP address has been defined for ${_j}"
98	fi
99
100}
101
102# set_sysctl rc_knob mib msg
103#	If the mib sysctl is set according to what rc_knob
104#	specifies, this function does nothing. However if
105#	rc_knob is set differently than mib, then the mib
106#	is set accordingly and msg is displayed followed by
107#	an '=" sign and the word 'YES' or 'NO'.
108#
109set_sysctl()
110{
111	_knob="$1"
112	_mib="$2"
113	_msg="$3"
114
115	_current=`${SYSCTL} -n $_mib 2>/dev/null`
116	if checkyesno $_knob ; then
117		if [ "$_current" -ne 1 ]; then
118			echo -n " ${_msg}=YES"
119			${SYSCTL_W} 1>/dev/null ${_mib}=1
120		fi
121	else
122		if [ "$_current" -ne 0 ]; then
123			echo -n " ${_msg}=NO"
124			${SYSCTL_W} 1>/dev/null ${_mib}=0
125		fi
126	fi
127}
128
129# jail_umount_fs
130#	This function unmounts certain special filesystems in the
131#	currently selected jail. The caller must call the init_variables()
132#	routine before calling this one.
133#
134jail_umount_fs()
135{
136	if checkyesno jail_fdescfs; then
137		if [ -d "${jail_fdescdir}" ] ; then
138			umount -f ${jail_fdescdir} >/dev/null 2>&1
139		fi
140	fi
141	if checkyesno jail_devfs; then
142		if [ -d "${jail_devdir}" ] ; then
143			umount -f ${jail_devdir} >/dev/null 2>&1
144		fi
145	fi
146	if checkyesno jail_procfs; then
147		if [ -d "${jail_procdir}" ] ; then
148			umount -f ${jail_procdir} >/dev/null 2>&1
149		fi
150	fi
151	if checkyesno jail_mount; then
152		[ -f "${jail_fstab}" ] || warn "${jail_fstab} does not exist"
153		umount -a -F "${jail_fstab}" >/dev/null 2>&1
154	fi
155}
156
157jail_start()
158{
159	echo -n 'Configuring jails:'
160	set_sysctl jail_set_hostname_allow security.jail.set_hostname_allowed \
161	    set_hostname_allow
162	set_sysctl jail_socket_unixiproute_only \
163	    security.jail.socket_unixiproute_only unixiproute_only
164	set_sysctl jail_sysvipc_allow security.jail.sysvipc_allowed \
165	    sysvipc_allow
166	echo '.'
167
168	echo -n 'Starting jails:'
169	_tmp_dir=`mktemp -d /tmp/jail.XXXXXXXX` || \
170	    err 3 "$name: Can't create temp dir, exiting..."
171	for _jail in ${jail_list}
172	do
173		init_variables $_jail
174		if [ -f /var/run/jail_${_jail}.id ]; then
175			echo -n " [${jail_hostname} already running (/var/run/jail_${_jail}.id exists)]"
176			continue;
177		fi
178		if [ -n "${jail_interface}" ]; then
179			ifconfig ${jail_interface} alias ${jail_ip} netmask 255.255.255.255
180		fi
181		if checkyesno jail_mount; then
182			info "Mounting fstab for jail ${_jail} (${jail_fstab})"
183			if [ ! -f "${jail_fstab}" ]; then
184				err 3 "$name: ${jail_fstab} does not exist"
185			fi
186			mount -a -F "${jail_fstab}"
187		fi
188		if checkyesno jail_devfs; then
189			# If devfs is already mounted here, skip it.
190			df -t devfs "${jail_devdir}" >/dev/null
191			if [ $? -ne 0 ]; then
192				info "Mounting devfs on ${jail_devdir}"
193				devfs_mount_jail "${jail_devdir}" ${jail_ruleset}
194				# Transitional symlink for old binaries
195				if [ ! -L "${jail_devdir}/log" ]; then
196					__pwd="`pwd`"
197					cd "${jail_devdir}"
198					ln -sf ../var/run/log log
199					cd "$__pwd"
200				fi
201			fi
202
203			# XXX - It seems symlinks don't work when there
204			#	is a devfs(5) device of the same name.
205			# Jail console output
206			#	__pwd="`pwd`"
207			#	cd "${jail_devdir}"
208			#	ln -sf ../var/log/console console
209			#	cd "$__pwd"
210		fi
211		if checkyesno jail_fdescfs; then
212			info "Mounting fdescfs on ${jail_fdescdir}"
213			mount -t fdescfs fdesc "${jail_fdescdir}"
214		fi
215		if checkyesno jail_procfs; then
216			info "Mounting procfs onto ${jail_procdir}"
217			if [ -d "${jail_procdir}" ] ; then
218				mount -t procfs proc "${jail_procdir}"
219			fi
220		fi
221		_tmp_jail=${_tmp_dir}/jail.$$
222		eval jail ${jail_flags} -i ${jail_rootdir} ${jail_hostname} \
223			${jail_ip} ${jail_exec_start} > ${_tmp_jail} 2>&1
224		[ "$?" -eq 0 ] && echo -n " $jail_hostname"
225		_jail_id=$(head -1 ${_tmp_jail})
226		tail +2 ${_tmp_jail} >${jail_rootdir}/var/log/console.log
227		rm -f ${_tmp_jail}
228		echo ${_jail_id} > /var/run/jail_${_jail}.id
229	done
230	rmdir ${_tmp_dir}
231	echo '.'
232}
233
234jail_stop()
235{
236	echo -n 'Stopping jails:'
237	for _jail in ${jail_list}
238	do
239		if [ -f "/var/run/jail_${_jail}.id" ]; then
240			_jail_id=$(cat /var/run/jail_${_jail}.id)
241			if [ ! -z "${_jail_id}" ]; then
242				init_variables $_jail
243				if [ -n "${jail_exec_stop}" ]; then
244					eval env -i /usr/sbin/jexec ${_jail_id} ${jail_exec_stop} \
245						>> ${jail_rootdir}/var/log/console.log 2>&1
246				fi
247				killall -j ${_jail_id} -TERM > /dev/null 2>&1
248				sleep 1
249				killall -j ${_jail_id} -KILL > /dev/null 2>&1
250				jail_umount_fs
251				echo -n " $jail_hostname"
252			fi
253			if [ -n "${jail_interface}" ]; then
254				ifconfig ${jail_interface} -alias ${jail_ip}
255			fi
256			rm /var/run/jail_${_jail}.id
257		else
258			echo "cannot stop jail ${_jail}. No jail id in /var/run"
259		fi
260	done
261	echo '.'
262}
263
264load_rc_config $name
265cmd="$1"
266if [ $# -gt 0 ]; then
267	shift
268fi
269if [ -n "$*" ]; then
270	jail_list="$*"
271fi
272run_rc_command "${cmd}"
273