xref: /openbsd/etc/rc (revision 6041cb5b)
1#	$OpenBSD: rc,v 1.551 2021/07/22 18:09:04 sthen 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 _dkdev in $(df /usr/{lib,libexec} $_relink |
179	    sed '1d;s/ .*//' | sort -u); do
180		_mp=$(mount -t ffs | grep "^$_dkdev") || return
181		if [[ $_mp == *read-only* ]]; then
182			_ro_list="$_ro_list ${_mp%% *}"
183		fi
184	done
185
186	echo -n 'reordering libraries:'
187
188	# Remount the (read-only) filessystems in _ro_list as read-write.
189	for _mp in $_ro_list; do
190		if ! mount -u -w $_mp; then
191			echo ' failed.'
192			return
193		fi
194	done
195
196	# Only choose the latest version of the libraries.
197	for _liba in $_relink/usr/lib/lib{c,crypto}; do
198		_libas="$_libas $(ls $_liba.so.+([0-9.]).a | sort -rV | head -1)"
199	done
200
201	for _liba in $_relink/usr/libexec/ld.so.a $_libas; do
202		_tmpdir=$(mktemp -dq $_relink/_rebuild.XXXXXXXXXXXX) &&
203		(
204		set -o errexit
205		_install='install -F -o root -g bin -m 0444'
206		_lib=${_liba##*/}
207		_lib=${_lib%.a}
208		_lib_dir=${_liba#$_relink}
209		_lib_dir=${_lib_dir%/*}
210		cd $_tmpdir
211		ar x $_liba
212		if [[ $_lib == ld.so ]]; then
213			args="-g -x -e _dl_start \
214			    --version-script=Symbols.map --shared -Bsymbolic \
215			    --no-undefined"
216			[[ -f ld.script ]] && args="$args -T ld.script"
217			ld $args -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) $(<.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# /etc/myname contains my symbolic name.
305if [[ -f /etc/myname ]]; then
306	hostname "$(stripcom /etc/myname)"
307fi
308
309# Must set the domainname before rc.conf, so YP startup choices can be made.
310if [[ -s /etc/defaultdomain ]]; then
311	domainname "$(stripcom /etc/defaultdomain)"
312fi
313
314# Get local functions from rc.subr to load rc.conf into scope.
315FUNCS_ONLY=1 . /etc/rc.d/rc.subr
316_rc_parse_conf
317
318# If executed with the 'shutdown' parameter by the halt, reboot or shutdown:
319# - update seed files
320# - execute the rc.d scripts specified by $pkg_scripts in reverse order
321# - bring carp interfaces down gracefully
322if [[ $1 == shutdown ]]; then
323	if echo 2>/dev/null >>/var/db/host.random ||
324	    echo 2>/dev/null >>/etc/random.seed; then
325		random_seed
326	else
327		echo warning: cannot write random seed to disk
328	fi
329
330	# If we are in secure level 0, assume single user mode.
331	if (($(sysctl -n kern.securelevel) == 0)); then
332		echo 'single user: not running shutdown scripts'
333	else
334		set -A _d -- $pkg_scripts
335		_i=${#_d[*]}
336		if ((_i)); then
337			echo -n 'stopping package daemons:'
338			while ((--_i >= 0)); do
339				[[ -x /etc/rc.d/${_d[_i]} ]] &&
340					/etc/rc.d/${_d[_i]} stop
341			done
342			echo '.'
343		fi
344
345		if /etc/rc.d/vmd check > /dev/null; then
346			echo -n 'stopping VMs'
347			/etc/rc.d/vmd stop > /dev/null
348			echo '.'
349		fi
350
351		[[ -f /etc/rc.shutdown ]] && sh /etc/rc.shutdown
352	fi
353
354	ifconfig | while read _if _junk; do
355		[[ $_if == carp+([0-9]): ]] && ifconfig ${_if%:} down
356	done
357
358	exit 0
359fi
360
361# If bootblocks failed to give us random, try to cause some churn
362(dmesg; sysctl hw.{uuid,serialno,sensors} ) >/dev/random 2>&1
363
364# Add swap block-devices.
365swapctl -A -t blk
366
367# Run filesystem check unless a /fastboot file exists.
368if [[ -e /fastboot ]]; then
369	echo "Fast boot: skipping disk checks."
370elif [[ $1 == autoboot ]]; then
371	echo "Automatic boot in progress: starting file system checks."
372	do_fsck
373fi
374
375# From now on, allow user to interrupt (^C) the boot process.
376trap "echo 'Boot interrupted.'; exit 1" 3
377
378# Unmount all filesystems except root.
379umount -a >/dev/null 2>&1
380
381# Mount all filesystems except those of type NFS and VND.
382mount -a -t nonfs,vnd
383
384# Re-mount the root filesystem read/writeable. (root on nfs requires this,
385# others aren't hurt.)
386mount -uw /
387chmod og-rwx /bsd
388ln -fh /bsd /bsd.booted
389
390rm -f /fastboot
391
392# Set flags on ttys.
393ttyflags -a
394
395# Set keyboard encoding.
396if [[ -x /sbin/kbd && -s /etc/kbdtype ]]; then
397	kbd "$(</etc/kbdtype)"
398fi
399
400wsconsctl_conf
401
402# Set initial temporary pf rule set.
403if [[ $pf != NO ]]; then
404	RULES="
405	block all
406	pass on lo0
407	pass in proto tcp from any to any port ssh keep state
408	pass out proto { tcp, udp } from any to any port domain keep state
409	pass out inet proto icmp all icmp-type echoreq keep state
410	pass out inet proto udp from any port bootpc to any port bootps
411	pass in inet proto udp from any port bootps to any port bootpc"
412
413	if ifconfig lo0 inet6 >/dev/null 2>&1; then
414		RULES="$RULES
415		pass out inet6 proto icmp6 all icmp6-type neighbrsol
416		pass in inet6 proto icmp6 all icmp6-type neighbradv
417		pass out inet6 proto icmp6 all icmp6-type routersol
418		pass in inet6 proto icmp6 all icmp6-type routeradv
419		pass out inet6 proto udp from any port dhcpv6-client to any port dhcpv6-server
420		pass in inet6 proto udp from any port dhcpv6-server to any port dhcpv6-client"
421	fi
422
423	RULES="$RULES
424	pass in proto carp keep state (no-sync)
425	pass out proto carp !received-on any keep state (no-sync)"
426
427	if (($(sysctl -n vfs.mounts.nfs 2>/dev/null)+0 > 0)); then
428		# Don't kill NFS.
429		RULES="set reassemble yes no-df
430		$RULES
431		pass in proto { tcp, udp } from any port { sunrpc, nfsd } to any
432		pass out proto { tcp, udp } from any to any port { sunrpc, nfsd } !received-on any"
433	fi
434
435	print -- "$RULES" | pfctl -f -
436	pfctl -e
437fi
438
439fill_baddynamic udp
440fill_baddynamic tcp
441
442sysctl_conf
443
444start_daemon slaacd >/dev/null 2>&1
445
446echo 'starting network'
447
448# Set carp interlock by increasing the demotion counter.
449# Prevents carp from preempting until the system is booted.
450ifconfig -g carp carpdemote 128
451
452sh /etc/netstart
453
454mount -s /usr >/dev/null 2>&1
455mount -s /var >/dev/null 2>&1
456
457start_daemon dhcpleased unwind resolvd >/dev/null 2>&1
458
459random_seed
460
461reorder_libs
462
463# Pause a little so at least one dynamic (slaacd or dhcpleased) config completes
464count=0
465while ((count++ < 20)); do
466	route -n show | grep -q ^default && break
467	sleep .5
468done
469
470# Load pf rules and bring up pfsync interface.
471if [[ $pf != NO ]]; then
472	if [[ -f /etc/pf.conf ]]; then
473		pfctl -f /etc/pf.conf
474	fi
475	if [[ -f /etc/hostname.pfsync0 ]]; then
476		sh /etc/netstart pfsync0
477	fi
478fi
479
480# Clean up left-over files.
481rm -f /etc/nologin /var/spool/lock/LCK.*
482(cd /var/run && { rm -rf -- *; install -c -m 664 -g utmp /dev/null utmp; })
483(cd /var/authpf && rm -rf -- *)
484
485# Save a copy of the boot messages.
486dmesg >/var/run/dmesg.boot
487
488make_keys
489
490echo -n 'starting early daemons:'
491start_daemon syslogd ldattach pflogd nsd unbound ntpd
492start_daemon iscsid isakmpd iked sasyncd ldapd npppd
493echo '.'
494
495# Load IPsec rules.
496if [[ $ipsec != NO && -f /etc/ipsec.conf ]]; then
497	ipsecctl -f /etc/ipsec.conf
498fi
499
500echo -n 'starting RPC daemons:'
501start_daemon portmap ypldap
502rm -f /var/run/ypbind.lock
503if [[ -n $(domainname) ]]; then
504	start_daemon ypserv ypbind
505fi
506start_daemon mountd nfsd lockd statd amd
507echo '.'
508
509# Check and mount remaining file systems and enable additional swap.
510mount -a
511swapctl -A -t noblk
512do_fsck -N
513mount -a -N
514
515# Build kvm(3) and /dev databases.
516kvm_mkdb
517dev_mkdb
518
519# /var/crash should be a directory or a symbolic link to the crash directory
520# if core dumps are to be saved.
521if [[ -d /var/crash ]]; then
522	savecore $savecore_flags /var/crash
523fi
524
525# Store ACPI tables in /var/db/acpi to be used by sendbug(1).
526if [[ -x /usr/sbin/acpidump ]]; then
527	acpidump -q -o /var/db/acpi/
528fi
529
530if [[ $check_quotas == YES ]]; then
531	echo -n 'checking quotas:'
532	quotacheck -a
533	echo ' done.'
534	quotaon -a
535fi
536
537# Set proper permission for the tty device files.
538chmod 666 /dev/tty[pqrstuvwxyzPQRST]*
539chown root:wheel /dev/tty[pqrstuvwxyzPQRST]*
540
541# Check for the password temp/lock file.
542if [[ -f /etc/ptmp ]]; then
543	logger -s -p auth.err \
544	    'password file may be incorrect -- /etc/ptmp exists'
545fi
546
547echo clearing /tmp
548
549# Prune quickly with one rm, then use find to clean up /tmp/[lqv]*
550# (not needed with mfs /tmp, but doesn't hurt there...).
551(cd /tmp && rm -rf [a-km-pr-uw-zA-Z]*)
552(cd /tmp &&
553    find . -maxdepth 1 ! -name . ! -name lost+found ! -name quota.user \
554	! -name quota.group ! -name vi.recover -execdir rm -rf -- {} \;)
555
556# Create Unix sockets directories for X if needed and make sure they have
557# correct permissions.
558[[ -d /usr/X11R6/lib ]] && mkdir -m 1777 /tmp/.{X11,ICE}-unix
559
560[[ -f /etc/rc.securelevel ]] && sh /etc/rc.securelevel
561
562# rc.securelevel did not specifically set -1 or 2, so select the default: 1.
563(($(sysctl -n kern.securelevel) == 0)) && sysctl kern.securelevel=1
564
565
566# Patch /etc/motd.
567if [[ ! -f /etc/motd ]]; then
568	install -c -o root -g wheel -m 664 /dev/null /etc/motd
569fi
570if T=$(mktemp /tmp/_motd.XXXXXXXXXX); then
571	sysctl -n kern.version | sed 1q >$T
572	sed -n '/^$/,$p' </etc/motd >>$T
573	cmp -s $T /etc/motd || cp $T /etc/motd
574	rm -f $T
575fi
576
577if [[ $accounting == YES ]]; then
578	[[ ! -f /var/account/acct ]] && touch /var/account/acct
579	echo 'turning on accounting'
580	accton /var/account/acct
581fi
582
583if [[ -x /sbin/ldconfig ]]; then
584	echo 'creating runtime link editor directory cache.'
585	[[ -d /usr/local/lib ]] && shlib_dirs="/usr/local/lib $shlib_dirs"
586	[[ -d /usr/X11R6/lib ]] && shlib_dirs="/usr/X11R6/lib $shlib_dirs"
587	ldconfig $shlib_dirs
588fi
589
590echo 'preserving editor files.'; /usr/libexec/vi.recover
591
592# If rc.sysmerge exists, run it just once, and make sure it is deleted.
593run_upgrade_script sysmerge
594
595echo -n 'starting network daemons:'
596start_daemon ldomd sshd switchd snmpd ldpd ripd ospfd ospf6d bgpd ifstated
597start_daemon relayd dhcpd dhcrelay mrouted dvmrpd radiusd eigrpd route6d
598start_daemon rad hostapd lpd smtpd slowcgi httpd ftpd
599start_daemon ftpproxy ftpproxy6 tftpd tftpproxy identd inetd rarpd bootparamd
600start_daemon rbootd mopd vmd spamd spamlogd sndiod
601echo '.'
602
603# If rc.firsttime exists, run it just once, and make sure it is deleted.
604run_upgrade_script firsttime
605
606# Run rc.d(8) scripts from packages.
607if [[ -n $pkg_scripts ]]; then
608	echo -n 'starting package daemons:'
609	for _daemon in $pkg_scripts; do
610		if [[ -x /etc/rc.d/$_daemon ]]; then
611			start_daemon $_daemon
612		else
613			echo -n " ${_daemon}(absent)"
614		fi
615	done
616	echo '.'
617fi
618
619[[ -f /etc/rc.local ]] && sh /etc/rc.local
620
621# Disable carp interlock.
622ifconfig -g carp -carpdemote 128
623
624mixerctl_conf
625
626echo -n 'starting local daemons:'
627start_daemon apmd sensorsd hotplugd watchdogd cron wsmoused xenodm
628echo '.'
629
630# Re-link the kernel, placing the objects in a random order.
631# Replace current with relinked kernel and inform root about it.
632/usr/libexec/reorder_kernel &
633
634date
635exit 0
636