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