Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 420165 | Differences between
and this patch

Collapse All | Expand All

(-)a/init.d/Makefile (-1 / +1 lines)
Lines 22-28 NET_LO-FreeBSD= net.lo0 Link Here
22
SRCS-FreeBSD=	hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
22
SRCS-FreeBSD=	hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
23
		rpcbind.in savecore.in syslogd.in
23
		rpcbind.in savecore.in syslogd.in
24
# These are FreeBSD specific
24
# These are FreeBSD specific
25
SRCS-FreeBSD+=	adjkerntz.in devd.in encswap.in dumpon.in ipfw.in \
25
SRCS-FreeBSD+=	adjkerntz.in devd.in dumpon.in encswap.in ipfw.in jail.in \
26
		mixer.in nscd.in powerd.in syscons.in
26
		mixer.in nscd.in powerd.in syscons.in
27
27
28
NET_LO-Linux=	net.lo
28
NET_LO-Linux=	net.lo
(-)a/init.d/jail.in (+894 lines)
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
}

Return to bug 420165