1#!/bin/ksh 2# 3# $OpenBSD: sysupgrade.sh,v 1.48 2022/06/08 09:03:11 mglocker Exp $ 4# 5# Copyright (c) 1997-2015 Todd Miller, Theo de Raadt, Ken Westerback 6# Copyright (c) 2015 Robert Peichaer <rpe@openbsd.org> 7# Copyright (c) 2016, 2017 Antoine Jacoutot <ajacoutot@openbsd.org> 8# Copyright (c) 2019 Christian Weisgerber <naddy@openbsd.org> 9# Copyright (c) 2019 Florian Obser <florian@openbsd.org> 10# 11# Permission to use, copy, modify, and distribute this software for any 12# purpose with or without fee is hereby granted, provided that the above 13# copyright notice and this permission notice appear in all copies. 14# 15# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 23set -e 24umask 0022 25export PATH=/usr/bin:/bin:/usr/sbin:/sbin 26 27ARCH=$(uname -m) 28SETSDIR=/home/_sysupgrade 29 30err() 31{ 32 echo "${0##*/}: ${1}" 1>&2 33 return ${2:-1} 34} 35 36usage() 37{ 38 echo "usage: ${0##*/} [-fkn] [-r | -s] [-b base-directory] [installurl]" 1>&2 39 return 1 40} 41 42unpriv() 43{ 44 local _file _rc=0 _user=_syspatch 45 46 if [[ $1 == -f ]]; then 47 _file=$2 48 shift 2 49 fi 50 if [[ -n ${_file} ]]; then 51 >${_file} 52 chown "${_user}" "${_file}" 53 fi 54 (($# >= 1)) 55 56 eval su -s /bin/sh ${_user} -c "'$@'" || _rc=$? 57 58 [[ -n ${_file} ]] && chown root "${_file}" 59 60 return ${_rc} 61} 62 63# Remove all occurrences of first argument from list formed by the remaining 64# arguments. 65rmel() { 66 local _a=$1 _b _c 67 68 shift 69 for _b; do 70 [[ $_a != "$_b" ]] && _c="${_c:+$_c }$_b" 71 done 72 echo -n "$_c" 73} 74 75RELEASE=false 76SNAP=false 77FORCE=false 78KEEP=false 79REBOOT=true 80 81while getopts b:fknrs arg; do 82 case ${arg} in 83 b) SETSDIR=${OPTARG}/_sysupgrade;; 84 f) FORCE=true;; 85 k) KEEP=true;; 86 n) REBOOT=false;; 87 r) RELEASE=true;; 88 s) SNAP=true;; 89 *) usage;; 90 esac 91done 92 93(($(id -u) != 0)) && err "need root privileges" 94 95if $RELEASE && $SNAP; then 96 usage 97fi 98 99set -A _KERNV -- $(sysctl -n kern.version | 100 sed 's/^OpenBSD \([1-9][0-9]*\.[0-9]\)\([^ ]*\).*/\1 \2/;q') 101 102shift $(( OPTIND -1 )) 103 104case $# in 1050) MIRROR=$(sed 's/#.*//;/^$/d' /etc/installurl) 2>/dev/null || 106 MIRROR=https://cdn.openbsd.org/pub/OpenBSD 107 ;; 1081) MIRROR=$1 109 ;; 110*) usage 111esac 112[[ $MIRROR == @(file|ftp|http|https)://* ]] || 113 err "invalid installurl: $MIRROR" 114 115if ! $RELEASE && [[ ${#_KERNV[*]} == 2 ]]; then 116 if [[ ${_KERNV[1]} != '-stable' ]]; then 117 SNAP=true 118 fi 119fi 120 121if $RELEASE && [[ ${_KERNV[1]} == '-beta' ]]; then 122 NEXT_VERSION=${_KERNV[0]} 123else 124 NEXT_VERSION=$(echo ${_KERNV[0]} + 0.1 | bc) 125fi 126 127if $SNAP; then 128 URL=${MIRROR}/snapshots/${ARCH}/ 129else 130 URL=${MIRROR}/${NEXT_VERSION}/${ARCH}/ 131fi 132 133install -d -o 0 -g 0 -m 0755 ${SETSDIR} 134cd ${SETSDIR} 135 136echo "Fetching from ${URL}" 137unpriv -f SHA256.sig ftp -N sysupgrade -Vmo SHA256.sig ${URL}SHA256.sig 138 139_KEY=openbsd-${_KERNV[0]%.*}${_KERNV[0]#*.}-base.pub 140_NEXTKEY=openbsd-${NEXT_VERSION%.*}${NEXT_VERSION#*.}-base.pub 141 142read _LINE <SHA256.sig 143case ${_LINE} in 144*\ ${_KEY}) SIGNIFY_KEY=/etc/signify/${_KEY} ;; 145*\ ${_NEXTKEY}) SIGNIFY_KEY=/etc/signify/${_NEXTKEY} ;; 146*) err "invalid signing key" ;; 147esac 148 149[[ -f ${SIGNIFY_KEY} ]] || err "cannot find ${SIGNIFY_KEY}" 150 151unpriv -f SHA256 signify -Ve -p "${SIGNIFY_KEY}" -x SHA256.sig -m SHA256 152rm SHA256.sig 153 154if cmp -s /var/db/installed.SHA256 SHA256 && ! $FORCE; then 155 echo "Already on latest snapshot." 156 exit 0 157fi 158 159# INSTALL.*, bsd*, *.tgz 160SETS=$(sed -n -e 's/^SHA256 (\(.*\)) .*/\1/' \ 161 -e '/^INSTALL\./p;/^bsd/p;/\.tgz$/p' SHA256) 162 163OLD_FILES=$(ls) 164OLD_FILES=$(rmel SHA256 $OLD_FILES) 165DL=$SETS 166 167[[ -n ${OLD_FILES} ]] && echo Verifying old sets. 168for f in ${OLD_FILES}; do 169 if cksum -C SHA256 $f >/dev/null 2>&1; then 170 DL=$(rmel $f ${DL}) 171 OLD_FILES=$(rmel $f ${OLD_FILES}) 172 fi 173done 174 175[[ -n ${OLD_FILES} ]] && rm ${OLD_FILES} 176for f in ${DL}; do 177 unpriv -f $f ftp -N sysupgrade -Vmo ${f} ${URL}${f} 178done 179 180if [[ -n ${DL} ]]; then 181 echo Verifying sets. 182 unpriv cksum -qC SHA256 ${DL} 183fi 184 185cat <<__EOT >/auto_upgrade.conf 186Location of sets = disk 187Pathname to the sets = ${SETSDIR}/ 188Set name(s) = done 189Directory does not contain SHA256.sig. Continue without verification = yes 190__EOT 191 192if ! ${KEEP}; then 193 CLEAN=$(echo SHA256 ${SETS} | sed -e 's/ /,/g') 194 cat <<__EOT > /etc/rc.firsttime 195rm -f ${SETSDIR}/{${CLEAN}} 196__EOT 197fi 198 199echo Fetching updated firmware. 200set -A _NEXTKERNV -- $(what bsd | 201 sed -n '2s/^[[:blank:]]OpenBSD \([1-9][0-9]*\.[0-9]\)\([^ ]*\).*/\1 \2/p') 202 203if [[ ${_NEXTKERNV[1]} == '-current' ]]; then 204 FW_URL=http://firmware.openbsd.org/firmware/snapshots/ 205else 206 FW_URL=http://firmware.openbsd.org/firmware/${_NEXTKERNV[0]}/ 207fi 208VNAME="${_NEXTKERNV[0]}" fw_update -p ${FW_URL} || true 209 210install -F -m 700 bsd.rd /bsd.upgrade 211logger -t sysupgrade -p kern.info "installed new /bsd.upgrade. Old kernel version: $(sysctl -n kern.version)" 212sync 213 214if ${REBOOT}; then 215 echo Upgrading. 216 exec reboot 217else 218 echo "Will upgrade on next reboot" 219fi 220