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