1a2818ee4SJoe Lawrence#!/bin/bash
2a2818ee4SJoe Lawrence# SPDX-License-Identifier: GPL-2.0
3a2818ee4SJoe Lawrence# Copyright (C) 2018 Joe Lawrence <[email protected]>
4a2818ee4SJoe Lawrence
5a2818ee4SJoe Lawrence# Shell functions for the rest of the scripts.
6a2818ee4SJoe Lawrence
7a2818ee4SJoe LawrenceMAX_RETRIES=600
8a2818ee4SJoe LawrenceRETRY_INTERVAL=".1"	# seconds
959766286SMichael VetterSYSFS_KERNEL_DIR="/sys/kernel"
1059766286SMichael VetterSYSFS_KLP_DIR="$SYSFS_KERNEL_DIR/livepatch"
1159766286SMichael VetterSYSFS_DEBUG_DIR="$SYSFS_KERNEL_DIR/debug"
1259766286SMichael VetterSYSFS_KPROBES_DIR="$SYSFS_DEBUG_DIR/kprobes"
13*2ca7cd80SFilipe XavierSYSFS_TRACING_DIR="$SYSFS_DEBUG_DIR/tracing"
14a2818ee4SJoe Lawrence
1505564c29SShuah Khan# Kselftest framework requirement - SKIP code is 4
1605564c29SShuah Khanksft_skip=4
1705564c29SShuah Khan
18a2818ee4SJoe Lawrence# log(msg) - write message to kernel log
19a2818ee4SJoe Lawrence#	msg - insightful words
20a2818ee4SJoe Lawrencefunction log() {
21a2818ee4SJoe Lawrence	echo "$1" > /dev/kmsg
22a2818ee4SJoe Lawrence}
23a2818ee4SJoe Lawrence
24527d37e9SJoe Lawrence# skip(msg) - testing can't proceed
25527d37e9SJoe Lawrence#	msg - explanation
26527d37e9SJoe Lawrencefunction skip() {
27527d37e9SJoe Lawrence	log "SKIP: $1"
28527d37e9SJoe Lawrence	echo "SKIP: $1" >&2
2905564c29SShuah Khan	exit $ksft_skip
3005564c29SShuah Khan}
3105564c29SShuah Khan
3205564c29SShuah Khan# root test
3305564c29SShuah Khanfunction is_root() {
3405564c29SShuah Khan	uid=$(id -u)
3505564c29SShuah Khan	if [ $uid -ne 0 ]; then
3605564c29SShuah Khan		echo "skip all tests: must be run as root" >&2
3705564c29SShuah Khan		exit $ksft_skip
3805564c29SShuah Khan	fi
39527d37e9SJoe Lawrence}
40527d37e9SJoe Lawrence
4154ee3526SMarcos Paulo de Souza# Check if we can compile the modules before loading them
4254ee3526SMarcos Paulo de Souzafunction has_kdir() {
4354ee3526SMarcos Paulo de Souza	if [ -z "$KDIR" ]; then
4454ee3526SMarcos Paulo de Souza		KDIR="/lib/modules/$(uname -r)/build"
4554ee3526SMarcos Paulo de Souza	fi
4654ee3526SMarcos Paulo de Souza
4754ee3526SMarcos Paulo de Souza	if [ ! -d "$KDIR" ]; then
4854ee3526SMarcos Paulo de Souza		echo "skip all tests: KDIR ($KDIR) not available to compile modules."
4954ee3526SMarcos Paulo de Souza		exit $ksft_skip
5054ee3526SMarcos Paulo de Souza	fi
5154ee3526SMarcos Paulo de Souza}
5254ee3526SMarcos Paulo de Souza
53a2818ee4SJoe Lawrence# die(msg) - game over, man
54a2818ee4SJoe Lawrence#	msg - dying words
55a2818ee4SJoe Lawrencefunction die() {
56a2818ee4SJoe Lawrence	log "ERROR: $1"
57a2818ee4SJoe Lawrence	echo "ERROR: $1" >&2
58a2818ee4SJoe Lawrence	exit 1
59a2818ee4SJoe Lawrence}
60a2818ee4SJoe Lawrence
6135c9e74cSJoe Lawrencefunction push_config() {
6259766286SMichael Vetter	DYNAMIC_DEBUG=$(grep '^kernel/livepatch' "$SYSFS_DEBUG_DIR/dynamic_debug/control" | \
63fbb01c52SJoe Lawrence			awk -F'[: ]' '{print "file " $1 " line " $2 " " $4}')
648c666d2aSJoe Lawrence	FTRACE_ENABLED=$(sysctl --values kernel.ftrace_enabled)
6559766286SMichael Vetter	KPROBE_ENABLED=$(cat "$SYSFS_KPROBES_DIR/enabled")
66*2ca7cd80SFilipe Xavier	TRACING_ON=$(cat "$SYSFS_TRACING_DIR/tracing_on")
67*2ca7cd80SFilipe Xavier	CURRENT_TRACER=$(cat "$SYSFS_TRACING_DIR/current_tracer")
68*2ca7cd80SFilipe Xavier	FTRACE_FILTER=$(cat "$SYSFS_TRACING_DIR/set_ftrace_filter")
69fbb01c52SJoe Lawrence}
70fbb01c52SJoe Lawrence
7135c9e74cSJoe Lawrencefunction pop_config() {
72fbb01c52SJoe Lawrence	if [[ -n "$DYNAMIC_DEBUG" ]]; then
7359766286SMichael Vetter		echo -n "$DYNAMIC_DEBUG" > "$SYSFS_DEBUG_DIR/dynamic_debug/control"
74fbb01c52SJoe Lawrence	fi
758c666d2aSJoe Lawrence	if [[ -n "$FTRACE_ENABLED" ]]; then
768c666d2aSJoe Lawrence		sysctl kernel.ftrace_enabled="$FTRACE_ENABLED" &> /dev/null
778c666d2aSJoe Lawrence	fi
7859766286SMichael Vetter	if [[ -n "$KPROBE_ENABLED" ]]; then
7959766286SMichael Vetter		echo "$KPROBE_ENABLED" > "$SYSFS_KPROBES_DIR/enabled"
8059766286SMichael Vetter	fi
81*2ca7cd80SFilipe Xavier	if [[ -n "$TRACING_ON" ]]; then
82*2ca7cd80SFilipe Xavier		echo "$TRACING_ON" > "$SYSFS_TRACING_DIR/tracing_on"
83*2ca7cd80SFilipe Xavier	fi
84*2ca7cd80SFilipe Xavier	if [[ -n "$CURRENT_TRACER" ]]; then
85*2ca7cd80SFilipe Xavier		echo "$CURRENT_TRACER" > "$SYSFS_TRACING_DIR/current_tracer"
86*2ca7cd80SFilipe Xavier	fi
87*2ca7cd80SFilipe Xavier	if [[ -n "$FTRACE_FILTER" ]]; then
88*2ca7cd80SFilipe Xavier		echo "$FTRACE_FILTER" \
89*2ca7cd80SFilipe Xavier			| sed -e "/#### all functions enabled ####/d" \
90*2ca7cd80SFilipe Xavier			> "$SYSFS_TRACING_DIR/set_ftrace_filter"
91*2ca7cd80SFilipe Xavier	fi
92fbb01c52SJoe Lawrence}
93fbb01c52SJoe Lawrence
94a2818ee4SJoe Lawrencefunction set_dynamic_debug() {
9559766286SMichael Vetter        cat <<-EOF > "$SYSFS_DEBUG_DIR/dynamic_debug/control"
96a2818ee4SJoe Lawrence		file kernel/livepatch/* +p
97a2818ee4SJoe Lawrence		func klp_try_switch_task -p
98a2818ee4SJoe Lawrence		EOF
99a2818ee4SJoe Lawrence}
100a2818ee4SJoe Lawrence
1018c666d2aSJoe Lawrencefunction set_ftrace_enabled() {
1024327b9eaSDavid Vernet	local can_fail=0
1034327b9eaSDavid Vernet	if [[ "$1" == "--fail" ]] ; then
1044327b9eaSDavid Vernet		can_fail=1
1054327b9eaSDavid Vernet		shift
1064327b9eaSDavid Vernet	fi
1074327b9eaSDavid Vernet
1084327b9eaSDavid Vernet	local err=$(sysctl -q kernel.ftrace_enabled="$1" 2>&1)
1094327b9eaSDavid Vernet	local result=$(sysctl --values kernel.ftrace_enabled)
1104327b9eaSDavid Vernet
1114327b9eaSDavid Vernet	if [[ "$result" != "$1" ]] ; then
1124327b9eaSDavid Vernet		if [[ $can_fail -eq 1 ]] ; then
113857300b7SJoe Lawrence			echo "livepatch: $err" | sed 's#/proc/sys/kernel/#kernel.#' > /dev/kmsg
1144327b9eaSDavid Vernet			return
1154327b9eaSDavid Vernet		fi
1164327b9eaSDavid Vernet
1174327b9eaSDavid Vernet		skip "failed to set kernel.ftrace_enabled = $1"
1184327b9eaSDavid Vernet	fi
1194327b9eaSDavid Vernet
1204327b9eaSDavid Vernet	echo "livepatch: kernel.ftrace_enabled = $result" > /dev/kmsg
1218c666d2aSJoe Lawrence}
1228c666d2aSJoe Lawrence
1232eeb0d45SJoe Lawrencefunction cleanup() {
1242eeb0d45SJoe Lawrence	pop_config
1252eeb0d45SJoe Lawrence}
1262eeb0d45SJoe Lawrence
12735c9e74cSJoe Lawrence# setup_config - save the current config and set a script exit trap that
12835c9e74cSJoe Lawrence#		 restores the original config.  Setup the dynamic debug
1298c666d2aSJoe Lawrence#		 for verbose livepatching output and turn on
1308c666d2aSJoe Lawrence#		 the ftrace_enabled sysctl.
13135c9e74cSJoe Lawrencefunction setup_config() {
13205564c29SShuah Khan	is_root
13354ee3526SMarcos Paulo de Souza	has_kdir
13435c9e74cSJoe Lawrence	push_config
13535c9e74cSJoe Lawrence	set_dynamic_debug
1368c666d2aSJoe Lawrence	set_ftrace_enabled 1
1372eeb0d45SJoe Lawrence	trap cleanup EXIT INT TERM HUP
13835c9e74cSJoe Lawrence}
13935c9e74cSJoe Lawrence
140a2818ee4SJoe Lawrence# loop_until(cmd) - loop a command until it is successful or $MAX_RETRIES,
141a2818ee4SJoe Lawrence#		    sleep $RETRY_INTERVAL between attempts
142a2818ee4SJoe Lawrence#	cmd - command and its arguments to run
143a2818ee4SJoe Lawrencefunction loop_until() {
144a2818ee4SJoe Lawrence	local cmd="$*"
145a2818ee4SJoe Lawrence	local i=0
146a2818ee4SJoe Lawrence	while true; do
147a2818ee4SJoe Lawrence		eval "$cmd" && return 0
148a2818ee4SJoe Lawrence		[[ $((i++)) -eq $MAX_RETRIES ]] && return 1
149a2818ee4SJoe Lawrence		sleep $RETRY_INTERVAL
150a2818ee4SJoe Lawrence	done
151a2818ee4SJoe Lawrence}
152a2818ee4SJoe Lawrence
153a2818ee4SJoe Lawrencefunction is_livepatch_mod() {
154a2818ee4SJoe Lawrence	local mod="$1"
155a2818ee4SJoe Lawrence
156c4bbe83dSMarcos Paulo de Souza	if [[ ! -f "test_modules/$mod.ko" ]]; then
157c4bbe83dSMarcos Paulo de Souza		die "Can't find \"test_modules/$mod.ko\", try \"make\""
158c4bbe83dSMarcos Paulo de Souza	fi
159c4bbe83dSMarcos Paulo de Souza
160c4bbe83dSMarcos Paulo de Souza	if [[ $(modinfo "test_modules/$mod.ko" | awk '/^livepatch:/{print $NF}') == "Y" ]]; then
161a2818ee4SJoe Lawrence		return 0
162a2818ee4SJoe Lawrence	fi
163a2818ee4SJoe Lawrence
164a2818ee4SJoe Lawrence	return 1
165a2818ee4SJoe Lawrence}
166a2818ee4SJoe Lawrence
167a2818ee4SJoe Lawrencefunction __load_mod() {
168a2818ee4SJoe Lawrence	local mod="$1"; shift
169a2818ee4SJoe Lawrence
170c4bbe83dSMarcos Paulo de Souza	local msg="% insmod test_modules/$mod.ko $*"
171a2818ee4SJoe Lawrence	log "${msg%% }"
172c4bbe83dSMarcos Paulo de Souza	ret=$(insmod "test_modules/$mod.ko" "$@" 2>&1)
173a2818ee4SJoe Lawrence	if [[ "$ret" != "" ]]; then
174a2818ee4SJoe Lawrence		die "$ret"
175a2818ee4SJoe Lawrence	fi
176a2818ee4SJoe Lawrence
177a2818ee4SJoe Lawrence	# Wait for module in sysfs ...
178a2818ee4SJoe Lawrence	loop_until '[[ -e "/sys/module/$mod" ]]' ||
179a2818ee4SJoe Lawrence		die "failed to load module $mod"
180a2818ee4SJoe Lawrence}
181a2818ee4SJoe Lawrence
182a2818ee4SJoe Lawrence
183a2818ee4SJoe Lawrence# load_mod(modname, params) - load a kernel module
184a2818ee4SJoe Lawrence#	modname - module name to load
185c4bbe83dSMarcos Paulo de Souza#	params  - module parameters to pass to insmod
186a2818ee4SJoe Lawrencefunction load_mod() {
187a2818ee4SJoe Lawrence	local mod="$1"; shift
188a2818ee4SJoe Lawrence
189a2818ee4SJoe Lawrence	is_livepatch_mod "$mod" &&
190a2818ee4SJoe Lawrence		die "use load_lp() to load the livepatch module $mod"
191a2818ee4SJoe Lawrence
192fbb76d57SJoe Lawrence	__load_mod "$mod" "$@"
193a2818ee4SJoe Lawrence}
194a2818ee4SJoe Lawrence
195a2818ee4SJoe Lawrence# load_lp_nowait(modname, params) - load a kernel module with a livepatch
196a2818ee4SJoe Lawrence#			but do not wait on until the transition finishes
197a2818ee4SJoe Lawrence#	modname - module name to load
198c4bbe83dSMarcos Paulo de Souza#	params  - module parameters to pass to insmod
199a2818ee4SJoe Lawrencefunction load_lp_nowait() {
200a2818ee4SJoe Lawrence	local mod="$1"; shift
201a2818ee4SJoe Lawrence
202a2818ee4SJoe Lawrence	is_livepatch_mod "$mod" ||
203a2818ee4SJoe Lawrence		die "module $mod is not a livepatch"
204a2818ee4SJoe Lawrence
205fbb76d57SJoe Lawrence	__load_mod "$mod" "$@"
206a2818ee4SJoe Lawrence
207a2818ee4SJoe Lawrence	# Wait for livepatch in sysfs ...
208637c7309SMichael Vetter	loop_until '[[ -e "$SYSFS_KLP_DIR/$mod" ]]' ||
209a2818ee4SJoe Lawrence		die "failed to load module $mod (sysfs)"
210a2818ee4SJoe Lawrence}
211a2818ee4SJoe Lawrence
212a2818ee4SJoe Lawrence# load_lp(modname, params) - load a kernel module with a livepatch
213a2818ee4SJoe Lawrence#	modname - module name to load
214c4bbe83dSMarcos Paulo de Souza#	params  - module parameters to pass to insmod
215a2818ee4SJoe Lawrencefunction load_lp() {
216a2818ee4SJoe Lawrence	local mod="$1"; shift
217a2818ee4SJoe Lawrence
218fbb76d57SJoe Lawrence	load_lp_nowait "$mod" "$@"
219a2818ee4SJoe Lawrence
220a2818ee4SJoe Lawrence	# Wait until the transition finishes ...
221637c7309SMichael Vetter	loop_until 'grep -q '^0$' $SYSFS_KLP_DIR/$mod/transition' ||
222a2818ee4SJoe Lawrence		die "failed to complete transition"
223a2818ee4SJoe Lawrence}
224a2818ee4SJoe Lawrence
225a2818ee4SJoe Lawrence# load_failing_mod(modname, params) - load a kernel module, expect to fail
226a2818ee4SJoe Lawrence#	modname - module name to load
227c4bbe83dSMarcos Paulo de Souza#	params  - module parameters to pass to insmod
228a2818ee4SJoe Lawrencefunction load_failing_mod() {
229a2818ee4SJoe Lawrence	local mod="$1"; shift
230a2818ee4SJoe Lawrence
231c4bbe83dSMarcos Paulo de Souza	local msg="% insmod test_modules/$mod.ko $*"
232a2818ee4SJoe Lawrence	log "${msg%% }"
233c4bbe83dSMarcos Paulo de Souza	ret=$(insmod "test_modules/$mod.ko" "$@" 2>&1)
234a2818ee4SJoe Lawrence	if [[ "$ret" == "" ]]; then
235a2818ee4SJoe Lawrence		die "$mod unexpectedly loaded"
236a2818ee4SJoe Lawrence	fi
237a2818ee4SJoe Lawrence	log "$ret"
238a2818ee4SJoe Lawrence}
239a2818ee4SJoe Lawrence
240a2818ee4SJoe Lawrence# unload_mod(modname) - unload a kernel module
241a2818ee4SJoe Lawrence#	modname - module name to unload
242a2818ee4SJoe Lawrencefunction unload_mod() {
243a2818ee4SJoe Lawrence	local mod="$1"
244a2818ee4SJoe Lawrence
245a2818ee4SJoe Lawrence	# Wait for module reference count to clear ...
246a2818ee4SJoe Lawrence	loop_until '[[ $(cat "/sys/module/$mod/refcnt") == "0" ]]' ||
247a2818ee4SJoe Lawrence		die "failed to unload module $mod (refcnt)"
248a2818ee4SJoe Lawrence
249a2818ee4SJoe Lawrence	log "% rmmod $mod"
250a2818ee4SJoe Lawrence	ret=$(rmmod "$mod" 2>&1)
251a2818ee4SJoe Lawrence	if [[ "$ret" != "" ]]; then
252a2818ee4SJoe Lawrence		die "$ret"
253a2818ee4SJoe Lawrence	fi
254a2818ee4SJoe Lawrence
255a2818ee4SJoe Lawrence	# Wait for module in sysfs ...
256a2818ee4SJoe Lawrence	loop_until '[[ ! -e "/sys/module/$mod" ]]' ||
257a2818ee4SJoe Lawrence		die "failed to unload module $mod (/sys/module)"
258a2818ee4SJoe Lawrence}
259a2818ee4SJoe Lawrence
260a2818ee4SJoe Lawrence# unload_lp(modname) - unload a kernel module with a livepatch
261a2818ee4SJoe Lawrence#	modname - module name to unload
262a2818ee4SJoe Lawrencefunction unload_lp() {
263a2818ee4SJoe Lawrence	unload_mod "$1"
264a2818ee4SJoe Lawrence}
265a2818ee4SJoe Lawrence
266a2818ee4SJoe Lawrence# disable_lp(modname) - disable a livepatch
267a2818ee4SJoe Lawrence#	modname - module name to unload
268a2818ee4SJoe Lawrencefunction disable_lp() {
269a2818ee4SJoe Lawrence	local mod="$1"
270a2818ee4SJoe Lawrence
271637c7309SMichael Vetter	log "% echo 0 > $SYSFS_KLP_DIR/$mod/enabled"
272637c7309SMichael Vetter	echo 0 > "$SYSFS_KLP_DIR/$mod/enabled"
273a2818ee4SJoe Lawrence
274a2818ee4SJoe Lawrence	# Wait until the transition finishes and the livepatch gets
275a2818ee4SJoe Lawrence	# removed from sysfs...
276637c7309SMichael Vetter	loop_until '[[ ! -e "$SYSFS_KLP_DIR/$mod" ]]' ||
277a2818ee4SJoe Lawrence		die "failed to disable livepatch $mod"
278a2818ee4SJoe Lawrence}
279a2818ee4SJoe Lawrence
280a2818ee4SJoe Lawrence# set_pre_patch_ret(modname, pre_patch_ret)
281a2818ee4SJoe Lawrence#	modname - module name to set
282a2818ee4SJoe Lawrence#	pre_patch_ret - new pre_patch_ret value
283a2818ee4SJoe Lawrencefunction set_pre_patch_ret {
284a2818ee4SJoe Lawrence	local mod="$1"; shift
285a2818ee4SJoe Lawrence	local ret="$1"
286a2818ee4SJoe Lawrence
287a2818ee4SJoe Lawrence	log "% echo $ret > /sys/module/$mod/parameters/pre_patch_ret"
288a2818ee4SJoe Lawrence	echo "$ret" > /sys/module/"$mod"/parameters/pre_patch_ret
289a2818ee4SJoe Lawrence
290a2818ee4SJoe Lawrence	# Wait for sysfs value to hold ...
291a2818ee4SJoe Lawrence	loop_until '[[ $(cat "/sys/module/$mod/parameters/pre_patch_ret") == "$ret" ]]' ||
292a2818ee4SJoe Lawrence		die "failed to set pre_patch_ret parameter for $mod module"
293a2818ee4SJoe Lawrence}
294a2818ee4SJoe Lawrence
2952eeb0d45SJoe Lawrencefunction start_test {
2962eeb0d45SJoe Lawrence	local test="$1"
2972eeb0d45SJoe Lawrence
298f1fea725SJoe Lawrence	# Dump something unique into the dmesg log, then stash the entry
299f1fea725SJoe Lawrence	# in LAST_DMESG.  The check_result() function will use it to
300f1fea725SJoe Lawrence	# find new kernel messages since the test started.
301f1fea725SJoe Lawrence	local last_dmesg_msg="livepatch kselftest timestamp: $(date --rfc-3339=ns)"
302f1fea725SJoe Lawrence	log "$last_dmesg_msg"
303f1fea725SJoe Lawrence	loop_until 'dmesg | grep -q "$last_dmesg_msg"' ||
304f1fea725SJoe Lawrence		die "buffer busy? can't find canary dmesg message: $last_dmesg_msg"
305f1fea725SJoe Lawrence	LAST_DMESG=$(dmesg | grep "$last_dmesg_msg")
306f1fea725SJoe Lawrence
3072eeb0d45SJoe Lawrence	echo -n "TEST: $test ... "
3083fd9bd8bSJoe Lawrence	log "===== TEST: $test ====="
3092eeb0d45SJoe Lawrence}
3102eeb0d45SJoe Lawrence
311a2818ee4SJoe Lawrence# check_result() - verify dmesg output
312a2818ee4SJoe Lawrence#	TODO - better filter, out of order msgs, etc?
313a2818ee4SJoe Lawrencefunction check_result {
314a2818ee4SJoe Lawrence	local expect="$*"
315a2818ee4SJoe Lawrence	local result
316a2818ee4SJoe Lawrence
317f1fea725SJoe Lawrence	# Test results include any new dmesg entry since LAST_DMESG, then:
318f1fea725SJoe Lawrence	# - include lines matching keywords
319f1fea725SJoe Lawrence	# - exclude lines matching keywords
320f1fea725SJoe Lawrence	# - filter out dmesg timestamp prefixes
321f1fea725SJoe Lawrence	result=$(dmesg | awk -v last_dmesg="$LAST_DMESG" 'p; $0 == last_dmesg { p=1 }' | \
322c401088fSJoe Lawrence		 grep -e 'livepatch:' -e 'test_klp' | \
323c401088fSJoe Lawrence		 grep -v '\(tainting\|taints\) kernel' | \
3242eeb0d45SJoe Lawrence		 sed 's/^\[[ 0-9.]*\] //' | \
325a2818ee4SJoe Lawrence		 sed 's/^\[[ ]*[CT][0-9]*\] //')
326a2818ee4SJoe Lawrence
327a2818ee4SJoe Lawrence	if [[ "$expect" == "$result" ]] ; then
328f1fea725SJoe Lawrence		echo "ok"
329f1fea725SJoe Lawrence	elif [[ "$result" == "" ]] ; then
330f1fea725SJoe Lawrence		echo -e "not ok\n\nbuffer overrun? can't find canary dmesg entry: $LAST_DMESG\n"
331a2818ee4SJoe Lawrence		die "livepatch kselftest(s) failed"
332a2818ee4SJoe Lawrence	else
333a2818ee4SJoe Lawrence		echo -e "not ok\n\n$(diff -upr --label expected --label result <(echo "$expect") <(echo "$result"))\n"
334a2818ee4SJoe Lawrence		die "livepatch kselftest(s) failed"
335a2818ee4SJoe Lawrence	fi
336ff1b80ecSSong Liu}
337ff1b80ecSSong Liu
338ff1b80ecSSong Liu# check_sysfs_rights(modname, rel_path, expected_rights) - check sysfs
339ff1b80ecSSong Liu# path permissions
340ff1b80ecSSong Liu#	modname - livepatch module creating the sysfs interface
341ff1b80ecSSong Liu#	rel_path - relative path of the sysfs interface
342ff1b80ecSSong Liu#	expected_rights - expected access rights
343ff1b80ecSSong Liufunction check_sysfs_rights() {
344ff1b80ecSSong Liu	local mod="$1"; shift
345ff1b80ecSSong Liu	local rel_path="$1"; shift
346ff1b80ecSSong Liu	local expected_rights="$1"; shift
347637c7309SMichael Vetter
348ff1b80ecSSong Liu	local path="$SYSFS_KLP_DIR/$mod/$rel_path"
349ff1b80ecSSong Liu	local rights=$(/bin/stat --format '%A' "$path")
350ff1b80ecSSong Liu	if test "$rights" != "$expected_rights" ; then
351ff1b80ecSSong Liu		die "Unexpected access rights of $path: $expected_rights vs. $rights"
352ff1b80ecSSong Liu	fi
353ff1b80ecSSong Liu}
354ff1b80ecSSong Liu
355ff1b80ecSSong Liu# check_sysfs_value(modname, rel_path, expected_value) - check sysfs value
356ff1b80ecSSong Liu#	modname - livepatch module creating the sysfs interface
357ff1b80ecSSong Liu#	rel_path - relative path of the sysfs interface
358ff1b80ecSSong Liu#	expected_value - expected value read from the file
359ff1b80ecSSong Liufunction check_sysfs_value() {
360ff1b80ecSSong Liu	local mod="$1"; shift
361ff1b80ecSSong Liu	local rel_path="$1"; shift
362ff1b80ecSSong Liu	local expected_value="$1"; shift
363637c7309SMichael Vetter
364ff1b80ecSSong Liu	local path="$SYSFS_KLP_DIR/$mod/$rel_path"
365ff1b80ecSSong Liu	local value=`cat $path`
366ff1b80ecSSong Liu	if test "$value" != "$expected_value" ; then
367ff1b80ecSSong Liu		die "Unexpected value in $path: $expected_value vs. $value"
368ff1b80ecSSong Liu	fi
369*2ca7cd80SFilipe Xavier}
370*2ca7cd80SFilipe Xavier
371*2ca7cd80SFilipe Xavier# cleanup_tracing() - stop and clean up function tracing
372*2ca7cd80SFilipe Xavierfunction cleanup_tracing() {
373*2ca7cd80SFilipe Xavier	echo 0 > "$SYSFS_TRACING_DIR/tracing_on"
374*2ca7cd80SFilipe Xavier	echo "" > "$SYSFS_TRACING_DIR/set_ftrace_filter"
375*2ca7cd80SFilipe Xavier	echo "nop" > "$SYSFS_TRACING_DIR/current_tracer"
376*2ca7cd80SFilipe Xavier	echo "" > "$SYSFS_TRACING_DIR/trace"
377*2ca7cd80SFilipe Xavier}
378*2ca7cd80SFilipe Xavier
379*2ca7cd80SFilipe Xavier# trace_function(function) - start tracing of a function
380*2ca7cd80SFilipe Xavier#	function - to be traced function
381*2ca7cd80SFilipe Xavierfunction trace_function() {
382*2ca7cd80SFilipe Xavier	local function="$1"; shift
383*2ca7cd80SFilipe Xavier
384*2ca7cd80SFilipe Xavier	cleanup_tracing
385*2ca7cd80SFilipe Xavier
386*2ca7cd80SFilipe Xavier	echo "function" > "$SYSFS_TRACING_DIR/current_tracer"
387*2ca7cd80SFilipe Xavier	echo "$function" > "$SYSFS_TRACING_DIR/set_ftrace_filter"
388*2ca7cd80SFilipe Xavier	echo 1 > "$SYSFS_TRACING_DIR/tracing_on"
389*2ca7cd80SFilipe Xavier}
390*2ca7cd80SFilipe Xavier
391*2ca7cd80SFilipe Xavier# check_traced_functions(functions...) - check whether each function appeared in the trace log
392*2ca7cd80SFilipe Xavier#	functions - list of functions to be checked
393*2ca7cd80SFilipe Xavierfunction check_traced_functions() {
394*2ca7cd80SFilipe Xavier	local function
395*2ca7cd80SFilipe Xavier
396*2ca7cd80SFilipe Xavier	for function in "$@"; do
397*2ca7cd80SFilipe Xavier		if ! grep -Fwq "$function" "$SYSFS_TRACING_DIR/trace" ; then
398*2ca7cd80SFilipe Xavier			die "Function ($function) did not appear in the trace"
399*2ca7cd80SFilipe Xavier		fi
400*2ca7cd80SFilipe Xavier	done
401*2ca7cd80SFilipe Xavier
402*2ca7cd80SFilipe Xavier	cleanup_tracing
403}
404