bge: Remove unused structs and macros
[dragonfly.git] / etc / rc.d / jail
1 #!/bin/sh
2 #
3 # $FreeBSD: src/etc/rc.d/jail,v 1.23.2.9 2007/01/11 18:16:58 simon Exp $
4 # $DragonFly: src/etc/rc.d/jail,v 1.5 2007/08/10 21:01:05 swildner Exp $
5 #
6
7 # PROVIDE: jail
8 # REQUIRE: LOGIN
9 # BEFORE: securelevel
10
11 . /etc/rc.subr
12
13 name="jail"
14 rcvar=`set_rcvar`
15 start_cmd="jail_start"
16 stop_cmd="jail_stop"
17
18 # init_variables _j
19 #       Initialize the various jail variables for jail _j.
20 #
21 init_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 _rootdir=\"\$jail_${_j}_rootdir\"
31         _devdir="${_rootdir}/dev"
32         _fdescdir="${_rootdir}/dev/fd"
33         _procdir="${_rootdir}/proc"
34         eval _hostname=\"\$jail_${_j}_hostname\"
35         eval _ip=\"\$jail_${_j}_ip\"
36         eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
37         eval _exec=\"\$jail_${_j}_exec\"
38         eval _exec_start=\"\${jail_${_j}_exec_start:-${jail_exec_start}}\"
39         eval _exec_stop=\"\${jail_${_j}_exec_stop:-${jail_exec_stop}}\"
40         if [ -n "${_exec}" ]; then
41                 #   simple/backward-compatible execution
42                 _exec_start="${_exec}"
43                 _exec_stop=""
44         else
45                 #   flexible execution
46                 if [ -z "${_exec_start}" ]; then
47                         _exec_start="/bin/sh /etc/rc"
48                         if [ -z "${_exec_stop}" ]; then
49                                 _exec_stop="/bin/sh /etc/rc.shutdown"
50                         fi
51                 fi
52         fi
53
54         eval _devfs=\"\${jail_${_j}_devfs_enable:-${jail_devfs_enable}}\"
55         [ -z "${_devfs}" ] && _devfs="NO"
56         eval _fdesc=\"\${jail_${_j}_fdesc_enable:-${jail_fdesc_enable}}\"
57         [ -z "${_fdesc}" ] && _fdesc="NO"
58         eval _procfs=\"\${jail_${_j}_procfs_enable:-${jail_procfs_enable}}\"
59         [ -z "${_procfs}" ] && _procfs="NO"
60
61         eval _mount=\"\${jail_${_j}_mount_enable:-${jail_mount_enable}}\"
62         [ -z "${_mount}" ] && _mount="NO"
63         # "/etc/fstab.${_j}" will be used for {,u}mount(8) if none is specified.
64         eval _fstab=\"\${jail_${_j}_fstab:-${jail_fstab}}\"
65         [ -z "${_fstab}" ] && _fstab="/etc/fstab.${_j}"
66         eval _flags=\"\${jail_${_j}_flags:-${jail_flags}}\"
67         [ -z "${_flags}" ] && _flags="-l -U root"
68         eval _consolelog=\"\${jail_${_j}_consolelog:-${jail_consolelog}}\"
69         [ -z "${_consolelog}" ] && _consolelog="/var/log/jail_${_j}_console.log"
70
71         # Debugging aid
72         #
73         debug "$_j devfs enable: $_devfs"
74         debug "$_j fdesc enable: $_fdesc"
75         debug "$_j procfs enable: $_procfs"
76         debug "$_j mount enable: $_mount"
77         debug "$_j hostname: $_hostname"
78         debug "$_j ip: $_ip"
79         debug "$_j interface: $_interface"
80         debug "$_j root: $_rootdir"
81         debug "$_j devdir: $_devdir"
82         debug "$_j fdescdir: $_fdescdir"
83         debug "$_j procdir: $_procdir"
84         debug "$_j fstab: $_fstab"
85         debug "$_j exec start: $_exec_start"
86         debug "$_j exec stop: $_exec_stop"
87         debug "$_j flags: $_flags"
88         debug "$_j consolelog: $_consolelog"
89
90         if [ -z "${_hostname}" ]; then
91                 err 3 "$name: No hostname has been defined for ${_j}"
92         fi
93         if [ -z "${_rootdir}" ]; then
94                 err 3 "$name: No root directory has been defined for ${_j}"
95         fi
96         if [ -z "${_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 #
109 set_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 # is_current_mountpoint()
130 #       Is the directory mount point for a currently mounted file
131 #       system?
132 #
133 is_current_mountpoint()
134 {
135         local _dir _dir2
136
137         _dir=$1
138
139         _dir=`echo $_dir | sed -Ee 's#//+#/#g' -e 's#/$##'`
140         [ ! -d "${_dir}" ] && return 1
141         _dir2=`df ${_dir} | tail +2 | awk '{ print $6 }'`
142         [ "${_dir}" = "${_dir2}" ]
143         return $?
144 }
145
146 # is_symlinked_mountpoint()
147 #       Is a mount point, or any of its parent directories, a symlink?
148 #
149 is_symlinked_mountpoint()
150 {
151         local _dir
152
153         _dir=$1
154
155         [ -L "$_dir" ] && return 0
156         [ "$_dir" = "/" ] && return 1
157         is_symlinked_mountpoint `dirname $_dir`
158         return $?
159 }
160
161 # secure_umount
162 #       Try to unmount a mount point without being vulnerable to
163 #       symlink attacks.
164 #
165 secure_umount()
166 {
167         local _dir
168
169         _dir=$1
170
171         if is_current_mountpoint ${_dir}; then
172                 umount -f ${_dir} >/dev/null 2>&1
173         else
174                 debug "Nothing mounted on ${_dir} - not unmounting"
175         fi
176 }
177
178
179 # jail_umount_fs
180 #       This function unmounts certain special filesystems in the
181 #       currently selected jail. The caller must call the init_variables()
182 #       routine before calling this one.
183 #
184 jail_umount_fs()
185 {
186         local _device _mountpt _rest
187
188         if checkyesno _fdesc; then
189                 if [ -d "${_fdescdir}" ] ; then
190                         secure_umount ${_fdescdir}
191                 fi
192         fi
193         if checkyesno _devfs; then
194             if [ -d "${_devdir}" ] ; then
195                 secure_umount ${_devdir}
196             fi
197         fi
198         if checkyesno _procfs; then
199                 if [ -d "${_procdir}" ] ; then
200                         secure_umount ${_procdir}
201                 fi
202         fi
203         if checkyesno _mount; then
204                 [ -f "${_fstab}" ] || warn "${_fstab} does not exist"
205                 tail -r ${_fstab} | while read _device _mountpt _rest; do
206                         case ":${_device}" in
207                         :#* | :)
208                                 continue
209                                 ;;
210                         esac
211                         secure_umount ${_mountpt}
212                 done
213         fi
214 }
215
216 # jail_mount_fstab()
217 #       Mount file systems from a per jail fstab while trying to
218 #       secure against symlink attacks at the mount points.
219 #
220 #       If we are certain we cannot secure against symlink attacks we
221 #       do not mount all of the file systems (since we cannot just not
222 #       mount the file system with the problematic mount point).
223 #
224 #       The caller must call the init_variables() routine before
225 #       calling this one.
226 #
227 jail_mount_fstab()
228 {
229         local _device _mountpt _rest
230
231         while read _device _mountpt _rest; do
232                 case ":${_device}" in
233                 :#* | :)
234                         continue
235                         ;;
236                 esac
237                 if is_symlinked_mountpoint ${_mountpt}; then
238                         warn "${_mountpt} has symlink as parent - not mounting from ${_fstab}"
239                         return
240                 fi
241         done <${_fstab}
242         mount -a -F "${_fstab}"
243 }
244
245 jail_start()
246 {
247         echo -n 'Configuring jails:'
248         set_sysctl jail_set_hostname_allow jail.set_hostname_allowed \
249             set_hostname_allow
250         set_sysctl jail_socket_unixiproute_only \
251             jail.socket_unixiproute_only unixiproute_only
252         set_sysctl jail_sysvipc_allow jail.sysvipc_allowed \
253             sysvipc_allow
254         echo '.'
255
256         echo -n 'Starting jails:'
257         _tmp_dir=`mktemp -d /tmp/jail.XXXXXXXX` || \
258             err 3 "$name: Can't create temp dir, exiting..."
259         for _jail in ${jail_list}
260         do
261                 init_variables $_jail
262                 if [ -f /var/run/jail_${_jail}.id ]; then
263                         echo -n " [${_hostname} already running (/var/run/jail_${_jail}.id exists)]"
264                         continue;
265                 fi
266                 if [ -n "${_interface}" ]; then
267                         ifconfig ${_interface} alias ${_ip} netmask 255.255.255.255
268                 fi
269                 if checkyesno _mount; then
270                         info "Mounting fstab for jail ${_jail} (${_fstab})"
271                         if [ ! -f "${_fstab}" ]; then
272                                 err 3 "$name: ${_fstab} does not exist"
273                         fi
274                         jail_mount_fstab
275                 fi
276                 if checkyesno _devfs; then
277                         # If devfs is already mounted here, skip it.
278                         df -t devfs "${_devdir}" >/dev/null
279                         if [ $? -ne 0 ]; then
280                                 if is_symlinked_mountpoint ${_devdir}; then
281                                         warn "${_devdir} has symlink as parent" \
282                                         "- not starting jail ${_jail}"
283                                         continue
284                                 fi
285                                 info "Mounting devfs on ${_devdir}"
286                                 devfs_mount_jail "${_devdir}"
287                         fi
288                 fi
289                 if checkyesno _fdesc; then
290                         if is_symlinked_mountpoint ${_fdescdir}; then
291                                 warn "${_fdescdir} has symlink as parent, not mounting"
292                         else
293                                 info "Mounting fdesc on ${_fdescdir}"
294                                 mount -t fdesc fdesc "${_fdescdir}"
295                         fi
296                 fi
297                 if checkyesno _procfs; then
298                         if is_symlinked_mountpoint ${_procdir}; then
299                                 warn "${_procdir} has symlink as parent, not mounting"
300                         else
301                                 info "Mounting procfs onto ${_procdir}"
302                                 if [ -d "${_procdir}" ] ; then
303                                         mount -t procfs proc "${_procdir}"
304                                 fi
305                         fi
306                 fi
307                 _tmp_jail=${_tmp_dir}/jail.$$
308                 eval jail ${_flags} -i ${_rootdir} ${_hostname} \
309                         ${_ip} ${_exec_start} > ${_tmp_jail} 2>&1
310                         if [ "$?" -eq 0 ] ; then
311                                 echo -n " $_hostname"
312                                 _jail_id=$(head -1 ${_tmp_jail})
313                                 tail +2 ${_tmp_jail} >${_consolelog}
314                                 echo ${_jail_id} > /var/run/jail_${_jail}.id
315                         else
316                                 jail_umount_fs
317                                 if [ -n "${_interface}" ]; then
318                                         ifconfig ${_interface} -alias ${_ip}
319                                 fi
320                                 echo " cannot start jail \"${_jail}\": "
321                                 tail +2 ${_tmp_jail}
322                         fi
323                 rm -f ${_tmp_jail}
324         done
325         rmdir ${_tmp_dir}
326         echo '.'
327 }
328
329 jail_stop()
330 {
331         echo -n 'Stopping jails:'
332         for _jail in ${jail_list}
333         do
334                 if [ -f "/var/run/jail_${_jail}.id" ]; then
335                         _jail_id=$(cat /var/run/jail_${_jail}.id)
336                         if [ ! -z "${_jail_id}" ]; then
337                                 init_variables $_jail
338                                 if [ -n "${_exec_stop}" ]; then
339                                         eval env -i /usr/sbin/jexec ${_jail_id} ${_exec_stop} \
340                                                 >> ${_consolelog} 2>&1
341                                 fi
342                                 killall -j ${_jail_id} -TERM > /dev/null 2>&1
343                                 sleep 1
344                                 killall -j ${_jail_id} -KILL > /dev/null 2>&1
345                                 jail_umount_fs
346                                 echo -n " $_hostname"
347                         fi
348                         if [ -n "${_interface}" ]; then
349                                 ifconfig ${_interface} -alias ${_ip}
350                         fi
351                         rm /var/run/jail_${_jail}.id
352                 else
353                         echo " cannot stop jail ${_jail}. No jail id in /var/run"
354                 fi
355         done
356         echo '.'
357 }
358
359 load_rc_config $name
360 cmd="$1"
361 if [ $# -gt 0 ]; then
362         shift
363 fi
364 if [ -n "$*" ]; then
365         jail_list="$*"
366 fi
367 run_rc_command "${cmd}"