2 # ASR live update script by David van Moolenbroek <david@minix3.org>
4 # The path to the initial, standard system service binaries.
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.
9 SERVICE_ASR_PATH
=$SERVICE_PATH/asr
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.
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.
25 STATES
="vfs:2 ahci_:2 virtio_blk_:2"
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".
32 # Configuration ends here.
35 if [ $verbose -eq 1 ]; then
43 while getopts 'v' opt
; do
47 ?
) echo "Usage: $0 [-v] [label [label..]]" >&2
51 shift $
(($OPTIND - 1))
54 services
=$
(echo /proc
/service
/*)
58 services
="$services /proc/service/$label"
62 for service
in $services; do
63 label
=$
(basename $service)
64 filename
=$
(grep filename
: $service | cut
-d' ' -f2)
65 count
=$
(grep ASRcount
: $service | cut
-d' ' -f2)
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"
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"
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.
85 while [ -f $SERVICE_ASR_PATH/$filename-$total ]; do
89 if [ $total -eq 1 ]; then
90 debug
"skipping $label: no ASR binaries found"
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
100 binary
=$SERVICE_ASR_PATH/$filename-$count
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.
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)"
116 # Apply a custom timeout if present. This may be necessary in VMs.
118 if [ -n "$TIMEOUT" ]; then
119 maxtime
="-maxtime $TIMEOUT"
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
128 if [ $error -eq 0 ]; then
129 debug
"updated $label to number $count, total $total"
131 echo "failed updating $label: error $error" >&2