1#!/bin/sh 2# ASR live update script by David van Moolenbroek <david@minix3.org> 3 4# The path to the initial, standard system service binaries. 5SERVICE_PATH=/service 6 7# The path to the alternative, ASR-rerandomized system service binaries. 8# The path used here is typically a symlink into /usr for size reasons. 9SERVICE_ASR_PATH=$SERVICE_PATH/asr 10 11# A space-separated list of labels not to update in any case. The list 12# includes the memory service, which is currently not compiled with bitcode 13# and therefore also not instrumented. It also contains the VM service, 14# for which ASR is possible but too dangerous: much of its address space is 15# deliberately ignored by the instrumentation, and ASR would invalidate any 16# pointers from the ignored memory to the relocated memory. Note that 17# skipped services may still have rerandomized binaries on disk. 18SKIP="memory vm" 19 20# Custom live update states to use for certain label prefixes. This list is 21# made up of space-separated tokens, each token consisting of a label prefix, 22# followed by a colon, followed by the state number to use for those labels. 23# Currently it contains all services that make use of worker threads. This 24# setting should not need to exist; see the corresponding TODO item below. 25STATES="vfs:2 ahci_:2 virtio_blk_:2" 26 27# If this variable is set, it is used as timeout for the live updates. The 28# service(8) argument takes a number of click ticks, or a number of seconds 29# if the value ends with "HZ". 30TIMEOUT=300HZ 31 32# Configuration ends here. 33 34debug() { 35 if [ $verbose -eq 1 ]; then 36 echo "$@" 37 fi 38} 39 40verbose=0 41ret=0 42 43while getopts 'v' opt; do 44 case $opt in 45 v) verbose=1 46 ;; 47 ?) echo "Usage: $0 [-v] [label [label..]]" >&2 48 exit 1 49 esac 50done 51shift $(($OPTIND - 1)) 52 53if [ $# -eq 0 ]; then 54 services=$(echo /proc/service/*) 55else 56 services= 57 for label in $@; do 58 services="$services /proc/service/$label" 59 done 60fi 61 62for service in $services; do 63 label=$(basename $service) 64 filename=$(grep filename: $service | cut -d' ' -f2) 65 count=$(grep ASRcount: $service | cut -d' ' -f2) 66 67 # Start by making sure we are not supposed to skip this service. 68 if echo " $SKIP " | grep -q " $label "; then 69 debug "skipping $label: found in skip list" 70 continue 71 fi 72 73 # The base binary of the program has number 0 and must be present. 74 if [ ! -f $SERVICE_PATH/$filename ]; then 75 debug "skipping $label: no base binary found" 76 continue 77 fi 78 79 # Count the ASR binaries for this program, starting from number 1. 80 # There must be at least one, so that we can switch between versions. 81 # By counting using a number rather than using a directory iterator, 82 # we avoid potential problems with gaps between the numbers by 83 # stopping at the first number for which no binary is present. 84 total=1 85 while [ -f $SERVICE_ASR_PATH/$filename-$total ]; do 86 total=$(($total + 1)) 87 done 88 89 if [ $total -eq 1 ]; then 90 debug "skipping $label: no ASR binaries found" 91 continue 92 fi 93 94 # Determine the path name of the binary to use for this update. 95 # TODO: pick the next binary at random rather than round-robin. 96 count=$((($count + 1) % $total)) 97 if [ $count -eq 0 ]; then 98 binary=$SERVICE_PATH/$filename 99 else 100 binary=$SERVICE_ASR_PATH/$filename-$count 101 fi 102 103 # Check whether the live update should use a state other than the 104 # default (namely state 1, which is "work free"). In particular, any 105 # programs that use threads typically need another state (namely state 106 # 2, which is "request free". TODO: allow services to specify their 107 # own default state, thus avoiding the redundancy introduced here. 108 state= 109 for token in $STATES; do 110 prefix=$(echo $token | cut -d: -f1) 111 if echo "$label" | grep -q -e "^$prefix"; then 112 state="-state $(echo $token | cut -d: -f2)" 113 fi 114 done 115 116 # Apply a custom timeout if present. This may be necessary in VMs. 117 maxtime= 118 if [ -n "$TIMEOUT" ]; then 119 maxtime="-maxtime $TIMEOUT" 120 fi 121 122 # Perform the live update. The update may legitimately fail if the 123 # service is not in the right state. TODO: report transient errors 124 # as debugging output only. 125 service -a update $binary -progname $filename -label $label \ 126 -asr-count $count $state $maxtime 127 error=$? 128 if [ $error -eq 0 ]; then 129 debug "updated $label to number $count, total $total" 130 else 131 echo "failed updating $label: error $error" >&2 132 ret=1 133 fi 134done 135 136exit $ret 137