1# $OpenBSD: rc,v 1.574 2024/04/02 08:21:04 deraadt 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 local _ssh_pub=/etc/ssh/ssh_host_ed25519_key.pub _show_ssh_fp=false 141 142 if [[ ! -f $_isakmpd_key ]]; then 143 echo -n "openssl: generating isakmpd RSA keys... " 144 if openssl genrsa -out $_isakmpd_key 2048 >/dev/null 2>&1 && 145 chmod 600 $_isakmpd_key && 146 openssl rsa -out $_isakmpd_pub -in $_isakmpd_key \ 147 -pubout >/dev/null 2>&1; then 148 echo done. 149 else 150 echo failed. 151 fi 152 fi 153 154 if [[ ! -f $_iked_key ]]; then 155 echo -n "openssl: generating iked ECDSA keys... " 156 if openssl ecparam -genkey -name prime256v1 -out $_iked_key >/dev/null 2>&1 && 157 chmod 600 $_iked_key && 158 openssl ec -out $_iked_pub -in $_iked_key \ 159 -pubout >/dev/null 2>&1; then 160 echo done. 161 else 162 echo failed. 163 fi 164 fi 165 166 [[ -f $_ssh_pub ]] || _show_ssh_fp=true 167 ssh-keygen -A 168 $_show_ssh_fp && ssh-keygen -lf $_ssh_pub | 169 (read sz fp comm type && echo "sshd: $type $fp") 170 171 if [[ ! -f /etc/soii.key ]]; then 172 openssl rand -hex 16 > /etc/soii.key && 173 chmod 600 /etc/soii.key && sysctl -q \ 174 "net.inet6.ip6.soiikey=$(</etc/soii.key)" 175 fi 176} 177 178# Re-link libraries, placing the objects in a random order. 179reorder_libs() { 180 local _error=false _dkdev _liba _libas _mp _ro_list _tmpdir 181 local _relink=/usr/share/relink 182 183 [[ $library_aslr == NO ]] && return 184 185 # Skip if /usr/lib, /usr/libexec or /usr/share/relink are on nfs mounted 186 # filesystems, otherwise record which ones are mounted read-only. 187 for _dkdev in $(df /usr/{lib,libexec} $_relink | 188 sed '1d;s/ .*//' | sort -u); do 189 _mp=$(mount -t ffs | grep "^$_dkdev") || return 190 if [[ $_mp == *read-only* ]]; then 191 _ro_list="$_ro_list ${_mp%% *}" 192 fi 193 done 194 195 echo 'reordering:' 196 197 # Remount the (read-only) filesystems in _ro_list as read-write. 198 for _mp in $_ro_list; do 199 if ! mount -u -w $_mp; then 200 echo '(failed).' 201 return 202 fi 203 done 204 205 # Only choose the latest version of the libraries. 206 for _liba in $_relink/usr/lib/lib{c,crypto}; do 207 _libas="$_libas $(ls $_liba.so.+([0-9.]).a | sort -rV | head -1)" 208 done 209 210 for _liba in $_relink/usr/libexec/ld.so.a $_libas; do 211 _tmpdir=$(mktemp -dq $_relink/_rebuild.XXXXXXXXXXXX) && 212 ( 213 set -o errexit 214 _install='install -F -o root -g bin -m 0444' 215 _lib=${_liba##*/} 216 _lib=${_lib%.a} 217 _lib_dir=${_liba#$_relink} 218 _lib_dir=${_lib_dir%/*} 219 cd $_tmpdir 220 ar x $_liba 221 if [[ $_lib == ld.so ]]; then 222 echo " $_lib" 223 args="-g -x -e _dl_start \ 224 --version-script=Symbols.map --shared -Bsymbolic \ 225 --no-undefined" 226 [[ -f ld.script ]] && args="$args -T ld.script" 227 ld $args -o ld.so.test $(ls *.o | sort -R) 228 chmod u+x test-ld.so 229 [[ $(./test-ld.so ok) == './test-ld.so: ok!' ]] 230 $_install /usr/libexec/ld.so /usr/libexec/ld.so.save 231 $_install ld.so.test $_lib_dir/ld.so 232 else 233 echo " ${_lib%%.*}" 234 cc -shared -o $_lib $(ls *.so | sort -R) $(<.ldadd) 235 [[ -s $_lib ]] && file $_lib | fgrep -q 'shared object' 236 LD_BIND_NOW=1 LD_LIBRARY_PATH=$_tmpdir awk 'BEGIN {exit 0}' 237 LD_BIND_NOW=1 LD_LIBRARY_PATH=$_tmpdir openssl \ 238 x509 -in /etc/ssl/cert.pem -out /dev/null 239 $_install $_lib $_lib_dir/$_lib 240 fi 241 ) || { _error=true; break; } 242 done 243 244 for _bin in $_relink/usr/sbin/sshd $_relink/usr/bin/ssh-agent ; do 245 _tmpdir=$(mktemp -dq $_relink/_rebuild.XXXXXXXXXXXX) && 246 ( 247 set -o errexit 248 cd $_tmpdir 249 _binn=${_bin##*/} 250 _bint=${_bin}/${_binn}.tar 251 if [[ -f $_bint ]]; then 252 echo " $_binn" 253 tar xf $_bint 254 if [[ -f install.sh ]]; then 255 sh install.sh >/dev/null 2>&1 256 else 257 make -f Makefile.relink relink >/dev/null 2>&1 258 fi 259 fi 260 ) || { _error=true; break; } 261 done 262 263 rm -rf $_relink/_rebuild.* 264 265 # Restore previous mount state if it was changed. 266 for _mp in $_ro_list; do 267 mount -u -r $_mp || _error=true 268 done 269 270 if $_error; then 271 echo '(failed).' 272 else 273 echo '.' 274 fi 275} 276 277# Read output of reorder_libs co-process and output on console. 278wait_reorder_libs() { 279 local _line 280 281 [[ $library_aslr == NO ]] && return 282 283 while IFS= read -p _line; do 284 echo -n "$_line" 285 done 286 echo 287} 288 289# Run rc.* script and email output to root. 290# Usage: run_upgrade_script firsttime|sysmerge 291run_upgrade_script() { 292 local _suffix=$1 293 294 [[ -n $_suffix ]] || return 1 295 296 if [[ -f /etc/rc.$_suffix ]]; then 297 echo "running rc.$_suffix" 298 mv /etc/rc.$_suffix /etc/rc.$_suffix.run 299 . /etc/rc.$_suffix.run 2>&1 | tee /dev/tty | 300 mail -Es "$(hostname) rc.$_suffix output" root >/dev/null 301 fi 302 rm -f /etc/rc.$_suffix.run 303} 304 305# Check filesystems, optionally by using a fsck(8) flag. 306# Usage: do_fsck [-flag] 307do_fsck() { 308 fsck -p "$@" 309 case $? in 310 0) ;; 311 2) exit 1 312 ;; 313 4) echo "Rebooting..." 314 reboot 315 echo "Reboot failed; help!" 316 exit 1 317 ;; 318 8) echo "Automatic file system check failed; help!" 319 exit 1 320 ;; 321 12) echo "Boot interrupted." 322 exit 1 323 ;; 324 130) # Interrupt before catcher installed. 325 exit 1 326 ;; 327 *) echo "Unknown error; help!" 328 exit 1 329 ;; 330 esac 331} 332 333# End subroutines. 334 335stty status '^T' 336 337# Set shell to ignore SIGINT (2), but not children; shell catches SIGQUIT (3) 338# and returns to single user after fsck. 339trap : 2 340trap : 3 # Shouldn't be needed. 341 342export HOME=/ 343export INRC=1 344export PATH=/sbin:/bin:/usr/sbin:/usr/bin 345 346# /etc/myname contains my symbolic name. 347if [[ -f /etc/myname ]]; then 348 hostname "$(stripcom /etc/myname)" 349fi 350 351# Must set the domainname before rc.conf, so YP startup choices can be made. 352if [[ -s /etc/defaultdomain && -z "$(sysctl -n kern.domainname)" ]]; then 353 domainname "$(stripcom /etc/defaultdomain)" 354fi 355 356# Get local functions from rc.subr to load rc.conf into scope. 357FUNCS_ONLY=1 . /etc/rc.d/rc.subr 358_rc_parse_conf 359 360# If executed with the 'shutdown' parameter by the halt, reboot or shutdown: 361# - update seed files 362# - execute the rc.d scripts specified by $pkg_scripts in reverse order 363# - bring carp interfaces down gracefully 364if [[ $1 == shutdown ]]; then 365 if echo 2>/dev/null >>/var/db/host.random || 366 echo 2>/dev/null >>/etc/random.seed; then 367 random_seed 368 else 369 echo warning: cannot write random seed to disk 370 fi 371 372 # If we are in secure level 0, assume single user mode. 373 if (($(sysctl -n kern.securelevel) == 0)); then 374 echo 'single user: not running shutdown scripts' 375 else 376 set -A _d -- $pkg_scripts 377 _i=${#_d[*]} 378 if ((_i)); then 379 echo -n 'stopping package daemons:' 380 while ((--_i >= 0)); do 381 [[ -x /etc/rc.d/${_d[_i]} ]] && 382 /etc/rc.d/${_d[_i]} stop 383 done 384 echo '.' 385 fi 386 387 if /etc/rc.d/vmd check > /dev/null; then 388 echo -n 'stopping VMs' 389 /etc/rc.d/vmd stop > /dev/null 390 echo '.' 391 fi 392 393 [[ -f /etc/rc.shutdown ]] && sh /etc/rc.shutdown 394 fi 395 396 ifconfig | while read _if _junk; do 397 [[ $_if == carp+([0-9]): ]] && ifconfig ${_if%:} down 398 done 399 400 exit 0 401fi 402 403# If bootblocks failed to give us random, try to cause some churn 404(dmesg; sysctl hw.{uuid,serialno,sensors} ) >/dev/random 2>&1 405 406# Add swap block-devices. 407swapctl -A -t blk 408 409# Run filesystem check unless a /fastboot file exists. 410if [[ -e /fastboot ]]; then 411 echo "Fast boot: skipping disk checks." 412elif [[ $1 == autoboot ]]; then 413 echo "Automatic boot in progress: starting file system checks." 414 do_fsck 415fi 416 417# From now on, allow user to interrupt (^C) the boot process. 418trap "echo 'Boot interrupted.'; exit 1" 3 419 420# Unmount all filesystems except root. 421umount -a >/dev/null 2>&1 422 423# Mount all filesystems except those of type NFS and VND. 424mount -a -t nonfs,vnd 425 426# Re-mount the root filesystem read/writeable. (root on nfs requires this, 427# others aren't hurt.) 428mount -uw / 429chmod og-rwx /bsd 430ln -fh /bsd /bsd.booted 431 432rm -f /fastboot 433 434# Set flags on ttys. 435ttyflags -a 436 437# Set keyboard encoding. 438if [[ -x /sbin/kbd && -s /etc/kbdtype ]]; then 439 kbd "$(</etc/kbdtype)" 440fi 441 442wsconsctl_conf 443 444# Set initial temporary pf rule set. 445if [[ $pf != NO ]]; then 446 RULES=" 447 block all 448 pass on lo0 449 pass in proto tcp from any to any port ssh keep state 450 pass out proto { tcp, udp } from any to any port domain keep state 451 pass out inet proto icmp all icmp-type echoreq keep state 452 pass out inet proto udp from any port bootpc to any port bootps 453 pass in inet proto udp from any port bootps to any port bootpc" 454 455 if ifconfig lo0 inet6 >/dev/null 2>&1; then 456 RULES="$RULES 457 pass out inet6 proto icmp6 all icmp6-type neighbrsol 458 pass inet6 proto icmp6 all icmp6-type neighbradv no state 459 pass out inet6 proto icmp6 all icmp6-type routersol 460 pass in inet6 proto icmp6 all icmp6-type routeradv 461 pass out inet6 proto udp from any port dhcpv6-client to any port dhcpv6-server 462 pass in inet6 proto udp from any port dhcpv6-server to any port dhcpv6-client" 463 fi 464 465 RULES="$RULES 466 pass in proto carp keep state (no-sync) 467 pass out proto carp !received-on any keep state (no-sync)" 468 469 if (($(sysctl -n vfs.mounts.nfs 2>/dev/null)+0 > 0)); then 470 # Don't kill NFS. 471 RULES="set reassemble yes no-df 472 $RULES 473 pass in proto { tcp, udp } from any port { sunrpc, nfsd } to any 474 pass out proto { tcp, udp } from any to any port { sunrpc, nfsd } !received-on any" 475 fi 476 477 print -- "$RULES" | pfctl -f - 478 pfctl -e 479fi 480 481fill_baddynamic udp 482fill_baddynamic tcp 483 484sysctl_conf 485 486mount -s /var >/dev/null 2>&1 # cannot be on NFS 487mount -s /var/log >/dev/null 2>&1 # cannot be on NFS 488mount -s /usr >/dev/null 2>&1 # if NFS, fstab must use IP address 489 490reorder_libs 2>&1 |& 491 492start_daemon slaacd dhcpleased resolvd >/dev/null 2>&1 493 494echo 'starting network' 495 496# Set carp interlock by increasing the demotion counter. 497# Prevents carp from preempting until the system is booted. 498ifconfig -g carp carpdemote 128 499 500sh /etc/netstart 501 502start_daemon unwind >/dev/null 2>&1 503 504random_seed 505 506wait_reorder_libs 507 508# Load pf rules and bring up pfsync interface. 509if [[ $pf != NO ]]; then 510 if [[ -f /etc/pf.conf ]]; then 511 pfctl -f /etc/pf.conf 512 fi 513 if [[ -f /etc/hostname.pfsync0 ]]; then 514 sh /etc/netstart pfsync0 515 fi 516fi 517 518# Clean up left-over files. 519rm -f /etc/nologin /var/spool/lock/LCK.* 520(cd /var/run && { rm -rf -- *; install -c -m 664 -g utmp /dev/null utmp; }) 521(cd /var/authpf && rm -rf -- *) 522 523# Save a copy of the boot messages. 524dmesg >/var/run/dmesg.boot 525 526make_keys 527 528echo -n 'starting early daemons:' 529start_daemon syslogd ldattach pflogd nsd unbound ntpd 530start_daemon iscsid isakmpd iked sasyncd ldapd npppd 531echo '.' 532 533# Load IPsec rules. 534if [[ $ipsec != NO && -f /etc/ipsec.conf ]]; then 535 ipsecctl -f /etc/ipsec.conf 536fi 537 538echo -n 'starting RPC daemons:' 539start_daemon portmap 540if [[ -n $(domainname) ]]; then 541 start_daemon ypldap ypserv ypbind 542fi 543start_daemon mountd nfsd lockd statd amd 544echo '.' 545 546# Check and mount remaining file systems and enable additional swap. 547mount -a 548swapctl -A -t noblk 549do_fsck -N 550mount -a -N 551 552# Build kvm(3) and /dev databases. 553kvm_mkdb 554dev_mkdb 555 556# /var/crash should be a directory or a symbolic link to the crash directory 557# if core dumps are to be saved. 558if [[ -d /var/crash ]]; then 559 savecore $savecore_flags /var/crash 560fi 561 562# Store ACPI tables in /var/db/acpi to be used by sendbug(1). 563if [[ -x /usr/sbin/acpidump ]]; then 564 acpidump -q -o /var/db/acpi/ 565fi 566 567if [[ $check_quotas == YES ]]; then 568 echo -n 'checking quotas:' 569 quotacheck -a 570 echo ' done.' 571 quotaon -a 572fi 573 574# Set proper permission for the tty device files. 575chmod 666 /dev/tty[pqrstuvwxyzPQRST]* 576chown root:wheel /dev/tty[pqrstuvwxyzPQRST]* 577 578# Check for the password temp/lock file. 579if [[ -f /etc/ptmp ]]; then 580 logger -s -p auth.err \ 581 'password file may be incorrect -- /etc/ptmp exists' 582fi 583 584echo clearing /tmp 585 586# Prune quickly with one rm, then use find to clean up /tmp/[lqv]* 587# (not needed with mfs /tmp, but doesn't hurt there...). 588(cd /tmp && rm -rf [a-km-pr-uw-zA-Z]*) 589(cd /tmp && 590 find . -maxdepth 1 ! -name . ! -name lost+found ! -name quota.user \ 591 ! -name quota.group ! -name vi.recover -execdir rm -rf -- {} \;) 592 593# Create Unix sockets directories for X if needed and make sure they have 594# correct permissions. 595[[ -d /usr/X11R6/lib ]] && mkdir -m 1777 /tmp/.{X11,ICE}-unix 596 597[[ -f /etc/rc.securelevel ]] && sh /etc/rc.securelevel 598 599# rc.securelevel did not specifically set -1 or 2, so select the default: 1. 600(($(sysctl -n kern.securelevel) == 0)) && sysctl kern.securelevel=1 601 602 603# Patch /etc/motd. 604if [[ ! -f /etc/motd ]]; then 605 install -c -o root -g wheel -m 664 /dev/null /etc/motd 606fi 607if T=$(mktemp /tmp/_motd.XXXXXXXXXX); then 608 sysctl -n kern.version | sed 1q >$T 609 sed -n '/^$/,$p' </etc/motd >>$T 610 cmp -s $T /etc/motd || cp $T /etc/motd 611 rm -f $T 612fi 613 614if [[ $accounting == YES ]]; then 615 [[ ! -f /var/account/acct ]] && touch /var/account/acct 616 echo 'turning on accounting' 617 accton /var/account/acct 618fi 619 620if [[ -x /sbin/ldconfig ]]; then 621 echo 'creating runtime link editor directory cache.' 622 [[ -d /usr/local/lib ]] && shlib_dirs="/usr/local/lib $shlib_dirs" 623 [[ -d /usr/X11R6/lib ]] && shlib_dirs="/usr/X11R6/lib $shlib_dirs" 624 ldconfig $shlib_dirs 625fi 626 627echo 'preserving editor files.'; /usr/libexec/vi.recover 628 629# If rc.sysmerge exists, run it just once, and make sure it is deleted. 630run_upgrade_script sysmerge 631 632echo -n 'starting network daemons:' 633start_daemon ldomd sshd snmpd ldpd ripd ospfd ospf6d bgpd ifstated 634start_daemon relayd dhcpd dhcrelay mrouted dvmrpd radiusd eigrpd route6d 635start_daemon rad hostapd lpd smtpd slowcgi bgplgd httpd ftpd 636start_daemon ftpproxy ftpproxy6 tftpd tftpproxy identd inetd rarpd bootparamd 637start_daemon rbootd mopd vmd spamd spamlogd sndiod 638echo '.' 639 640# If rc.firsttime exists, run it just once, and make sure it is deleted. 641run_upgrade_script firsttime 642 643# Run rc.d(8) scripts from packages. 644if [[ -n $pkg_scripts ]]; then 645 echo -n 'starting package daemons:' 646 for _daemon in $pkg_scripts; do 647 if [[ -x /etc/rc.d/$_daemon ]]; then 648 start_daemon $_daemon 649 else 650 echo -n " ${_daemon}(absent)" 651 fi 652 done 653 echo '.' 654fi 655 656[[ -f /etc/rc.local ]] && sh /etc/rc.local 657 658# Disable carp interlock. 659ifconfig -g carp -carpdemote 128 660 661mixerctl_conf 662 663echo -n 'starting local daemons:' 664start_daemon apmd sensorsd hotplugd watchdogd cron wsmoused xenodm 665echo '.' 666 667# Re-link the kernel, placing the objects in a random order. 668# Replace current with relinked kernel and inform root about it. 669/usr/libexec/reorder_kernel & 670 671date 672exit 0 673