xref: /openbsd-src/etc/rc (revision 9f11ffb7133c203312a01e4b986886bc88c7d74b)
1#	$OpenBSD: rc,v 1.532 2019/01/26 10:59:07 florian Exp $
2
3# System startup script run by init on autoboot or after single-user.
4# Output and error are redirected to console by init, and the console is the
5# controlling terminal.
6
7# Turn off Strict Bourne shell.
8set +o sh
9
10# Subroutines (have to come first).
11
12# Strip in- and whole-line comments from a file.
13# Strip leading and trailing whitespace if IFS is set.
14# Usage: stripcom /path/to/file
15stripcom() {
16	local _file=$1 _line
17
18	[[ -s $_file ]] || return
19
20	while read _line ; do
21		_line=${_line%%#*}
22		[[ -n $_line ]] && print -r -- "$_line"
23	done <$_file
24}
25
26# Update resource limits based on login.conf settings.
27# Usage: update_limit -flag capability
28update_limit() {
29	local _flag=$1		# ulimit flag
30	local _cap=$2 _val	# login.conf capability and its value
31	local _suffix
32
33	for _suffix in {,-max,-cur}; do
34		_val=$(getcap -f /etc/login.conf -s ${_cap}${_suffix} daemon 2>/dev/null)
35		[[ -n $_val ]] || continue
36		[[ $_val == infinity ]] && _val=unlimited
37
38		case $_suffix in
39		-cur)	ulimit -S $_flag $_val
40			;;
41		-max)	ulimit -H $_flag $_val
42			;;
43		*)	ulimit $_flag $_val
44			return
45			;;
46		esac
47	done
48}
49
50# Apply sysctl.conf(5) settings.
51sysctl_conf() {
52	# do not use a pipe as limits would only be applied to the subshell
53	set -- $(stripcom /etc/sysctl.conf)
54	while [[ $# > 0 ]] ; do
55		sysctl "$1"
56
57		case "$1" in
58		kern.maxproc=*)
59			update_limit -p maxproc
60			;;
61		kern.maxfiles=*)
62			update_limit -n openfiles
63			;;
64		esac
65		shift
66	done
67}
68
69# Apply mixerctl.conf(5) settings.
70mixerctl_conf() {
71	stripcom /etc/mixerctl.conf |
72	while read _line; do
73		mixerctl -q "$_line" 2>/dev/null
74	done
75}
76
77# Apply wsconsctl.conf(5) settings.
78wsconsctl_conf() {
79	[[ -x /sbin/wsconsctl ]] || return
80
81	stripcom /etc/wsconsctl.conf |
82	while read _line; do
83		eval "wsconsctl $_line"
84	done
85}
86
87# Push the old seed into the kernel, create a future seed  and create a seed
88# file for the boot-loader.
89random_seed() {
90	dd if=/var/db/host.random of=/dev/random bs=65536 count=1 status=none
91	chmod 600 /var/db/host.random
92	dd if=/dev/random of=/var/db/host.random bs=65536 count=1 status=none
93	dd if=/dev/random of=/etc/random.seed bs=512 count=1 status=none
94	chmod 600 /etc/random.seed
95}
96
97# Populate net.inet.(tcp|udp).baddynamic with the contents of /etc/services so
98# as to avoid randomly allocating source ports that correspond to well-known
99# services.
100# Usage: fill_baddynamic tcp|udp
101fill_baddynamic() {
102	local _service=$1
103	local _sysctl="net.inet.${_service}.baddynamic"
104
105	stripcom /etc/services |
106	{
107		_ban=
108		while IFS=" 	/" read _name _port _srv _junk; do
109			[[ $_srv == $_service ]] || continue
110
111			_ban="${_ban:+$_ban,}+$_port"
112
113			# Flush before argv gets too long
114			if ((${#_ban} > 1024)); then
115				sysctl -q "$_sysctl=$_ban"
116				_ban=
117			fi
118		done
119		[[ -n $_ban ]] && sysctl -q "$_sysctl=$_ban"
120	}
121}
122
123# Start daemon using the rc.d daemon control scripts.
124# Usage: start_daemon daemon1 daemon2 daemon3
125start_daemon() {
126	local _daemon
127
128	for _daemon; do
129		eval "_do=\${${_daemon}_flags}"
130		[[ $_do != NO ]] && /etc/rc.d/${_daemon} start
131	done
132}
133
134# Generate keys for isakmpd, iked and sshd if they don't exist yet.
135make_keys() {
136	local _isakmpd_key=/etc/isakmpd/private/local.key
137	local _isakmpd_pub=/etc/isakmpd/local.pub
138	local _iked_key=/etc/iked/private/local.key
139	local _iked_pub=/etc/iked/local.pub
140
141	if [[ ! -f $_isakmpd_key ]]; then
142		echo -n "openssl: generating isakmpd/iked RSA keys... "
143		if openssl genrsa -out $_isakmpd_key 2048 >/dev/null 2>&1 &&
144			chmod 600 $_isakmpd_key &&
145			openssl rsa -out $_isakmpd_pub -in $_isakmpd_key \
146			    -pubout >/dev/null 2>&1; then
147			echo done.
148		else
149			echo failed.
150		fi
151	fi
152
153	if [[ ! -f $_iked_key ]]; then
154		# Just copy the generated isakmpd key
155		cp $_isakmpd_key $_iked_key
156		chmod 600 $_iked_key
157		cp $_isakmpd_pub $_iked_pub
158	fi
159
160	ssh-keygen -A
161
162	if [[ ! -f /etc/soii.key ]]; then
163		openssl rand -hex 16 > /etc/soii.key &&
164		    chmod 600 /etc/soii.key && sysctl -q \
165		    "net.inet6.ip6.soiikey=$(</etc/soii.key)"
166	fi
167}
168
169# Re-link libraries, placing the objects in a random order.
170reorder_libs() {
171	local _error=false _dkdev _liba _libas _mp _ro_list _tmpdir
172	local _relink=/usr/share/relink
173
174	[[ $library_aslr == NO ]] && return
175
176	# Skip if /usr/lib, /usr/libexec or /usr/share/relink are on nfs mounted
177	# filesystems, otherwise record which ones are mounted read-only.
178	for _d in /usr/{lib,libexec,share/relink}; do
179		_dkdev=$(df $_d | sed '1d;s/ .*//')
180		_mp=$(mount | grep "^$_dkdev")
181		[[ $_mp == *" type nfs "* ]] && return
182		if [[ $_mp == *" type ffs "*"read-only"* &&
183			$_ro_list != *${_mp%% *}* ]]; then
184				_ro_list="$_ro_list ${_mp%% *}"
185		fi
186	done
187
188	echo -n 'reordering libraries:'
189
190	# Remount the (read-only) filessystems in _ro_list as read-write.
191	for _mp in $_ro_list; do
192		if ! mount -u -w $_mp; then
193			echo ' failed.'
194			return
195		fi
196	done
197
198	# Only choose the latest version of the libraries.
199	for _liba in $_relink/usr/lib/lib{c,crypto}; do
200		_libas="$_libas $(ls $_liba.so.+([0-9.]).a | sort -rV | head -1)"
201	done
202
203	for _liba in $_relink/usr/libexec/ld.so.a $_libas; do
204		_tmpdir=$(mktemp -dq $_relink/_rebuild.XXXXXXXXXXXX) &&
205		(
206		set -o errexit
207		_install='install -F -S -o root -g bin -m 0444'
208		_lib=${_liba##*/}
209		_lib=${_lib%.a}
210		_lib_dir=${_liba#$_relink}
211		_lib_dir=${_lib_dir%/*}
212		cd $_tmpdir
213		ar x $_liba
214		if [[ $_lib == ld.so ]]; then
215			ld -g -x -e _dl_start \
216			    --version-script=Symbols.map --shared -Bsymbolic \
217			    --no-undefined -o ld.so.test $(ls *.o | sort -R)
218			chmod u+x test-ld.so
219			[[ $(./test-ld.so ok) == './test-ld.so: ok!' ]]
220			$_install /usr/libexec/ld.so /usr/libexec/ld.so.save
221			$_install ld.so.test $_lib_dir/ld.so
222		else
223			cc -shared -o $_lib $(ls *.so | sort -R) $(cat .ldadd)
224			[[ -s $_lib ]] && file $_lib | fgrep -q 'shared object'
225			LD_BIND_NOW=1 LD_LIBRARY_PATH=$_tmpdir awk 'BEGIN {exit 0}'
226			LD_BIND_NOW=1 LD_LIBRARY_PATH=$_tmpdir openssl \
227			    x509 -in /etc/ssl/cert.pem -out /dev/null
228			$_install $_lib $_lib_dir/$_lib
229		fi
230		) || { _error=true; break; }
231	done
232
233	rm -rf $_relink/_rebuild.*
234
235	# Restore previous mount state if it was changed.
236	for _mp in $_ro_list; do
237		mount -u -r $_mp || _error=true
238	done
239
240	if $_error; then
241		echo ' failed.'
242	else
243		echo ' done.'
244	fi
245}
246
247# Run rc.* script and email output to root.
248# Usage: run_upgrade_script firsttime|sysmerge
249run_upgrade_script() {
250	local _suffix=$1
251
252	[[ -n $_suffix ]] || return 1
253
254	if [[ -f /etc/rc.$_suffix ]]; then
255		echo "running rc.$_suffix"
256		mv /etc/rc.$_suffix /etc/rc.$_suffix.run
257		. /etc/rc.$_suffix.run 2>&1 | tee /dev/tty |
258			mail -Es "$(hostname) rc.$_suffix output" root >/dev/null
259	fi
260	rm -f /etc/rc.$_suffix.run
261}
262
263# Check filesystems, optionally by using a fsck(8) flag.
264# Usage: do_fsck [-flag]
265do_fsck() {
266	fsck -p "$@"
267	case $? in
268	0)	;;
269	2)	exit 1
270		;;
271	4)	echo "Rebooting..."
272		reboot
273		echo "Reboot failed; help!"
274		exit 1
275		;;
276	8)	echo "Automatic file system check failed; help!"
277		exit 1
278		;;
279	12)	echo "Boot interrupted."
280		exit 1
281		;;
282	130)	# Interrupt before catcher installed.
283		exit 1
284		;;
285	*)	echo "Unknown error; help!"
286		exit 1
287		;;
288	esac
289}
290
291# End subroutines.
292
293stty status '^T'
294
295# Set shell to ignore SIGINT (2), but not children; shell catches SIGQUIT (3)
296# and returns to single user after fsck.
297trap : 2
298trap : 3	# Shouldn't be needed.
299
300export HOME=/
301export INRC=1
302export PATH=/sbin:/bin:/usr/sbin:/usr/bin
303
304# Must set the domainname before rc.conf, so YP startup choices can be made.
305if [[ -s /etc/defaultdomain ]]; then
306	domainname "$(stripcom /etc/defaultdomain)"
307fi
308
309# Get local functions from rc.subr to load rc.conf into scope.
310FUNCS_ONLY=1 . /etc/rc.d/rc.subr
311_rc_parse_conf
312
313# If executed with the 'shutdown' parameter by the halt, reboot or shutdown:
314# - update seed files
315# - execute the rc.d scripts specified by $pkg_scripts in reverse order
316# - bring carp interfaces down gracefully
317if [[ $1 == shutdown ]]; then
318	if echo 2>/dev/null >>/var/db/host.random ||
319	    echo 2>/dev/null >>/etc/random.seed; then
320		random_seed
321	else
322		echo warning: cannot write random seed to disk
323	fi
324
325	# If we are in secure level 0, assume single user mode.
326	if (($(sysctl -n kern.securelevel) == 0)); then
327		echo 'single user: not running shutdown scripts'
328	else
329		set -A _d -- $pkg_scripts
330		_i=${#_d[*]}
331		if ((_i)); then
332			echo -n 'stopping package daemons:'
333			while ((--_i >= 0)); do
334				[[ -x /etc/rc.d/${_d[_i]} ]] &&
335					/etc/rc.d/${_d[_i]} stop
336			done
337			echo '.'
338		fi
339
340		if /etc/rc.d/vmd check > /dev/null; then
341			echo -n 'stopping VMs'
342			/etc/rc.d/vmd stop > /dev/null
343			echo '.'
344		fi
345
346		[[ -f /etc/rc.shutdown ]] && sh /etc/rc.shutdown
347	fi
348
349	ifconfig | while read _if _junk; do
350		[[ $_if == carp+([0-9]): ]] && ifconfig ${_if%:} down
351	done
352
353	exit 0
354fi
355
356# Add swap block-devices.
357swapctl -A -t blk
358
359# Run filesystem check unless a /fastboot file exists.
360if [[ -e /fastboot ]]; then
361	echo "Fast boot: skipping disk checks."
362elif [[ $1 == autoboot ]]; then
363	echo "Automatic boot in progress: starting file system checks."
364	do_fsck
365fi
366
367# From now on, allow user to interrupt (^C) the boot process.
368trap "echo 'Boot interrupted.'; exit 1" 3
369
370# Unmount all filesystems except root.
371umount -a >/dev/null 2>&1
372
373# Mount all filesystems except those of type NFS and VND.
374mount -a -t nonfs,vnd
375
376# Re-mount the root filesystem read/writeable. (root on nfs requires this,
377# others aren't hurt.)
378mount -uw /
379chmod og-rwx /bsd
380ln -fh /bsd /bsd.booted
381
382rm -f /fastboot
383
384# Set flags on ttys.
385ttyflags -a
386
387# Set keyboard encoding.
388if [[ -x /sbin/kbd && -s /etc/kbdtype ]]; then
389	kbd "$(cat /etc/kbdtype)"
390fi
391
392wsconsctl_conf
393
394# Set initial temporary pf rule set.
395if [[ $pf != NO ]]; then
396	RULES="
397	block all
398	pass on lo0
399	pass in proto tcp from any to any port ssh keep state
400	pass out proto { tcp, udp } from any to any port domain keep state
401	pass out inet proto icmp all icmp-type echoreq keep state
402	pass out inet proto udp from any port bootpc to any port bootps
403	pass in inet proto udp from any port bootps to any port bootpc"
404
405	if ifconfig lo0 inet6 >/dev/null 2>&1; then
406		RULES="$RULES
407		pass out inet6 proto icmp6 all icmp6-type neighbrsol
408		pass in inet6 proto icmp6 all icmp6-type neighbradv
409		pass out inet6 proto icmp6 all icmp6-type routersol
410		pass in inet6 proto icmp6 all icmp6-type routeradv
411		pass out inet6 proto udp from any port dhcpv6-client to any port dhcpv6-server
412		pass in inet6 proto udp from any port dhcpv6-server to any port dhcpv6-client"
413	fi
414
415	RULES="$RULES
416	pass in proto carp keep state (no-sync)
417	pass out proto carp !received-on any keep state (no-sync)"
418
419	if (($(sysctl -n vfs.mounts.nfs 2>/dev/null) > 0)); then
420		# Don't kill NFS.
421		RULES="set reassemble yes no-df
422		$RULES
423		pass in proto { tcp, udp } from any port { sunrpc, nfsd } to any
424		pass out proto { tcp, udp } from any to any port { sunrpc, nfsd } !received-on any"
425	fi
426
427	print -- "$RULES" | pfctl -f -
428	pfctl -e
429fi
430
431fill_baddynamic udp
432fill_baddynamic tcp
433
434sysctl_conf
435
436start_daemon slaacd >/dev/null 2>&1
437
438echo 'starting network'
439
440# Set carp interlock by increasing the demotion counter.
441# Prevents carp from preempting until the system is booted.
442ifconfig -g carp carpdemote 128
443
444sh /etc/netstart
445
446# Any write triggers a rekey.
447dmesg >/dev/random
448
449# Load pf rules and bring up pfsync interface.
450if [[ $pf != NO ]]; then
451	if [[ -f /etc/pf.conf ]]; then
452		pfctl -f /etc/pf.conf
453	fi
454	if [[ -f /etc/hostname.pfsync0 ]]; then
455		sh /etc/netstart pfsync0
456	fi
457fi
458
459mount -s /usr >/dev/null 2>&1
460mount -s /var >/dev/null 2>&1
461
462random_seed
463
464reorder_libs
465
466# Clean up left-over files.
467rm -f /etc/nologin /var/spool/lock/LCK.*
468(cd /var/run && { rm -rf -- *; install -c -m 664 -g utmp /dev/null utmp; })
469(cd /var/authpf && rm -rf -- *)
470
471# Save a copy of the boot messages.
472dmesg >/var/run/dmesg.boot
473
474make_keys
475
476echo -n 'starting early daemons:'
477start_daemon syslogd ldattach pflogd nsd rebound unwind unbound ntpd
478start_daemon iscsid isakmpd iked sasyncd ldapd npppd
479echo '.'
480
481# Load IPsec rules.
482if [[ $ipsec != NO && -f /etc/ipsec.conf ]]; then
483	ipsecctl -f /etc/ipsec.conf
484fi
485
486echo -n 'starting RPC daemons:'
487start_daemon portmap ypldap
488rm -f /var/run/ypbind.lock
489if [[ -n $(domainname) ]]; then
490	start_daemon ypserv ypbind
491fi
492start_daemon mountd nfsd lockd statd amd
493echo '.'
494
495# Check and mount remaining file systems and enable additional swap.
496mount -a
497swapctl -A -t noblk
498do_fsck -N
499mount -a -N
500
501# /var/crash should be a directory or a symbolic link to the crash directory
502# if core dumps are to be saved.
503if [[ -d /var/crash ]]; then
504	savecore $savecore_flags /var/crash
505fi
506
507# Store ACPI tables in /var/db/acpi to be used by sendbug(1).
508if [[ -x /usr/sbin/acpidump ]]; then
509	acpidump -q -o /var/db/acpi/
510fi
511
512if [[ $check_quotas == YES ]]; then
513	echo -n 'checking quotas:'
514	quotacheck -a
515	echo ' done.'
516	quotaon -a
517fi
518
519# Build kvm(3) and /dev databases.
520kvm_mkdb
521dev_mkdb
522
523# Set proper permission for the tty device files.
524chmod 666 /dev/tty[pqrstuvwxyzPQRST]*
525chown root:wheel /dev/tty[pqrstuvwxyzPQRST]*
526
527# Check for the password temp/lock file.
528if [[ -f /etc/ptmp ]]; then
529	logger -s -p auth.err \
530	    'password file may be incorrect -- /etc/ptmp exists'
531fi
532
533echo clearing /tmp
534
535# Prune quickly with one rm, then use find to clean up /tmp/[lqv]*
536# (not needed with mfs /tmp, but doesn't hurt there...).
537(cd /tmp && rm -rf [a-km-pr-uw-zA-Z]*)
538(cd /tmp &&
539    find . -maxdepth 1 ! -name . ! -name lost+found ! -name quota.user \
540	! -name quota.group ! -name vi.recover -execdir rm -rf -- {} \;)
541
542# Create Unix sockets directories for X if needed and make sure they have
543# correct permissions.
544[[ -d /usr/X11R6/lib ]] && mkdir -m 1777 /tmp/.{X11,ICE}-unix
545
546[[ -f /etc/rc.securelevel ]] && sh /etc/rc.securelevel
547
548# rc.securelevel did not specifically set -1 or 2, so select the default: 1.
549(($(sysctl -n kern.securelevel) == 0)) && sysctl kern.securelevel=1
550
551
552# Patch /etc/motd.
553if [[ ! -f /etc/motd ]]; then
554	install -c -o root -g wheel -m 664 /dev/null /etc/motd
555fi
556if T=$(mktemp /tmp/_motd.XXXXXXXXXX); then
557	sysctl -n kern.version | sed 1q >$T
558	sed -n '/^$/,$p' </etc/motd >>$T
559	cmp -s $T /etc/motd || cp $T /etc/motd
560	rm -f $T
561fi
562
563if [[ $accounting == YES ]]; then
564	[[ ! -f /var/account/acct ]] && touch /var/account/acct
565	echo 'turning on accounting'
566	accton /var/account/acct
567fi
568
569if [[ -x /sbin/ldconfig ]]; then
570	echo 'creating runtime link editor directory cache.'
571	[[ -d /usr/local/lib ]] && shlib_dirs="/usr/local/lib $shlib_dirs"
572	[[ -d /usr/X11R6/lib ]] && shlib_dirs="/usr/X11R6/lib $shlib_dirs"
573	ldconfig $shlib_dirs
574fi
575
576echo 'preserving editor files.'; /usr/libexec/vi.recover
577
578# If rc.sysmerge exists, run it just once, and make sure it is deleted.
579run_upgrade_script sysmerge
580
581echo -n 'starting network daemons:'
582start_daemon ldomd sshd switchd snmpd ldpd ripd ospfd ospf6d bgpd ifstated
583start_daemon relayd dhcpd dhcrelay mrouted dvmrpd radiusd eigrpd route6d
584start_daemon rad hostapd lpd smtpd slowcgi httpd ftpd
585start_daemon ftpproxy ftpproxy6 tftpd tftpproxy identd inetd rarpd bootparamd
586start_daemon rbootd mopd vmd spamd spamlogd sndiod
587echo '.'
588
589# If rc.firsttime exists, run it just once, and make sure it is deleted.
590run_upgrade_script firsttime
591
592# Run rc.d(8) scripts from packages.
593if [[ -n $pkg_scripts ]]; then
594	echo -n 'starting package daemons:'
595	for _daemon in $pkg_scripts; do
596		if [[ -x /etc/rc.d/$_daemon ]]; then
597			start_daemon $_daemon
598		else
599			echo -n " ${_daemon}(absent)"
600		fi
601	done
602	echo '.'
603fi
604
605[[ -f /etc/rc.local ]] && sh /etc/rc.local
606
607# Disable carp interlock.
608ifconfig -g carp -carpdemote 128
609
610mixerctl_conf
611
612echo -n 'starting local daemons:'
613start_daemon apmd sensorsd hotplugd watchdogd cron wsmoused xenodm
614echo '.'
615
616# Re-link the kernel, placing the objects in a random order.
617# Replace current with relinked kernel and inform root about it.
618/usr/libexec/reorder_kernel &
619
620date
621exit 0
622