1#!/bin/sh 2#
| 1#!/bin/sh 2#
|
3# $FreeBSD: head/etc/rc.d/jail 187708 2009-01-26 12:59:11Z bz $
| 3# $FreeBSD: head/etc/rc.d/jail 191620 2009-04-28 09:45:32Z ru $
|
4# 5 6# PROVIDE: jail 7# REQUIRE: LOGIN cleanvar 8# BEFORE: securelevel 9# KEYWORD: nojail shutdown 10 11# WARNING: This script deals with untrusted data (the data and 12# processes inside the jails) and care must be taken when changing the 13# code related to this! If you have any doubt whether a change is 14# correct and have security impact, please get the patch reviewed by 15# the FreeBSD Security Team prior to commit. 16 17. /etc/rc.subr 18 19name="jail" 20rcvar=`set_rcvar` 21start_cmd="jail_start" 22stop_cmd="jail_stop" 23 24# init_variables _j 25# Initialize the various jail variables for jail _j. 26# 27init_variables() 28{ 29 _j="$1" 30 31 if [ -z "$_j" ]; then 32 warn "init_variables: you must specify a jail" 33 return 34 fi 35 36 eval _rootdir=\"\$jail_${_j}_rootdir\" 37 _devdir="${_rootdir}/dev" 38 _fdescdir="${_devdir}/fd" 39 _procdir="${_rootdir}/proc" 40 eval _hostname=\"\$jail_${_j}_hostname\" 41 eval _ip=\"\$jail_${_j}_ip\" 42 eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\" 43 eval _exec=\"\$jail_${_j}_exec\"
| 4# 5 6# PROVIDE: jail 7# REQUIRE: LOGIN cleanvar 8# BEFORE: securelevel 9# KEYWORD: nojail shutdown 10 11# WARNING: This script deals with untrusted data (the data and 12# processes inside the jails) and care must be taken when changing the 13# code related to this! If you have any doubt whether a change is 14# correct and have security impact, please get the patch reviewed by 15# the FreeBSD Security Team prior to commit. 16 17. /etc/rc.subr 18 19name="jail" 20rcvar=`set_rcvar` 21start_cmd="jail_start" 22stop_cmd="jail_stop" 23 24# init_variables _j 25# Initialize the various jail variables for jail _j. 26# 27init_variables() 28{ 29 _j="$1" 30 31 if [ -z "$_j" ]; then 32 warn "init_variables: you must specify a jail" 33 return 34 fi 35 36 eval _rootdir=\"\$jail_${_j}_rootdir\" 37 _devdir="${_rootdir}/dev" 38 _fdescdir="${_devdir}/fd" 39 _procdir="${_rootdir}/proc" 40 eval _hostname=\"\$jail_${_j}_hostname\" 41 eval _ip=\"\$jail_${_j}_ip\" 42 eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\" 43 eval _exec=\"\$jail_${_j}_exec\"
|
| 44 45 i=0 46 while : ; do 47 eval _exec_prestart${i}=\"\${jail_${_j}_exec_prestart${i}:-\${jail_exec_prestart${i}}}\" 48 [ -z "$(eval echo \"\$_exec_prestart${i}\")" ] && break 49 i=$((i + 1)) 50 done 51
|
44 eval _exec_start=\"\${jail_${_j}_exec_start:-${jail_exec_start}}\" 45 46 i=1 47 while [ true ]; do 48 eval _exec_afterstart${i}=\"\${jail_${_j}_exec_afterstart${i}:-\${jail_exec_afterstart${i}}}\" 49 [ -z "$(eval echo \"\$_exec_afterstart${i}\")" ] && break 50 i=$((i + 1)) 51 done
| 52 eval _exec_start=\"\${jail_${_j}_exec_start:-${jail_exec_start}}\" 53 54 i=1 55 while [ true ]; do 56 eval _exec_afterstart${i}=\"\${jail_${_j}_exec_afterstart${i}:-\${jail_exec_afterstart${i}}}\" 57 [ -z "$(eval echo \"\$_exec_afterstart${i}\")" ] && break 58 i=$((i + 1)) 59 done
|
52
| 60 61 i=0 62 while : ; do 63 eval _exec_poststart${i}=\"\${jail_${_j}_exec_poststart${i}:-\${jail_exec_poststart${i}}}\" 64 [ -z "$(eval echo \"\$_exec_poststart${i}\")" ] && break 65 i=$((i + 1)) 66 done 67 68 i=0 69 while : ; do 70 eval _exec_prestop${i}=\"\${jail_${_j}_exec_prestop${i}:-\${jail_exec_prestop${i}}}\" 71 [ -z "$(eval echo \"\$_exec_prestop${i}\")" ] && break 72 i=$((i + 1)) 73 done 74
|
53 eval _exec_stop=\"\${jail_${_j}_exec_stop:-${jail_exec_stop}}\"
| 75 eval _exec_stop=\"\${jail_${_j}_exec_stop:-${jail_exec_stop}}\"
|
| 76 77 i=0 78 while : ; do 79 eval _exec_poststop${i}=\"\${jail_${_j}_exec_poststop${i}:-\${jail_exec_poststop${i}}}\" 80 [ -z "$(eval echo \"\$_exec_poststop${i}\")" ] && break 81 i=$((i + 1)) 82 done 83
|
54 if [ -n "${_exec}" ]; then 55 # simple/backward-compatible execution 56 _exec_start="${_exec}" 57 _exec_stop="" 58 else 59 # flexible execution 60 if [ -z "${_exec_start}" ]; then 61 _exec_start="/bin/sh /etc/rc" 62 if [ -z "${_exec_stop}" ]; then 63 _exec_stop="/bin/sh /etc/rc.shutdown" 64 fi 65 fi 66 fi 67 68 # The default jail ruleset will be used by rc.subr if none is specified. 69 eval _ruleset=\"\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}\" 70 eval _devfs=\"\${jail_${_j}_devfs_enable:-${jail_devfs_enable}}\" 71 [ -z "${_devfs}" ] && _devfs="NO" 72 eval _fdescfs=\"\${jail_${_j}_fdescfs_enable:-${jail_fdescfs_enable}}\" 73 [ -z "${_fdescfs}" ] && _fdescfs="NO" 74 eval _procfs=\"\${jail_${_j}_procfs_enable:-${jail_procfs_enable}}\" 75 [ -z "${_procfs}" ] && _procfs="NO" 76 77 eval _mount=\"\${jail_${_j}_mount_enable:-${jail_mount_enable}}\" 78 [ -z "${_mount}" ] && _mount="NO" 79 # "/etc/fstab.${_j}" will be used for {,u}mount(8) if none is specified. 80 eval _fstab=\"\${jail_${_j}_fstab:-${jail_fstab}}\" 81 [ -z "${_fstab}" ] && _fstab="/etc/fstab.${_j}" 82 eval _flags=\"\${jail_${_j}_flags:-${jail_flags}}\" 83 [ -z "${_flags}" ] && _flags="-l -U root" 84 eval _consolelog=\"\${jail_${_j}_consolelog:-${jail_consolelog}}\" 85 [ -z "${_consolelog}" ] && _consolelog="/var/log/jail_${_j}_console.log" 86 eval _fib=\"\${jail_${_j}_fib:-${jail_fib}}\" 87 88 # Debugging aid 89 # 90 debug "$_j devfs enable: $_devfs" 91 debug "$_j fdescfs enable: $_fdescfs" 92 debug "$_j procfs enable: $_procfs" 93 debug "$_j mount enable: $_mount" 94 debug "$_j hostname: $_hostname" 95 debug "$_j ip: $_ip" 96 jail_show_addresses ${_j} 97 debug "$_j interface: $_interface" 98 debug "$_j fib: $_fib" 99 debug "$_j root: $_rootdir" 100 debug "$_j devdir: $_devdir" 101 debug "$_j fdescdir: $_fdescdir" 102 debug "$_j procdir: $_procdir" 103 debug "$_j ruleset: $_ruleset" 104 debug "$_j fstab: $_fstab"
| 84 if [ -n "${_exec}" ]; then 85 # simple/backward-compatible execution 86 _exec_start="${_exec}" 87 _exec_stop="" 88 else 89 # flexible execution 90 if [ -z "${_exec_start}" ]; then 91 _exec_start="/bin/sh /etc/rc" 92 if [ -z "${_exec_stop}" ]; then 93 _exec_stop="/bin/sh /etc/rc.shutdown" 94 fi 95 fi 96 fi 97 98 # The default jail ruleset will be used by rc.subr if none is specified. 99 eval _ruleset=\"\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}\" 100 eval _devfs=\"\${jail_${_j}_devfs_enable:-${jail_devfs_enable}}\" 101 [ -z "${_devfs}" ] && _devfs="NO" 102 eval _fdescfs=\"\${jail_${_j}_fdescfs_enable:-${jail_fdescfs_enable}}\" 103 [ -z "${_fdescfs}" ] && _fdescfs="NO" 104 eval _procfs=\"\${jail_${_j}_procfs_enable:-${jail_procfs_enable}}\" 105 [ -z "${_procfs}" ] && _procfs="NO" 106 107 eval _mount=\"\${jail_${_j}_mount_enable:-${jail_mount_enable}}\" 108 [ -z "${_mount}" ] && _mount="NO" 109 # "/etc/fstab.${_j}" will be used for {,u}mount(8) if none is specified. 110 eval _fstab=\"\${jail_${_j}_fstab:-${jail_fstab}}\" 111 [ -z "${_fstab}" ] && _fstab="/etc/fstab.${_j}" 112 eval _flags=\"\${jail_${_j}_flags:-${jail_flags}}\" 113 [ -z "${_flags}" ] && _flags="-l -U root" 114 eval _consolelog=\"\${jail_${_j}_consolelog:-${jail_consolelog}}\" 115 [ -z "${_consolelog}" ] && _consolelog="/var/log/jail_${_j}_console.log" 116 eval _fib=\"\${jail_${_j}_fib:-${jail_fib}}\" 117 118 # Debugging aid 119 # 120 debug "$_j devfs enable: $_devfs" 121 debug "$_j fdescfs enable: $_fdescfs" 122 debug "$_j procfs enable: $_procfs" 123 debug "$_j mount enable: $_mount" 124 debug "$_j hostname: $_hostname" 125 debug "$_j ip: $_ip" 126 jail_show_addresses ${_j} 127 debug "$_j interface: $_interface" 128 debug "$_j fib: $_fib" 129 debug "$_j root: $_rootdir" 130 debug "$_j devdir: $_devdir" 131 debug "$_j fdescdir: $_fdescdir" 132 debug "$_j procdir: $_procdir" 133 debug "$_j ruleset: $_ruleset" 134 debug "$_j fstab: $_fstab"
|
105 debug "$_j exec start: $_exec_start"
| |
106 debug "$_j consolelog: $_consolelog" 107
| 135 debug "$_j consolelog: $_consolelog" 136
|
| 137 i=0 138 while : ; do 139 eval out=\"\${_exec_prestart${i}:-''}\" 140 if [ -z "$out" ]; then 141 break 142 fi 143 debug "$_j exec pre-start #${i}: ${out}" 144 i=$((i + 1)) 145 done 146 147 debug "$_j exec start: $_exec_start" 148
|
108 i=1 109 while [ true ]; do 110 eval out=\"\${_exec_afterstart${i}:-''}\" 111 112 if [ -z "$out" ]; then 113 break; 114 fi 115 116 debug "$_j exec after start #${i}: ${out}" 117 i=$((i + 1)) 118 done 119
| 149 i=1 150 while [ true ]; do 151 eval out=\"\${_exec_afterstart${i}:-''}\" 152 153 if [ -z "$out" ]; then 154 break; 155 fi 156 157 debug "$_j exec after start #${i}: ${out}" 158 i=$((i + 1)) 159 done 160
|
| 161 i=0 162 while : ; do 163 eval out=\"\${_exec_poststart${i}:-''}\" 164 if [ -z "$out" ]; then 165 break 166 fi 167 debug "$_j exec post-start #${i}: ${out}" 168 i=$((i + 1)) 169 done 170 171 i=0 172 while : ; do 173 eval out=\"\${_exec_prestop${i}:-''}\" 174 if [ -z "$out" ]; then 175 break 176 fi 177 debug "$_j exec pre-stop #${i}: ${out}" 178 i=$((i + 1)) 179 done 180
|
120 debug "$_j exec stop: $_exec_stop"
| 181 debug "$_j exec stop: $_exec_stop"
|
| 182 183 i=0 184 while : ; do 185 eval out=\"\${_exec_poststop${i}:-''}\" 186 if [ -z "$out" ]; then 187 break 188 fi 189 debug "$_j exec post-stop #${i}: ${out}" 190 i=$((i + 1)) 191 done 192
|
121 debug "$_j flags: $_flags" 122 debug "$_j consolelog: $_consolelog" 123 124 if [ -z "${_hostname}" ]; then 125 err 3 "$name: No hostname has been defined for ${_j}" 126 fi 127 if [ -z "${_rootdir}" ]; then 128 err 3 "$name: No root directory has been defined for ${_j}" 129 fi 130} 131 132# set_sysctl rc_knob mib msg 133# If the mib sysctl is set according to what rc_knob 134# specifies, this function does nothing. However if 135# rc_knob is set differently than mib, then the mib 136# is set accordingly and msg is displayed followed by 137# an '=" sign and the word 'YES' or 'NO'. 138# 139set_sysctl() 140{ 141 _knob="$1" 142 _mib="$2" 143 _msg="$3" 144 145 _current=`${SYSCTL} -n $_mib 2>/dev/null` 146 if checkyesno $_knob ; then 147 if [ "$_current" -ne 1 ]; then 148 echo -n " ${_msg}=YES" 149 ${SYSCTL_W} 1>/dev/null ${_mib}=1 150 fi 151 else 152 if [ "$_current" -ne 0 ]; then 153 echo -n " ${_msg}=NO" 154 ${SYSCTL_W} 1>/dev/null ${_mib}=0 155 fi 156 fi 157} 158 159# is_current_mountpoint() 160# Is the directory mount point for a currently mounted file 161# system? 162# 163is_current_mountpoint() 164{ 165 local _dir _dir2 166 167 _dir=$1 168 169 _dir=`echo $_dir | sed -Ee 's#//+#/#g' -e 's#/$##'` 170 [ ! -d "${_dir}" ] && return 1 171 _dir2=`df ${_dir} | tail +2 | awk '{ print $6 }'` 172 [ "${_dir}" = "${_dir2}" ] 173 return $? 174} 175 176# is_symlinked_mountpoint() 177# Is a mount point, or any of its parent directories, a symlink? 178# 179is_symlinked_mountpoint() 180{ 181 local _dir 182 183 _dir=$1 184 185 [ -L "$_dir" ] && return 0 186 [ "$_dir" = "/" ] && return 1 187 is_symlinked_mountpoint `dirname $_dir` 188 return $? 189} 190 191# secure_umount 192# Try to unmount a mount point without being vulnerable to 193# symlink attacks. 194# 195secure_umount() 196{ 197 local _dir 198 199 _dir=$1 200 201 if is_current_mountpoint ${_dir}; then 202 umount -f ${_dir} >/dev/null 2>&1 203 else 204 debug "Nothing mounted on ${_dir} - not unmounting" 205 fi 206} 207 208 209# jail_umount_fs 210# This function unmounts certain special filesystems in the 211# currently selected jail. The caller must call the init_variables() 212# routine before calling this one. 213# 214jail_umount_fs() 215{ 216 local _device _mountpt _rest 217 218 if checkyesno _fdescfs; then 219 if [ -d "${_fdescdir}" ] ; then 220 secure_umount ${_fdescdir} 221 fi 222 fi 223 if checkyesno _devfs; then 224 if [ -d "${_devdir}" ] ; then 225 secure_umount ${_devdir} 226 fi 227 fi 228 if checkyesno _procfs; then 229 if [ -d "${_procdir}" ] ; then 230 secure_umount ${_procdir} 231 fi 232 fi 233 if checkyesno _mount; then 234 [ -f "${_fstab}" ] || warn "${_fstab} does not exist" 235 tail -r ${_fstab} | while read _device _mountpt _rest; do 236 case ":${_device}" in 237 :#* | :) 238 continue 239 ;; 240 esac 241 secure_umount ${_mountpt} 242 done 243 fi 244} 245 246# jail_mount_fstab() 247# Mount file systems from a per jail fstab while trying to 248# secure against symlink attacks at the mount points. 249# 250# If we are certain we cannot secure against symlink attacks we 251# do not mount all of the file systems (since we cannot just not 252# mount the file system with the problematic mount point). 253# 254# The caller must call the init_variables() routine before 255# calling this one. 256# 257jail_mount_fstab() 258{ 259 local _device _mountpt _rest 260 261 while read _device _mountpt _rest; do 262 case ":${_device}" in 263 :#* | :) 264 continue 265 ;; 266 esac 267 if is_symlinked_mountpoint ${_mountpt}; then 268 warn "${_mountpt} has symlink as parent - not mounting from ${_fstab}" 269 return 270 fi 271 done <${_fstab} 272 mount -a -F "${_fstab}" 273} 274 275# jail_show_addresses jail 276# Debug print the input for the given _multi aliases 277# for a jail for init_variables(). 278# 279jail_show_addresses() 280{ 281 local _j _type alias 282 _j="$1" 283 alias=0 284 285 if [ -z "${_j}" ]; then 286 warn "jail_show_addresses: you must specify a jail" 287 return 288 fi 289 290 while : ; do 291 eval _addr=\"\$jail_${_j}_ip_multi${alias}\" 292 if [ -n "${_addr}" ]; then 293 debug "${_j} ip_multi${alias}: $_addr" 294 alias=$((${alias} + 1)) 295 else 296 break 297 fi 298 done 299} 300 301# jail_extract_address argument 302# The second argument is the string from one of the _ip 303# or the _multi variables. In case of a comma separated list 304# only one argument must be passed in at a time. 305# The function alters the _type, _iface, _addr and _mask variables. 306# 307jail_extract_address() 308{ 309 local _i 310 _i=$1 311 312 if [ -z "${_i}" ]; then 313 warn "jail_extract_address: called without input" 314 return 315 fi 316 317 # Check if we have an interface prefix given and split into 318 # iFace and rest. 319 case "${_i}" in 320 *\|*) # ifN|.. prefix there 321 _iface=${_i%%|*} 322 _r=${_i##*|} 323 ;; 324 *) _iface="" 325 _r=${_i} 326 ;; 327 esac 328 329 # In case the IP has no interface given, check if we have a global one. 330 _iface=${_iface:-${_interface}} 331 332 # Set address, cut off any prefix/netmask/prefixlen. 333 _addr=${_r} 334 _addr=${_addr%%[/ ]*} 335 336 # Theoretically we can return here if interface is not set, 337 # as we only care about the _mask if we call ifconfig. 338 # This is not done because we may want to santize IP addresses 339 # based on _type later, and optionally change the type as well. 340 341 # Extract the prefix/netmask/prefixlen part by cutting off the address. 342 _mask=${_r} 343 _mask=`expr "${_mask}" : "${_addr}\(.*\)"` 344 345 # Identify type {inet,inet6}. 346 case "${_addr}" in 347 *\.*\.*\.*) _type="inet" ;; 348 *:*) _type="inet6" ;; 349 *) warn "jail_extract_address: type not identified" 350 ;; 351 esac 352 353 # Handle the special /netmask instead of /prefix or 354 # "netmask xxx" case for legacy IP. 355 # We do NOT support shortend class-full netmasks. 356 if [ "${_type}" = "inet" ]; then 357 case "${_mask}" in 358 /*\.*\.*\.*) _mask=" netmask ${_mask#/}" ;; 359 *) ;; 360 esac 361 362 # In case _mask is still not set use /32. 363 _mask=${_mask:-/32} 364 365 elif [ "${_type}" = "inet6" ]; then 366 # In case _maske is not set for IPv6, use /128. 367 _mask=${_mask:-/128} 368 fi 369} 370 371# jail_handle_ips_option {add,del} input 372# Handle a single argument imput which can be a comma separated 373# list of addresses (theoretically with an option interface and 374# prefix/netmask/prefixlen). 375# 376jail_handle_ips_option() 377{ 378 local _x _action _type _i 379 _action=$1 380 _x=$2 381 382 if [ -z "${_x}" ]; then 383 # No IP given. This can happen for the primary address 384 # of each address family. 385 return 386 fi 387 388 # Loop, in case we find a comma separated list, we need to handle 389 # each argument on its own. 390 while [ ${#_x} -gt 0 ]; do 391 case "${_x}" in 392 *,*) # Extract the first argument and strip it off the list. 393 _i=`expr "${_x}" : '^\([^,]*\)'` 394 _x=`expr "${_x}" : "^[^,]*,\(.*\)"` 395 ;; 396 *) _i=${_x} 397 _x="" 398 ;; 399 esac 400 401 _type="" 402 _iface="" 403 _addr="" 404 _mask="" 405 jail_extract_address "${_i}" 406 407 # make sure we got an address. 408 case "${_addr}" in 409 "") continue ;; 410 *) ;; 411 esac 412 413 # Append address to list of addresses for the jail command. 414 case "${_addrl}" in 415 "") _addrl="${_addr}" ;; 416 *) _addrl="${_addrl},${_addr}" ;; 417 esac 418 419 # Configure interface alias if requested by a given interface 420 # and if we could correctly parse everything. 421 case "${_iface}" in 422 "") continue ;; 423 esac 424 case "${_type}" in 425 inet) ;; 426 inet6) ;; 427 *) warn "Could not determine address family. Not going" \ 428 "to ${_action} address '${_addr}' for ${_jail}." 429 continue 430 ;; 431 esac 432 case "${_action}" in 433 add) ifconfig ${_iface} ${_type} ${_addr}${_mask} alias 434 ;; 435 del) # When removing the IP, ignore the _mask. 436 ifconfig ${_iface} ${_type} ${_addr} -alias 437 ;; 438 esac 439 done 440} 441 442# jail_ips {add,del} 443# Extract the comma separated list of addresses and return them 444# for the jail command. 445# Handle more than one address via the _multi option as well. 446# If an interface is given also add/remove an alias for the 447# address with an optional netmask. 448# 449jail_ips() 450{ 451 local _action 452 _action=$1 453 454 case "${_action}" in 455 add) ;; 456 del) ;; 457 *) warn "jail_ips: invalid action '${_action}'" 458 return 459 ;; 460 esac 461 462 # Handle addresses. 463 jail_handle_ips_option ${_action} "${_ip}" 464 # Handle jail_xxx_ip_multi<N> 465 alias=0 466 while : ; do 467 eval _x=\"\$jail_${_jail}_ip_multi${alias}\" 468 case "${_x}" in 469 "") break ;; 470 *) jail_handle_ips_option ${_action} "${_x}" 471 alias=$((${alias} + 1)) 472 ;; 473 esac 474 done 475} 476 477jail_start() 478{ 479 echo -n 'Configuring jails:' 480 set_sysctl jail_set_hostname_allow security.jail.set_hostname_allowed \ 481 set_hostname_allow 482 set_sysctl jail_socket_unixiproute_only \ 483 security.jail.socket_unixiproute_only unixiproute_only 484 set_sysctl jail_sysvipc_allow security.jail.sysvipc_allowed \ 485 sysvipc_allow 486 echo '.' 487 488 echo -n 'Starting jails:' 489 _tmp_dir=`mktemp -d /tmp/jail.XXXXXXXX` || \ 490 err 3 "$name: Can't create temp dir, exiting..." 491 for _jail in ${jail_list} 492 do 493 init_variables $_jail 494 if [ -f /var/run/jail_${_jail}.id ]; then 495 echo -n " [${_hostname} already running (/var/run/jail_${_jail}.id exists)]" 496 continue; 497 fi 498 _addrl="" 499 jail_ips "add" 500 if [ -n "${_fib}" ]; then 501 _setfib="setfib -F '${_fib}'" 502 else 503 _setfib="" 504 fi 505 if checkyesno _mount; then 506 info "Mounting fstab for jail ${_jail} (${_fstab})" 507 if [ ! -f "${_fstab}" ]; then 508 err 3 "$name: ${_fstab} does not exist" 509 fi 510 jail_mount_fstab 511 fi 512 if checkyesno _devfs; then 513 # If devfs is already mounted here, skip it. 514 df -t devfs "${_devdir}" >/dev/null 515 if [ $? -ne 0 ]; then 516 if is_symlinked_mountpoint ${_devdir}; then 517 warn "${_devdir} has symlink as parent - not starting jail ${_jail}" 518 continue 519 fi 520 info "Mounting devfs on ${_devdir}" 521 devfs_mount_jail "${_devdir}" ${_ruleset} 522 # Transitional symlink for old binaries 523 if [ ! -L "${_devdir}/log" ]; then 524 __pwd="`pwd`" 525 cd "${_devdir}" 526 ln -sf ../var/run/log log 527 cd "$__pwd" 528 fi 529 fi 530 531 # XXX - It seems symlinks don't work when there 532 # is a devfs(5) device of the same name. 533 # Jail console output 534 # __pwd="`pwd`" 535 # cd "${_devdir}" 536 # ln -sf ../var/log/console console 537 # cd "$__pwd" 538 fi 539 if checkyesno _fdescfs; then 540 if is_symlinked_mountpoint ${_fdescdir}; then 541 warn "${_fdescdir} has symlink as parent, not mounting" 542 else 543 info "Mounting fdescfs on ${_fdescdir}" 544 mount -t fdescfs fdesc "${_fdescdir}" 545 fi 546 fi 547 if checkyesno _procfs; then 548 if is_symlinked_mountpoint ${_procdir}; then 549 warn "${_procdir} has symlink as parent, not mounting" 550 else 551 info "Mounting procfs onto ${_procdir}" 552 if [ -d "${_procdir}" ] ; then 553 mount -t procfs proc "${_procdir}" 554 fi 555 fi 556 fi 557 _tmp_jail=${_tmp_dir}/jail.$$
| 193 debug "$_j flags: $_flags" 194 debug "$_j consolelog: $_consolelog" 195 196 if [ -z "${_hostname}" ]; then 197 err 3 "$name: No hostname has been defined for ${_j}" 198 fi 199 if [ -z "${_rootdir}" ]; then 200 err 3 "$name: No root directory has been defined for ${_j}" 201 fi 202} 203 204# set_sysctl rc_knob mib msg 205# If the mib sysctl is set according to what rc_knob 206# specifies, this function does nothing. However if 207# rc_knob is set differently than mib, then the mib 208# is set accordingly and msg is displayed followed by 209# an '=" sign and the word 'YES' or 'NO'. 210# 211set_sysctl() 212{ 213 _knob="$1" 214 _mib="$2" 215 _msg="$3" 216 217 _current=`${SYSCTL} -n $_mib 2>/dev/null` 218 if checkyesno $_knob ; then 219 if [ "$_current" -ne 1 ]; then 220 echo -n " ${_msg}=YES" 221 ${SYSCTL_W} 1>/dev/null ${_mib}=1 222 fi 223 else 224 if [ "$_current" -ne 0 ]; then 225 echo -n " ${_msg}=NO" 226 ${SYSCTL_W} 1>/dev/null ${_mib}=0 227 fi 228 fi 229} 230 231# is_current_mountpoint() 232# Is the directory mount point for a currently mounted file 233# system? 234# 235is_current_mountpoint() 236{ 237 local _dir _dir2 238 239 _dir=$1 240 241 _dir=`echo $_dir | sed -Ee 's#//+#/#g' -e 's#/$##'` 242 [ ! -d "${_dir}" ] && return 1 243 _dir2=`df ${_dir} | tail +2 | awk '{ print $6 }'` 244 [ "${_dir}" = "${_dir2}" ] 245 return $? 246} 247 248# is_symlinked_mountpoint() 249# Is a mount point, or any of its parent directories, a symlink? 250# 251is_symlinked_mountpoint() 252{ 253 local _dir 254 255 _dir=$1 256 257 [ -L "$_dir" ] && return 0 258 [ "$_dir" = "/" ] && return 1 259 is_symlinked_mountpoint `dirname $_dir` 260 return $? 261} 262 263# secure_umount 264# Try to unmount a mount point without being vulnerable to 265# symlink attacks. 266# 267secure_umount() 268{ 269 local _dir 270 271 _dir=$1 272 273 if is_current_mountpoint ${_dir}; then 274 umount -f ${_dir} >/dev/null 2>&1 275 else 276 debug "Nothing mounted on ${_dir} - not unmounting" 277 fi 278} 279 280 281# jail_umount_fs 282# This function unmounts certain special filesystems in the 283# currently selected jail. The caller must call the init_variables() 284# routine before calling this one. 285# 286jail_umount_fs() 287{ 288 local _device _mountpt _rest 289 290 if checkyesno _fdescfs; then 291 if [ -d "${_fdescdir}" ] ; then 292 secure_umount ${_fdescdir} 293 fi 294 fi 295 if checkyesno _devfs; then 296 if [ -d "${_devdir}" ] ; then 297 secure_umount ${_devdir} 298 fi 299 fi 300 if checkyesno _procfs; then 301 if [ -d "${_procdir}" ] ; then 302 secure_umount ${_procdir} 303 fi 304 fi 305 if checkyesno _mount; then 306 [ -f "${_fstab}" ] || warn "${_fstab} does not exist" 307 tail -r ${_fstab} | while read _device _mountpt _rest; do 308 case ":${_device}" in 309 :#* | :) 310 continue 311 ;; 312 esac 313 secure_umount ${_mountpt} 314 done 315 fi 316} 317 318# jail_mount_fstab() 319# Mount file systems from a per jail fstab while trying to 320# secure against symlink attacks at the mount points. 321# 322# If we are certain we cannot secure against symlink attacks we 323# do not mount all of the file systems (since we cannot just not 324# mount the file system with the problematic mount point). 325# 326# The caller must call the init_variables() routine before 327# calling this one. 328# 329jail_mount_fstab() 330{ 331 local _device _mountpt _rest 332 333 while read _device _mountpt _rest; do 334 case ":${_device}" in 335 :#* | :) 336 continue 337 ;; 338 esac 339 if is_symlinked_mountpoint ${_mountpt}; then 340 warn "${_mountpt} has symlink as parent - not mounting from ${_fstab}" 341 return 342 fi 343 done <${_fstab} 344 mount -a -F "${_fstab}" 345} 346 347# jail_show_addresses jail 348# Debug print the input for the given _multi aliases 349# for a jail for init_variables(). 350# 351jail_show_addresses() 352{ 353 local _j _type alias 354 _j="$1" 355 alias=0 356 357 if [ -z "${_j}" ]; then 358 warn "jail_show_addresses: you must specify a jail" 359 return 360 fi 361 362 while : ; do 363 eval _addr=\"\$jail_${_j}_ip_multi${alias}\" 364 if [ -n "${_addr}" ]; then 365 debug "${_j} ip_multi${alias}: $_addr" 366 alias=$((${alias} + 1)) 367 else 368 break 369 fi 370 done 371} 372 373# jail_extract_address argument 374# The second argument is the string from one of the _ip 375# or the _multi variables. In case of a comma separated list 376# only one argument must be passed in at a time. 377# The function alters the _type, _iface, _addr and _mask variables. 378# 379jail_extract_address() 380{ 381 local _i 382 _i=$1 383 384 if [ -z "${_i}" ]; then 385 warn "jail_extract_address: called without input" 386 return 387 fi 388 389 # Check if we have an interface prefix given and split into 390 # iFace and rest. 391 case "${_i}" in 392 *\|*) # ifN|.. prefix there 393 _iface=${_i%%|*} 394 _r=${_i##*|} 395 ;; 396 *) _iface="" 397 _r=${_i} 398 ;; 399 esac 400 401 # In case the IP has no interface given, check if we have a global one. 402 _iface=${_iface:-${_interface}} 403 404 # Set address, cut off any prefix/netmask/prefixlen. 405 _addr=${_r} 406 _addr=${_addr%%[/ ]*} 407 408 # Theoretically we can return here if interface is not set, 409 # as we only care about the _mask if we call ifconfig. 410 # This is not done because we may want to santize IP addresses 411 # based on _type later, and optionally change the type as well. 412 413 # Extract the prefix/netmask/prefixlen part by cutting off the address. 414 _mask=${_r} 415 _mask=`expr "${_mask}" : "${_addr}\(.*\)"` 416 417 # Identify type {inet,inet6}. 418 case "${_addr}" in 419 *\.*\.*\.*) _type="inet" ;; 420 *:*) _type="inet6" ;; 421 *) warn "jail_extract_address: type not identified" 422 ;; 423 esac 424 425 # Handle the special /netmask instead of /prefix or 426 # "netmask xxx" case for legacy IP. 427 # We do NOT support shortend class-full netmasks. 428 if [ "${_type}" = "inet" ]; then 429 case "${_mask}" in 430 /*\.*\.*\.*) _mask=" netmask ${_mask#/}" ;; 431 *) ;; 432 esac 433 434 # In case _mask is still not set use /32. 435 _mask=${_mask:-/32} 436 437 elif [ "${_type}" = "inet6" ]; then 438 # In case _maske is not set for IPv6, use /128. 439 _mask=${_mask:-/128} 440 fi 441} 442 443# jail_handle_ips_option {add,del} input 444# Handle a single argument imput which can be a comma separated 445# list of addresses (theoretically with an option interface and 446# prefix/netmask/prefixlen). 447# 448jail_handle_ips_option() 449{ 450 local _x _action _type _i 451 _action=$1 452 _x=$2 453 454 if [ -z "${_x}" ]; then 455 # No IP given. This can happen for the primary address 456 # of each address family. 457 return 458 fi 459 460 # Loop, in case we find a comma separated list, we need to handle 461 # each argument on its own. 462 while [ ${#_x} -gt 0 ]; do 463 case "${_x}" in 464 *,*) # Extract the first argument and strip it off the list. 465 _i=`expr "${_x}" : '^\([^,]*\)'` 466 _x=`expr "${_x}" : "^[^,]*,\(.*\)"` 467 ;; 468 *) _i=${_x} 469 _x="" 470 ;; 471 esac 472 473 _type="" 474 _iface="" 475 _addr="" 476 _mask="" 477 jail_extract_address "${_i}" 478 479 # make sure we got an address. 480 case "${_addr}" in 481 "") continue ;; 482 *) ;; 483 esac 484 485 # Append address to list of addresses for the jail command. 486 case "${_addrl}" in 487 "") _addrl="${_addr}" ;; 488 *) _addrl="${_addrl},${_addr}" ;; 489 esac 490 491 # Configure interface alias if requested by a given interface 492 # and if we could correctly parse everything. 493 case "${_iface}" in 494 "") continue ;; 495 esac 496 case "${_type}" in 497 inet) ;; 498 inet6) ;; 499 *) warn "Could not determine address family. Not going" \ 500 "to ${_action} address '${_addr}' for ${_jail}." 501 continue 502 ;; 503 esac 504 case "${_action}" in 505 add) ifconfig ${_iface} ${_type} ${_addr}${_mask} alias 506 ;; 507 del) # When removing the IP, ignore the _mask. 508 ifconfig ${_iface} ${_type} ${_addr} -alias 509 ;; 510 esac 511 done 512} 513 514# jail_ips {add,del} 515# Extract the comma separated list of addresses and return them 516# for the jail command. 517# Handle more than one address via the _multi option as well. 518# If an interface is given also add/remove an alias for the 519# address with an optional netmask. 520# 521jail_ips() 522{ 523 local _action 524 _action=$1 525 526 case "${_action}" in 527 add) ;; 528 del) ;; 529 *) warn "jail_ips: invalid action '${_action}'" 530 return 531 ;; 532 esac 533 534 # Handle addresses. 535 jail_handle_ips_option ${_action} "${_ip}" 536 # Handle jail_xxx_ip_multi<N> 537 alias=0 538 while : ; do 539 eval _x=\"\$jail_${_jail}_ip_multi${alias}\" 540 case "${_x}" in 541 "") break ;; 542 *) jail_handle_ips_option ${_action} "${_x}" 543 alias=$((${alias} + 1)) 544 ;; 545 esac 546 done 547} 548 549jail_start() 550{ 551 echo -n 'Configuring jails:' 552 set_sysctl jail_set_hostname_allow security.jail.set_hostname_allowed \ 553 set_hostname_allow 554 set_sysctl jail_socket_unixiproute_only \ 555 security.jail.socket_unixiproute_only unixiproute_only 556 set_sysctl jail_sysvipc_allow security.jail.sysvipc_allowed \ 557 sysvipc_allow 558 echo '.' 559 560 echo -n 'Starting jails:' 561 _tmp_dir=`mktemp -d /tmp/jail.XXXXXXXX` || \ 562 err 3 "$name: Can't create temp dir, exiting..." 563 for _jail in ${jail_list} 564 do 565 init_variables $_jail 566 if [ -f /var/run/jail_${_jail}.id ]; then 567 echo -n " [${_hostname} already running (/var/run/jail_${_jail}.id exists)]" 568 continue; 569 fi 570 _addrl="" 571 jail_ips "add" 572 if [ -n "${_fib}" ]; then 573 _setfib="setfib -F '${_fib}'" 574 else 575 _setfib="" 576 fi 577 if checkyesno _mount; then 578 info "Mounting fstab for jail ${_jail} (${_fstab})" 579 if [ ! -f "${_fstab}" ]; then 580 err 3 "$name: ${_fstab} does not exist" 581 fi 582 jail_mount_fstab 583 fi 584 if checkyesno _devfs; then 585 # If devfs is already mounted here, skip it. 586 df -t devfs "${_devdir}" >/dev/null 587 if [ $? -ne 0 ]; then 588 if is_symlinked_mountpoint ${_devdir}; then 589 warn "${_devdir} has symlink as parent - not starting jail ${_jail}" 590 continue 591 fi 592 info "Mounting devfs on ${_devdir}" 593 devfs_mount_jail "${_devdir}" ${_ruleset} 594 # Transitional symlink for old binaries 595 if [ ! -L "${_devdir}/log" ]; then 596 __pwd="`pwd`" 597 cd "${_devdir}" 598 ln -sf ../var/run/log log 599 cd "$__pwd" 600 fi 601 fi 602 603 # XXX - It seems symlinks don't work when there 604 # is a devfs(5) device of the same name. 605 # Jail console output 606 # __pwd="`pwd`" 607 # cd "${_devdir}" 608 # ln -sf ../var/log/console console 609 # cd "$__pwd" 610 fi 611 if checkyesno _fdescfs; then 612 if is_symlinked_mountpoint ${_fdescdir}; then 613 warn "${_fdescdir} has symlink as parent, not mounting" 614 else 615 info "Mounting fdescfs on ${_fdescdir}" 616 mount -t fdescfs fdesc "${_fdescdir}" 617 fi 618 fi 619 if checkyesno _procfs; then 620 if is_symlinked_mountpoint ${_procdir}; then 621 warn "${_procdir} has symlink as parent, not mounting" 622 else 623 info "Mounting procfs onto ${_procdir}" 624 if [ -d "${_procdir}" ] ; then 625 mount -t procfs proc "${_procdir}" 626 fi 627 fi 628 fi 629 _tmp_jail=${_tmp_dir}/jail.$$
|
| 630 631 i=0 632 while : ; do 633 eval out=\"\${_exec_prestart${i}:-''}\" 634 [ -z "$out" ] && break 635 ${out} 636 i=$((i + 1)) 637 done 638
|
558 eval ${_setfib} jail ${_flags} -i ${_rootdir} ${_hostname} \ 559 \"${_addrl}\" ${_exec_start} > ${_tmp_jail} 2>&1 560 561 if [ "$?" -eq 0 ] ; then 562 _jail_id=$(head -1 ${_tmp_jail}) 563 i=1 564 while [ true ]; do 565 eval out=\"\${_exec_afterstart${i}:-''}\" 566 567 if [ -z "$out" ]; then 568 break; 569 fi 570 571 jexec "${_jail_id}" ${out} 572 i=$((i + 1)) 573 done 574 575 echo -n " $_hostname" 576 tail +2 ${_tmp_jail} >${_consolelog} 577 echo ${_jail_id} > /var/run/jail_${_jail}.id
| 639 eval ${_setfib} jail ${_flags} -i ${_rootdir} ${_hostname} \ 640 \"${_addrl}\" ${_exec_start} > ${_tmp_jail} 2>&1 641 642 if [ "$?" -eq 0 ] ; then 643 _jail_id=$(head -1 ${_tmp_jail}) 644 i=1 645 while [ true ]; do 646 eval out=\"\${_exec_afterstart${i}:-''}\" 647 648 if [ -z "$out" ]; then 649 break; 650 fi 651 652 jexec "${_jail_id}" ${out} 653 i=$((i + 1)) 654 done 655 656 echo -n " $_hostname" 657 tail +2 ${_tmp_jail} >${_consolelog} 658 echo ${_jail_id} > /var/run/jail_${_jail}.id
|
| 659 660 i=0 661 while : ; do 662 eval out=\"\${_exec_poststart${i}:-''}\" 663 [ -z "$out" ] && break 664 ${out} 665 i=$((i + 1)) 666 done
|
578 else 579 jail_umount_fs 580 jail_ips "del" 581 echo " cannot start jail \"${_jail}\": " 582 tail +2 ${_tmp_jail} 583 fi 584 rm -f ${_tmp_jail} 585 done 586 rmdir ${_tmp_dir} 587 echo '.' 588} 589 590jail_stop() 591{ 592 echo -n 'Stopping jails:' 593 for _jail in ${jail_list} 594 do 595 if [ -f "/var/run/jail_${_jail}.id" ]; then 596 _jail_id=$(cat /var/run/jail_${_jail}.id) 597 if [ ! -z "${_jail_id}" ]; then 598 init_variables $_jail
| 667 else 668 jail_umount_fs 669 jail_ips "del" 670 echo " cannot start jail \"${_jail}\": " 671 tail +2 ${_tmp_jail} 672 fi 673 rm -f ${_tmp_jail} 674 done 675 rmdir ${_tmp_dir} 676 echo '.' 677} 678 679jail_stop() 680{ 681 echo -n 'Stopping jails:' 682 for _jail in ${jail_list} 683 do 684 if [ -f "/var/run/jail_${_jail}.id" ]; then 685 _jail_id=$(cat /var/run/jail_${_jail}.id) 686 if [ ! -z "${_jail_id}" ]; then 687 init_variables $_jail
|
| 688 689 i=0 690 while : ; do 691 eval out=\"\${_exec_prestop${i}:-''}\" 692 [ -z "$out" ] && break 693 ${out} 694 i=$((i + 1)) 695 done 696
|
599 if [ -n "${_exec_stop}" ]; then 600 eval env -i /usr/sbin/jexec ${_jail_id} ${_exec_stop} \ 601 >> ${_consolelog} 2>&1 602 fi 603 killall -j ${_jail_id} -TERM > /dev/null 2>&1 604 sleep 1 605 killall -j ${_jail_id} -KILL > /dev/null 2>&1 606 jail_umount_fs 607 echo -n " $_hostname"
| 697 if [ -n "${_exec_stop}" ]; then 698 eval env -i /usr/sbin/jexec ${_jail_id} ${_exec_stop} \ 699 >> ${_consolelog} 2>&1 700 fi 701 killall -j ${_jail_id} -TERM > /dev/null 2>&1 702 sleep 1 703 killall -j ${_jail_id} -KILL > /dev/null 2>&1 704 jail_umount_fs 705 echo -n " $_hostname"
|
| 706 707 i=0 708 while : ; do 709 eval out=\"\${_exec_poststop${i}:-''}\" 710 [ -z "$out" ] && break 711 ${out} 712 i=$((i + 1)) 713 done
|
608 fi 609 jail_ips "del" 610 rm /var/run/jail_${_jail}.id 611 else 612 echo " cannot stop jail ${_jail}. No jail id in /var/run" 613 fi 614 done 615 echo '.' 616} 617 618load_rc_config $name 619cmd="$1" 620if [ $# -gt 0 ]; then 621 shift 622fi 623if [ -n "$*" ]; then 624 jail_list="$*" 625fi 626run_rc_command "${cmd}"
| 714 fi 715 jail_ips "del" 716 rm /var/run/jail_${_jail}.id 717 else 718 echo " cannot stop jail ${_jail}. No jail id in /var/run" 719 fi 720 done 721 echo '.' 722} 723 724load_rc_config $name 725cmd="$1" 726if [ $# -gt 0 ]; then 727 shift 728fi 729if [ -n "$*" ]; then 730 jail_list="$*" 731fi 732run_rc_command "${cmd}"
|