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