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