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