Commit 1e21b5c7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'livepatching-for-5.9' of...

Merge tag 'livepatching-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching

Pull livepatching updates from Petr Mladek:
 "Improvements and cleanups of livepatching selftests"

* tag 'livepatching-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching:
  selftests/livepatch: adopt to newer sysctl error format
  selftests/livepatch: Use "comm" instead of "diff" for dmesg
  selftests/livepatch: add test delimiter to dmesg
  selftests/livepatch: refine dmesg 'taints' in dmesg comparison
  selftests/livepatch: Don't clear dmesg when running tests
  selftests/livepatch: fix mem leaks in test-klp-shadow-vars
  selftests/livepatch: more verification in test-klp-shadow-vars
  selftests/livepatch: rework test-klp-shadow-vars
  selftests/livepatch: simplify test-klp-callbacks busy target tests
parents bfdd5aaa 5e4d4688
...@@ -5,34 +5,53 @@ ...@@ -5,34 +5,53 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/delay.h> #include <linux/delay.h>
static int sleep_secs; /* load/run-time control from sysfs writer */
module_param(sleep_secs, int, 0644); static bool block_transition;
MODULE_PARM_DESC(sleep_secs, "sleep_secs (default=0)"); module_param(block_transition, bool, 0644);
MODULE_PARM_DESC(block_transition, "block_transition (default=false)");
static void busymod_work_func(struct work_struct *work); static void busymod_work_func(struct work_struct *work);
static DECLARE_DELAYED_WORK(work, busymod_work_func); static DECLARE_WORK(work, busymod_work_func);
static void busymod_work_func(struct work_struct *work) static void busymod_work_func(struct work_struct *work)
{ {
pr_info("%s, sleeping %d seconds ...\n", __func__, sleep_secs); pr_info("%s enter\n", __func__);
msleep(sleep_secs * 1000);
while (READ_ONCE(block_transition)) {
/*
* Busy-wait until the sysfs writer has acknowledged a
* blocked transition and clears the flag.
*/
msleep(20);
}
pr_info("%s exit\n", __func__); pr_info("%s exit\n", __func__);
} }
static int test_klp_callbacks_busy_init(void) static int test_klp_callbacks_busy_init(void)
{ {
pr_info("%s\n", __func__); pr_info("%s\n", __func__);
schedule_delayed_work(&work, schedule_work(&work);
msecs_to_jiffies(1000 * 0));
if (!block_transition) {
/*
* Serialize output: print all messages from the work
* function before returning from init().
*/
flush_work(&work);
}
return 0; return 0;
} }
static void test_klp_callbacks_busy_exit(void) static void test_klp_callbacks_busy_exit(void)
{ {
cancel_delayed_work_sync(&work); WRITE_ONCE(block_transition, false);
flush_work(&work);
pr_info("%s\n", __func__); pr_info("%s\n", __func__);
} }
......
...@@ -109,8 +109,7 @@ static void shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor) ...@@ -109,8 +109,7 @@ static void shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor)
static void shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor) static void shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor)
{ {
klp_shadow_free_all(id, dtor); klp_shadow_free_all(id, dtor);
pr_info("klp_%s(id=0x%lx, dtor=PTR%d)\n", pr_info("klp_%s(id=0x%lx, dtor=PTR%d)\n", __func__, id, ptr_id(dtor));
__func__, id, ptr_id(dtor));
} }
...@@ -124,12 +123,16 @@ static int shadow_ctor(void *obj, void *shadow_data, void *ctor_data) ...@@ -124,12 +123,16 @@ static int shadow_ctor(void *obj, void *shadow_data, void *ctor_data)
return -EINVAL; return -EINVAL;
*sv = *var; *sv = *var;
pr_info("%s: PTR%d -> PTR%d\n", pr_info("%s: PTR%d -> PTR%d\n", __func__, ptr_id(sv), ptr_id(*var));
__func__, ptr_id(sv), ptr_id(*var));
return 0; return 0;
} }
/*
* With more than one item to free in the list, order is not determined and
* shadow_dtor will not be passed to shadow_free_all() which would make the
* test fail. (see pass 6)
*/
static void shadow_dtor(void *obj, void *shadow_data) static void shadow_dtor(void *obj, void *shadow_data)
{ {
int **sv = shadow_data; int **sv = shadow_data;
...@@ -138,132 +141,153 @@ static void shadow_dtor(void *obj, void *shadow_data) ...@@ -138,132 +141,153 @@ static void shadow_dtor(void *obj, void *shadow_data)
__func__, ptr_id(obj), ptr_id(sv)); __func__, ptr_id(obj), ptr_id(sv));
} }
static int test_klp_shadow_vars_init(void) /* number of objects we simulate that need shadow vars */
{ #define NUM_OBJS 3
void *obj = THIS_MODULE;
int id = 0x1234;
gfp_t gfp_flags = GFP_KERNEL;
int var1, var2, var3, var4; /* dynamically created obj fields have the following shadow var id values */
int *pv1, *pv2, *pv3, *pv4; #define SV_ID1 0x1234
int **sv1, **sv2, **sv3, **sv4; #define SV_ID2 0x1235
int **sv; /*
* The main test case adds/removes new fields (shadow var) to each of these
* test structure instances. The last group of fields in the struct represent
* the idea that shadow variables may be added and removed to and from the
* struct during execution.
*/
struct test_object {
/* add anything here below and avoid to define an empty struct */
struct shadow_ptr sp;
/* these represent shadow vars added and removed with SV_ID{1,2} */
/* char nfield1; */
/* int nfield2; */
};
pv1 = &var1; static int test_klp_shadow_vars_init(void)
pv2 = &var2; {
pv3 = &var3; struct test_object objs[NUM_OBJS];
pv4 = &var4; char nfields1[NUM_OBJS], *pnfields1[NUM_OBJS], **sv1[NUM_OBJS];
char *pndup[NUM_OBJS];
int nfields2[NUM_OBJS], *pnfields2[NUM_OBJS], **sv2[NUM_OBJS];
void **sv;
int ret;
int i;
ptr_id(NULL); ptr_id(NULL);
ptr_id(pv1);
ptr_id(pv2);
ptr_id(pv3);
ptr_id(pv4);
/* /*
* With an empty shadow variable hash table, expect not to find * With an empty shadow variable hash table, expect not to find
* any matches. * any matches.
*/ */
sv = shadow_get(obj, id); sv = shadow_get(&objs[0], SV_ID1);
if (!sv) if (!sv)
pr_info(" got expected NULL result\n"); pr_info(" got expected NULL result\n");
/* /* pass 1: init & alloc a char+int pair of svars for each objs */
* Allocate a few shadow variables with different <obj> and <id>. for (i = 0; i < NUM_OBJS; i++) {
*/ pnfields1[i] = &nfields1[i];
sv1 = shadow_alloc(obj, id, sizeof(pv1), gfp_flags, shadow_ctor, &pv1); ptr_id(pnfields1[i]);
if (!sv1)
return -ENOMEM; if (i % 2) {
sv1[i] = shadow_alloc(&objs[i], SV_ID1,
sv2 = shadow_alloc(obj + 1, id, sizeof(pv2), gfp_flags, shadow_ctor, &pv2); sizeof(pnfields1[i]), GFP_KERNEL,
if (!sv2) shadow_ctor, &pnfields1[i]);
return -ENOMEM; } else {
sv1[i] = shadow_get_or_alloc(&objs[i], SV_ID1,
sizeof(pnfields1[i]), GFP_KERNEL,
shadow_ctor, &pnfields1[i]);
}
if (!sv1[i]) {
ret = -ENOMEM;
goto out;
}
sv3 = shadow_alloc(obj, id + 1, sizeof(pv3), gfp_flags, shadow_ctor, &pv3); pnfields2[i] = &nfields2[i];
if (!sv3) ptr_id(pnfields2[i]);
return -ENOMEM; sv2[i] = shadow_alloc(&objs[i], SV_ID2, sizeof(pnfields2[i]),
GFP_KERNEL, shadow_ctor, &pnfields2[i]);
if (!sv2[i]) {
ret = -ENOMEM;
goto out;
}
}
/* /* pass 2: verify we find allocated svars and where they point to */
* Verify we can find our new shadow variables and that they point for (i = 0; i < NUM_OBJS; i++) {
* to expected data. /* check the "char" svar for all objects */
*/ sv = shadow_get(&objs[i], SV_ID1);
sv = shadow_get(obj, id); if (!sv) {
if (!sv) ret = -EINVAL;
return -EINVAL; goto out;
if (sv == sv1 && *sv1 == pv1) }
if ((char **)sv == sv1[i] && *sv1[i] == pnfields1[i])
pr_info(" got expected PTR%d -> PTR%d result\n", pr_info(" got expected PTR%d -> PTR%d result\n",
ptr_id(sv1), ptr_id(*sv1)); ptr_id(sv1[i]), ptr_id(*sv1[i]));
sv = shadow_get(obj + 1, id); /* check the "int" svar for all objects */
if (!sv) sv = shadow_get(&objs[i], SV_ID2);
return -EINVAL; if (!sv) {
if (sv == sv2 && *sv2 == pv2) ret = -EINVAL;
pr_info(" got expected PTR%d -> PTR%d result\n", goto out;
ptr_id(sv2), ptr_id(*sv2)); }
sv = shadow_get(obj, id + 1); if ((int **)sv == sv2[i] && *sv2[i] == pnfields2[i])
if (!sv)
return -EINVAL;
if (sv == sv3 && *sv3 == pv3)
pr_info(" got expected PTR%d -> PTR%d result\n", pr_info(" got expected PTR%d -> PTR%d result\n",
ptr_id(sv3), ptr_id(*sv3)); ptr_id(sv2[i]), ptr_id(*sv2[i]));
}
/* /* pass 3: verify that 'get_or_alloc' returns already allocated svars */
* Allocate or get a few more, this time with the same <obj>, <id>. for (i = 0; i < NUM_OBJS; i++) {
* The second invocation should return the same shadow var. pndup[i] = &nfields1[i];
*/ ptr_id(pndup[i]);
sv4 = shadow_get_or_alloc(obj + 2, id, sizeof(pv4), gfp_flags, shadow_ctor, &pv4);
if (!sv4)
return -ENOMEM;
sv = shadow_get_or_alloc(obj + 2, id, sizeof(pv4), gfp_flags, shadow_ctor, &pv4); sv = shadow_get_or_alloc(&objs[i], SV_ID1, sizeof(pndup[i]),
if (!sv) GFP_KERNEL, shadow_ctor, &pndup[i]);
return -EINVAL; if (!sv) {
if (sv == sv4 && *sv4 == pv4) ret = -EINVAL;
goto out;
}
if ((char **)sv == sv1[i] && *sv1[i] == pnfields1[i])
pr_info(" got expected PTR%d -> PTR%d result\n", pr_info(" got expected PTR%d -> PTR%d result\n",
ptr_id(sv4), ptr_id(*sv4)); ptr_id(sv1[i]), ptr_id(*sv1[i]));
}
/*
* Free the <obj=*, id> shadow variables and check that we can no
* longer find them.
*/
shadow_free(obj, id, shadow_dtor); /* sv1 */
sv = shadow_get(obj, id);
if (!sv)
pr_info(" got expected NULL result\n");
shadow_free(obj + 1, id, shadow_dtor); /* sv2 */
sv = shadow_get(obj + 1, id);
if (!sv)
pr_info(" got expected NULL result\n");
shadow_free(obj + 2, id, shadow_dtor); /* sv4 */ /* pass 4: free <objs[*], SV_ID1> pairs of svars, verify removal */
sv = shadow_get(obj + 2, id); for (i = 0; i < NUM_OBJS; i++) {
shadow_free(&objs[i], SV_ID1, shadow_dtor); /* 'char' pairs */
sv = shadow_get(&objs[i], SV_ID1);
if (!sv) if (!sv)
pr_info(" got expected NULL result\n"); pr_info(" got expected NULL result\n");
}
/* /* pass 5: check we still find <objs[*], SV_ID2> svar pairs */
* We should still find an <id+1> variable. for (i = 0; i < NUM_OBJS; i++) {
*/ sv = shadow_get(&objs[i], SV_ID2); /* 'int' pairs */
sv = shadow_get(obj, id + 1); if (!sv) {
if (!sv) ret = -EINVAL;
return -EINVAL; goto out;
if (sv == sv3 && *sv3 == pv3) }
if ((int **)sv == sv2[i] && *sv2[i] == pnfields2[i])
pr_info(" got expected PTR%d -> PTR%d result\n", pr_info(" got expected PTR%d -> PTR%d result\n",
ptr_id(sv3), ptr_id(*sv3)); ptr_id(sv2[i]), ptr_id(*sv2[i]));
}
/* /* pass 6: free all the <objs[*], SV_ID2> svar pairs too. */
* Free all the <id+1> variables, too. shadow_free_all(SV_ID2, NULL); /* 'int' pairs */
*/ for (i = 0; i < NUM_OBJS; i++) {
shadow_free_all(id + 1, shadow_dtor); /* sv3 */ sv = shadow_get(&objs[i], SV_ID2);
sv = shadow_get(obj, id);
if (!sv) if (!sv)
pr_info(" shadow_get() got expected NULL result\n"); pr_info(" got expected NULL result\n");
}
free_ptr_list(); free_ptr_list();
return 0; return 0;
out:
shadow_free_all(SV_ID1, NULL); /* 'char' pairs */
shadow_free_all(SV_ID2, NULL); /* 'int' pairs */
free_ptr_list();
return ret;
} }
static void test_klp_shadow_vars_exit(void) static void test_klp_shadow_vars_exit(void)
......
...@@ -6,8 +6,8 @@ This is a small set of sanity tests for the kernel livepatching. ...@@ -6,8 +6,8 @@ This is a small set of sanity tests for the kernel livepatching.
The test suite loads and unloads several test kernel modules to verify The test suite loads and unloads several test kernel modules to verify
livepatch behavior. Debug information is logged to the kernel's message livepatch behavior. Debug information is logged to the kernel's message
buffer and parsed for expected messages. (Note: the tests will clear buffer and parsed for expected messages. (Note: the tests will compare
the message buffer between individual tests.) the message buffer for only the duration of each individual test.)
Config Config
...@@ -35,9 +35,9 @@ Adding tests ...@@ -35,9 +35,9 @@ Adding tests
------------ ------------
See the common functions.sh file for the existing collection of utility See the common functions.sh file for the existing collection of utility
functions, most importantly setup_config() and check_result(). The functions, most importantly setup_config(), start_test() and
latter function greps the kernel's ring buffer for "livepatch:" and check_result(). The latter function greps the kernel's ring buffer for
"test_klp" strings, so tests be sure to include one of those strings for "livepatch:" and "test_klp" strings, so tests be sure to include one of
result comparison. Other utility functions include general module those strings for result comparison. Other utility functions include
loading and livepatch loading helpers (waiting for patch transitions, general module loading and livepatch loading helpers (waiting for patch
sysfs entries, etc.) transitions, sysfs entries, etc.)
...@@ -41,6 +41,17 @@ function die() { ...@@ -41,6 +41,17 @@ function die() {
exit 1 exit 1
} }
# save existing dmesg so we can detect new content
function save_dmesg() {
SAVED_DMESG=$(mktemp --tmpdir -t klp-dmesg-XXXXXX)
dmesg > "$SAVED_DMESG"
}
# cleanup temporary dmesg file from save_dmesg()
function cleanup_dmesg_file() {
rm -f "$SAVED_DMESG"
}
function push_config() { function push_config() {
DYNAMIC_DEBUG=$(grep '^kernel/livepatch' /sys/kernel/debug/dynamic_debug/control | \ DYNAMIC_DEBUG=$(grep '^kernel/livepatch' /sys/kernel/debug/dynamic_debug/control | \
awk -F'[: ]' '{print "file " $1 " line " $2 " " $4}') awk -F'[: ]' '{print "file " $1 " line " $2 " " $4}')
...@@ -64,10 +75,16 @@ function set_dynamic_debug() { ...@@ -64,10 +75,16 @@ function set_dynamic_debug() {
} }
function set_ftrace_enabled() { function set_ftrace_enabled() {
result=$(sysctl kernel.ftrace_enabled="$1" 2>&1 | paste --serial --delimiters=' ') result=$(sysctl -q kernel.ftrace_enabled="$1" 2>&1 && \
sysctl kernel.ftrace_enabled 2>&1)
echo "livepatch: $result" > /dev/kmsg echo "livepatch: $result" > /dev/kmsg
} }
function cleanup() {
pop_config
cleanup_dmesg_file
}
# setup_config - save the current config and set a script exit trap that # setup_config - save the current config and set a script exit trap that
# restores the original config. Setup the dynamic debug # restores the original config. Setup the dynamic debug
# for verbose livepatching output and turn on # for verbose livepatching output and turn on
...@@ -77,7 +94,7 @@ function setup_config() { ...@@ -77,7 +94,7 @@ function setup_config() {
push_config push_config
set_dynamic_debug set_dynamic_debug
set_ftrace_enabled 1 set_ftrace_enabled 1
trap pop_config EXIT INT TERM HUP trap cleanup EXIT INT TERM HUP
} }
# loop_until(cmd) - loop a command until it is successful or $MAX_RETRIES, # loop_until(cmd) - loop a command until it is successful or $MAX_RETRIES,
...@@ -243,13 +260,28 @@ function set_pre_patch_ret { ...@@ -243,13 +260,28 @@ function set_pre_patch_ret {
die "failed to set pre_patch_ret parameter for $mod module" die "failed to set pre_patch_ret parameter for $mod module"
} }
function start_test {
local test="$1"
save_dmesg
echo -n "TEST: $test ... "
log "===== TEST: $test ====="
}
# check_result() - verify dmesg output # check_result() - verify dmesg output
# TODO - better filter, out of order msgs, etc? # TODO - better filter, out of order msgs, etc?
function check_result { function check_result {
local expect="$*" local expect="$*"
local result local result
result=$(dmesg | grep -v 'tainting' | grep -e 'livepatch:' -e 'test_klp' | sed 's/^\[[ 0-9.]*\] //') # Note: when comparing dmesg output, the kernel log timestamps
# help differentiate repeated testing runs. Remove them with a
# post-comparison sed filter.
result=$(dmesg | comm -13 "$SAVED_DMESG" - | \
grep -e 'livepatch:' -e 'test_klp' | \
grep -v '\(tainting\|taints\) kernel' | \
sed 's/^\[[ 0-9.]*\] //')
if [[ "$expect" == "$result" ]] ; then if [[ "$expect" == "$result" ]] ; then
echo "ok" echo "ok"
...@@ -257,4 +289,6 @@ function check_result { ...@@ -257,4 +289,6 @@ function check_result {
echo -e "not ok\n\n$(diff -upr --label expected --label result <(echo "$expect") <(echo "$result"))\n" echo -e "not ok\n\n$(diff -upr --label expected --label result <(echo "$expect") <(echo "$result"))\n"
die "livepatch kselftest(s) failed" die "livepatch kselftest(s) failed"
fi fi
cleanup_dmesg_file
} }
...@@ -12,8 +12,6 @@ MOD_TARGET_BUSY=test_klp_callbacks_busy ...@@ -12,8 +12,6 @@ MOD_TARGET_BUSY=test_klp_callbacks_busy
setup_config setup_config
# TEST: target module before livepatch
#
# Test a combination of loading a kernel module and a livepatch that # Test a combination of loading a kernel module and a livepatch that
# patches a function in the first module. Load the target module # patches a function in the first module. Load the target module
# before the livepatch module. Unload them in the same order. # before the livepatch module. Unload them in the same order.
...@@ -28,8 +26,7 @@ setup_config ...@@ -28,8 +26,7 @@ setup_config
# unpatching transition starts. klp_objects are reverted, post-patch # unpatching transition starts. klp_objects are reverted, post-patch
# callbacks execute and the transition completes. # callbacks execute and the transition completes.
echo -n "TEST: target module before livepatch ... " start_test "target module before livepatch"
dmesg -C
load_mod $MOD_TARGET load_mod $MOD_TARGET
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
...@@ -63,8 +60,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -63,8 +60,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
$MOD_TARGET: ${MOD_TARGET}_exit" $MOD_TARGET: ${MOD_TARGET}_exit"
# TEST: module_coming notifier
#
# This test is similar to the previous test, but (un)load the livepatch # This test is similar to the previous test, but (un)load the livepatch
# module before the target kernel module. This tests the livepatch # module before the target kernel module. This tests the livepatch
# core's module_coming handler. # core's module_coming handler.
...@@ -78,8 +73,7 @@ $MOD_TARGET: ${MOD_TARGET}_exit" ...@@ -78,8 +73,7 @@ $MOD_TARGET: ${MOD_TARGET}_exit"
# - On livepatch disable, all currently loaded klp_objects' (vmlinux and # - On livepatch disable, all currently loaded klp_objects' (vmlinux and
# $MOD_TARGET) pre/post-unpatch callbacks are executed. # $MOD_TARGET) pre/post-unpatch callbacks are executed.
echo -n "TEST: module_coming notifier ... " start_test "module_coming notifier"
dmesg -C
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
load_mod $MOD_TARGET load_mod $MOD_TARGET
...@@ -114,8 +108,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -114,8 +108,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
$MOD_TARGET: ${MOD_TARGET}_exit" $MOD_TARGET: ${MOD_TARGET}_exit"
# TEST: module_going notifier
#
# Test loading the livepatch after a targeted kernel module, then unload # Test loading the livepatch after a targeted kernel module, then unload
# the kernel module before disabling the livepatch. This tests the # the kernel module before disabling the livepatch. This tests the
# livepatch core's module_going handler. # livepatch core's module_going handler.
...@@ -129,8 +121,7 @@ $MOD_TARGET: ${MOD_TARGET}_exit" ...@@ -129,8 +121,7 @@ $MOD_TARGET: ${MOD_TARGET}_exit"
# - When the livepatch is disabled, pre and post-unpatch callbacks are # - When the livepatch is disabled, pre and post-unpatch callbacks are
# run for the remaining klp_object, vmlinux. # run for the remaining klp_object, vmlinux.
echo -n "TEST: module_going notifier ... " start_test "module_going notifier"
dmesg -C
load_mod $MOD_TARGET load_mod $MOD_TARGET
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
...@@ -165,8 +156,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -165,8 +156,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH" % rmmod $MOD_LIVEPATCH"
# TEST: module_coming and module_going notifiers
#
# This test is similar to the previous test, however the livepatch is # This test is similar to the previous test, however the livepatch is
# loaded first. This tests the livepatch core's module_coming and # loaded first. This tests the livepatch core's module_coming and
# module_going handlers. # module_going handlers.
...@@ -180,8 +169,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -180,8 +169,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
# from the $MOD_TARGET klp_object. As such, only pre and # from the $MOD_TARGET klp_object. As such, only pre and
# post-unpatch callbacks are executed when this occurs. # post-unpatch callbacks are executed when this occurs.
echo -n "TEST: module_coming and module_going notifiers ... " start_test "module_coming and module_going notifiers"
dmesg -C
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
load_mod $MOD_TARGET load_mod $MOD_TARGET
...@@ -217,8 +205,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -217,8 +205,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH" % rmmod $MOD_LIVEPATCH"
# TEST: target module not present
#
# A simple test of loading a livepatch without one of its patch target # A simple test of loading a livepatch without one of its patch target
# klp_objects ever loaded ($MOD_TARGET). # klp_objects ever loaded ($MOD_TARGET).
# #
...@@ -227,8 +213,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -227,8 +213,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
# - As expected, only pre/post-(un)patch handlers are executed for # - As expected, only pre/post-(un)patch handlers are executed for
# vmlinux. # vmlinux.
echo -n "TEST: target module not present ... " start_test "target module not present"
dmesg -C
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
disable_lp $MOD_LIVEPATCH disable_lp $MOD_LIVEPATCH
...@@ -252,8 +237,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -252,8 +237,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH" % rmmod $MOD_LIVEPATCH"
# TEST: pre-patch callback -ENODEV
#
# Test a scenario where a vmlinux pre-patch callback returns a non-zero # Test a scenario where a vmlinux pre-patch callback returns a non-zero
# status (ie, failure). # status (ie, failure).
# #
...@@ -265,8 +248,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -265,8 +248,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
# The result is that the insmod command refuses to load the livepatch # The result is that the insmod command refuses to load the livepatch
# module. # module.
echo -n "TEST: pre-patch callback -ENODEV ... " start_test "pre-patch callback -ENODEV"
dmesg -C
load_mod $MOD_TARGET load_mod $MOD_TARGET
load_failing_mod $MOD_LIVEPATCH pre_patch_ret=-19 load_failing_mod $MOD_LIVEPATCH pre_patch_ret=-19
...@@ -288,8 +270,6 @@ modprobe: ERROR: could not insert '$MOD_LIVEPATCH': No such device ...@@ -288,8 +270,6 @@ modprobe: ERROR: could not insert '$MOD_LIVEPATCH': No such device
$MOD_TARGET: ${MOD_TARGET}_exit" $MOD_TARGET: ${MOD_TARGET}_exit"
# TEST: module_coming + pre-patch callback -ENODEV
#
# Similar to the previous test, setup a livepatch such that its vmlinux # Similar to the previous test, setup a livepatch such that its vmlinux
# pre-patch callback returns success. However, when a targeted kernel # pre-patch callback returns success. However, when a targeted kernel
# module is later loaded, have the livepatch return a failing status # module is later loaded, have the livepatch return a failing status
...@@ -307,8 +287,7 @@ $MOD_TARGET: ${MOD_TARGET}_exit" ...@@ -307,8 +287,7 @@ $MOD_TARGET: ${MOD_TARGET}_exit"
# #
# - Pre/post-unpatch callbacks are run for the vmlinux klp_object. # - Pre/post-unpatch callbacks are run for the vmlinux klp_object.
echo -n "TEST: module_coming + pre-patch callback -ENODEV ... " start_test "module_coming + pre-patch callback -ENODEV"
dmesg -C
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
set_pre_patch_ret $MOD_LIVEPATCH -19 set_pre_patch_ret $MOD_LIVEPATCH -19
...@@ -341,8 +320,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -341,8 +320,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH" % rmmod $MOD_LIVEPATCH"
# TEST: multiple target modules
#
# Test loading multiple targeted kernel modules. This test-case is # Test loading multiple targeted kernel modules. This test-case is
# mainly for comparing with the next test-case. # mainly for comparing with the next test-case.
# #
...@@ -353,12 +330,9 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -353,12 +330,9 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
# module. Post-patch callbacks are executed and the transition # module. Post-patch callbacks are executed and the transition
# completes quickly. # completes quickly.
echo -n "TEST: multiple target modules ... " start_test "multiple target modules"
dmesg -C
load_mod $MOD_TARGET_BUSY sleep_secs=0 load_mod $MOD_TARGET_BUSY block_transition=N
# give $MOD_TARGET_BUSY::busymod_work_func() a chance to run
sleep 5
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
load_mod $MOD_TARGET load_mod $MOD_TARGET
unload_mod $MOD_TARGET unload_mod $MOD_TARGET
...@@ -366,9 +340,9 @@ disable_lp $MOD_LIVEPATCH ...@@ -366,9 +340,9 @@ disable_lp $MOD_LIVEPATCH
unload_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH
unload_mod $MOD_TARGET_BUSY unload_mod $MOD_TARGET_BUSY
check_result "% modprobe $MOD_TARGET_BUSY sleep_secs=0 check_result "% modprobe $MOD_TARGET_BUSY block_transition=N
$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init
$MOD_TARGET_BUSY: busymod_work_func, sleeping 0 seconds ... $MOD_TARGET_BUSY: busymod_work_func enter
$MOD_TARGET_BUSY: busymod_work_func exit $MOD_TARGET_BUSY: busymod_work_func exit
% modprobe $MOD_LIVEPATCH % modprobe $MOD_LIVEPATCH
livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: enabling patch '$MOD_LIVEPATCH'
...@@ -404,11 +378,8 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -404,11 +378,8 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit" $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
# TEST: busy target module
#
# A similar test as the previous one, but force the "busy" kernel module # A similar test as the previous one, but force the "busy" kernel module
# to do longer work. # to block the livepatch transition.
# #
# The livepatching core will refuse to patch a task that is currently # The livepatching core will refuse to patch a task that is currently
# executing a to-be-patched function -- the consistency model stalls the # executing a to-be-patched function -- the consistency model stalls the
...@@ -417,8 +388,7 @@ $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit" ...@@ -417,8 +388,7 @@ $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
# function for a long time. Meanwhile, load and unload other target # function for a long time. Meanwhile, load and unload other target
# kernel modules while the livepatch transition is in progress. # kernel modules while the livepatch transition is in progress.
# #
# - Load the "busy" kernel module, this time make it do 10 seconds worth # - Load the "busy" kernel module, this time make its work function loop
# of work.
# #
# - Meanwhile, the livepatch is loaded. Notice that the patch # - Meanwhile, the livepatch is loaded. Notice that the patch
# transition does not complete as the targeted "busy" module is # transition does not complete as the targeted "busy" module is
...@@ -435,23 +405,25 @@ $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit" ...@@ -435,23 +405,25 @@ $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
# klp_object's post-patch callbacks executed, the remaining # klp_object's post-patch callbacks executed, the remaining
# klp_object's pre-unpatch callbacks are skipped. # klp_object's pre-unpatch callbacks are skipped.
echo -n "TEST: busy target module ... " start_test "busy target module"
dmesg -C
load_mod $MOD_TARGET_BUSY sleep_secs=10 load_mod $MOD_TARGET_BUSY block_transition=Y
load_lp_nowait $MOD_LIVEPATCH load_lp_nowait $MOD_LIVEPATCH
# Don't wait for transition, load $MOD_TARGET while the transition
# is still stalled in $MOD_TARGET_BUSY::busymod_work_func() # Wait until the livepatch reports in-transition state, i.e. that it's
sleep 5 # stalled on $MOD_TARGET_BUSY::busymod_work_func()
loop_until 'grep -q '^1$' /sys/kernel/livepatch/$MOD_LIVEPATCH/transition' ||
die "failed to stall transition"
load_mod $MOD_TARGET load_mod $MOD_TARGET
unload_mod $MOD_TARGET unload_mod $MOD_TARGET
disable_lp $MOD_LIVEPATCH disable_lp $MOD_LIVEPATCH
unload_lp $MOD_LIVEPATCH unload_lp $MOD_LIVEPATCH
unload_mod $MOD_TARGET_BUSY unload_mod $MOD_TARGET_BUSY
check_result "% modprobe $MOD_TARGET_BUSY sleep_secs=10 check_result "% modprobe $MOD_TARGET_BUSY block_transition=Y
$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init
$MOD_TARGET_BUSY: busymod_work_func, sleeping 10 seconds ... $MOD_TARGET_BUSY: busymod_work_func enter
% modprobe $MOD_LIVEPATCH % modprobe $MOD_LIVEPATCH
livepatch: enabling patch '$MOD_LIVEPATCH' livepatch: enabling patch '$MOD_LIVEPATCH'
livepatch: '$MOD_LIVEPATCH': initializing patching transition livepatch: '$MOD_LIVEPATCH': initializing patching transition
...@@ -479,8 +451,6 @@ $MOD_TARGET_BUSY: busymod_work_func exit ...@@ -479,8 +451,6 @@ $MOD_TARGET_BUSY: busymod_work_func exit
$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit" $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
# TEST: multiple livepatches
#
# Test loading multiple livepatches. This test-case is mainly for comparing # Test loading multiple livepatches. This test-case is mainly for comparing
# with the next test-case. # with the next test-case.
# #
...@@ -488,8 +458,7 @@ $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit" ...@@ -488,8 +458,7 @@ $MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
# execute as each patch progresses through its (un)patching # execute as each patch progresses through its (un)patching
# transition. # transition.
echo -n "TEST: multiple livepatches ... " start_test "multiple livepatches"
dmesg -C
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
load_lp $MOD_LIVEPATCH2 load_lp $MOD_LIVEPATCH2
...@@ -532,8 +501,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -532,8 +501,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH" % rmmod $MOD_LIVEPATCH"
# TEST: atomic replace
#
# Load multiple livepatches, but the second as an 'atomic-replace' # Load multiple livepatches, but the second as an 'atomic-replace'
# patch. When the latter loads, the original livepatch should be # patch. When the latter loads, the original livepatch should be
# disabled and *none* of its pre/post-unpatch callbacks executed. On # disabled and *none* of its pre/post-unpatch callbacks executed. On
...@@ -548,8 +515,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -548,8 +515,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
# - Once the atomic replace module is loaded, only its pre and post # - Once the atomic replace module is loaded, only its pre and post
# unpatch callbacks are executed. # unpatch callbacks are executed.
echo -n "TEST: atomic replace ... " start_test "atomic replace"
dmesg -C
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
load_lp $MOD_LIVEPATCH2 replace=1 load_lp $MOD_LIVEPATCH2 replace=1
......
...@@ -9,13 +9,11 @@ MOD_LIVEPATCH=test_klp_livepatch ...@@ -9,13 +9,11 @@ MOD_LIVEPATCH=test_klp_livepatch
setup_config setup_config
# TEST: livepatch interaction with ftrace_enabled sysctl
# - turn ftrace_enabled OFF and verify livepatches can't load # - turn ftrace_enabled OFF and verify livepatches can't load
# - turn ftrace_enabled ON and verify livepatch can load # - turn ftrace_enabled ON and verify livepatch can load
# - verify that ftrace_enabled can't be turned OFF while a livepatch is loaded # - verify that ftrace_enabled can't be turned OFF while a livepatch is loaded
echo -n "TEST: livepatch interaction with ftrace_enabled sysctl ... " start_test "livepatch interaction with ftrace_enabled sysctl"
dmesg -C
set_ftrace_enabled 0 set_ftrace_enabled 0
load_failing_mod $MOD_LIVEPATCH load_failing_mod $MOD_LIVEPATCH
...@@ -53,7 +51,7 @@ livepatch: '$MOD_LIVEPATCH': initializing patching transition ...@@ -53,7 +51,7 @@ livepatch: '$MOD_LIVEPATCH': initializing patching transition
livepatch: '$MOD_LIVEPATCH': starting patching transition livepatch: '$MOD_LIVEPATCH': starting patching transition
livepatch: '$MOD_LIVEPATCH': completing patching transition livepatch: '$MOD_LIVEPATCH': completing patching transition
livepatch: '$MOD_LIVEPATCH': patching complete livepatch: '$MOD_LIVEPATCH': patching complete
livepatch: sysctl: setting key \"kernel.ftrace_enabled\": Device or resource busy kernel.ftrace_enabled = 0 livepatch: sysctl: setting key \"kernel.ftrace_enabled\": Device or resource busy
% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled % echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
livepatch: '$MOD_LIVEPATCH': initializing unpatching transition livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
livepatch: '$MOD_LIVEPATCH': starting unpatching transition livepatch: '$MOD_LIVEPATCH': starting unpatching transition
......
...@@ -10,13 +10,11 @@ MOD_REPLACE=test_klp_atomic_replace ...@@ -10,13 +10,11 @@ MOD_REPLACE=test_klp_atomic_replace
setup_config setup_config
# TEST: basic function patching
# - load a livepatch that modifies the output from /proc/cmdline and # - load a livepatch that modifies the output from /proc/cmdline and
# verify correct behavior # verify correct behavior
# - unload the livepatch and make sure the patch was removed # - unload the livepatch and make sure the patch was removed
echo -n "TEST: basic function patching ... " start_test "basic function patching"
dmesg -C
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
...@@ -47,15 +45,13 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -47,15 +45,13 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH" % rmmod $MOD_LIVEPATCH"
# TEST: multiple livepatches
# - load a livepatch that modifies the output from /proc/cmdline and # - load a livepatch that modifies the output from /proc/cmdline and
# verify correct behavior # verify correct behavior
# - load another livepatch and verify that both livepatches are active # - load another livepatch and verify that both livepatches are active
# - unload the second livepatch and verify that the first is still active # - unload the second livepatch and verify that the first is still active
# - unload the first livepatch and verify none are active # - unload the first livepatch and verify none are active
echo -n "TEST: multiple livepatches ... " start_test "multiple livepatches"
dmesg -C
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
...@@ -109,7 +105,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -109,7 +105,6 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH" % rmmod $MOD_LIVEPATCH"
# TEST: atomic replace livepatch
# - load a livepatch that modifies the output from /proc/cmdline and # - load a livepatch that modifies the output from /proc/cmdline and
# verify correct behavior # verify correct behavior
# - load an atomic replace livepatch and verify that only the second is active # - load an atomic replace livepatch and verify that only the second is active
...@@ -117,8 +112,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -117,8 +112,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
# is still active # is still active
# - remove the atomic replace livepatch and verify that none are active # - remove the atomic replace livepatch and verify that none are active
echo -n "TEST: atomic replace livepatch ... " start_test "atomic replace livepatch"
dmesg -C
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
......
...@@ -9,52 +9,71 @@ MOD_TEST=test_klp_shadow_vars ...@@ -9,52 +9,71 @@ MOD_TEST=test_klp_shadow_vars
setup_config setup_config
# TEST: basic shadow variable API
# - load a module that exercises the shadow variable API # - load a module that exercises the shadow variable API
echo -n "TEST: basic shadow variable API ... " start_test "basic shadow variable API"
dmesg -C
load_mod $MOD_TEST load_mod $MOD_TEST
unload_mod $MOD_TEST unload_mod $MOD_TEST
check_result "% modprobe $MOD_TEST check_result "% modprobe $MOD_TEST
$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1234) = PTR0 $MOD_TEST: klp_shadow_get(obj=PTR1, id=0x1234) = PTR0
$MOD_TEST: got expected NULL result $MOD_TEST: got expected NULL result
$MOD_TEST: shadow_ctor: PTR6 -> PTR1 $MOD_TEST: shadow_ctor: PTR3 -> PTR2
$MOD_TEST: klp_shadow_alloc(obj=PTR5, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR7, ctor_data=PTR1 = PTR6 $MOD_TEST: klp_shadow_get_or_alloc(obj=PTR1, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR4, ctor_data=PTR2 = PTR3
$MOD_TEST: shadow_ctor: PTR8 -> PTR2 $MOD_TEST: shadow_ctor: PTR6 -> PTR5
$MOD_TEST: klp_shadow_alloc(obj=PTR9, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR7, ctor_data=PTR2 = PTR8 $MOD_TEST: klp_shadow_alloc(obj=PTR1, id=0x1235, size=8, gfp_flags=GFP_KERNEL), ctor=PTR4, ctor_data=PTR5 = PTR6
$MOD_TEST: shadow_ctor: PTR10 -> PTR3 $MOD_TEST: shadow_ctor: PTR8 -> PTR7
$MOD_TEST: klp_shadow_alloc(obj=PTR5, id=0x1235, size=8, gfp_flags=GFP_KERNEL), ctor=PTR7, ctor_data=PTR3 = PTR10 $MOD_TEST: klp_shadow_alloc(obj=PTR9, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR4, ctor_data=PTR7 = PTR8
$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1234) = PTR6 $MOD_TEST: shadow_ctor: PTR11 -> PTR10
$MOD_TEST: got expected PTR6 -> PTR1 result $MOD_TEST: klp_shadow_alloc(obj=PTR9, id=0x1235, size=8, gfp_flags=GFP_KERNEL), ctor=PTR4, ctor_data=PTR10 = PTR11
$MOD_TEST: shadow_ctor: PTR13 -> PTR12
$MOD_TEST: klp_shadow_get_or_alloc(obj=PTR14, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR4, ctor_data=PTR12 = PTR13
$MOD_TEST: shadow_ctor: PTR16 -> PTR15
$MOD_TEST: klp_shadow_alloc(obj=PTR14, id=0x1235, size=8, gfp_flags=GFP_KERNEL), ctor=PTR4, ctor_data=PTR15 = PTR16
$MOD_TEST: klp_shadow_get(obj=PTR1, id=0x1234) = PTR3
$MOD_TEST: got expected PTR3 -> PTR2 result
$MOD_TEST: klp_shadow_get(obj=PTR1, id=0x1235) = PTR6
$MOD_TEST: got expected PTR6 -> PTR5 result
$MOD_TEST: klp_shadow_get(obj=PTR9, id=0x1234) = PTR8 $MOD_TEST: klp_shadow_get(obj=PTR9, id=0x1234) = PTR8
$MOD_TEST: got expected PTR8 -> PTR2 result $MOD_TEST: got expected PTR8 -> PTR7 result
$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1235) = PTR10 $MOD_TEST: klp_shadow_get(obj=PTR9, id=0x1235) = PTR11
$MOD_TEST: got expected PTR10 -> PTR3 result $MOD_TEST: got expected PTR11 -> PTR10 result
$MOD_TEST: shadow_ctor: PTR11 -> PTR4 $MOD_TEST: klp_shadow_get(obj=PTR14, id=0x1234) = PTR13
$MOD_TEST: klp_shadow_get_or_alloc(obj=PTR12, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR7, ctor_data=PTR4 = PTR11 $MOD_TEST: got expected PTR13 -> PTR12 result
$MOD_TEST: klp_shadow_get_or_alloc(obj=PTR12, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR7, ctor_data=PTR4 = PTR11 $MOD_TEST: klp_shadow_get(obj=PTR14, id=0x1235) = PTR16
$MOD_TEST: got expected PTR11 -> PTR4 result $MOD_TEST: got expected PTR16 -> PTR15 result
$MOD_TEST: shadow_dtor(obj=PTR5, shadow_data=PTR6) $MOD_TEST: klp_shadow_get_or_alloc(obj=PTR1, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR4, ctor_data=PTR2 = PTR3
$MOD_TEST: klp_shadow_free(obj=PTR5, id=0x1234, dtor=PTR13) $MOD_TEST: got expected PTR3 -> PTR2 result
$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1234) = PTR0 $MOD_TEST: klp_shadow_get_or_alloc(obj=PTR9, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR4, ctor_data=PTR7 = PTR8
$MOD_TEST: got expected PTR8 -> PTR7 result
$MOD_TEST: klp_shadow_get_or_alloc(obj=PTR14, id=0x1234, size=8, gfp_flags=GFP_KERNEL), ctor=PTR4, ctor_data=PTR12 = PTR13
$MOD_TEST: got expected PTR13 -> PTR12 result
$MOD_TEST: shadow_dtor(obj=PTR1, shadow_data=PTR3)
$MOD_TEST: klp_shadow_free(obj=PTR1, id=0x1234, dtor=PTR17)
$MOD_TEST: klp_shadow_get(obj=PTR1, id=0x1234) = PTR0
$MOD_TEST: got expected NULL result $MOD_TEST: got expected NULL result
$MOD_TEST: shadow_dtor(obj=PTR9, shadow_data=PTR8) $MOD_TEST: shadow_dtor(obj=PTR9, shadow_data=PTR8)
$MOD_TEST: klp_shadow_free(obj=PTR9, id=0x1234, dtor=PTR13) $MOD_TEST: klp_shadow_free(obj=PTR9, id=0x1234, dtor=PTR17)
$MOD_TEST: klp_shadow_get(obj=PTR9, id=0x1234) = PTR0 $MOD_TEST: klp_shadow_get(obj=PTR9, id=0x1234) = PTR0
$MOD_TEST: got expected NULL result $MOD_TEST: got expected NULL result
$MOD_TEST: shadow_dtor(obj=PTR12, shadow_data=PTR11) $MOD_TEST: shadow_dtor(obj=PTR14, shadow_data=PTR13)
$MOD_TEST: klp_shadow_free(obj=PTR12, id=0x1234, dtor=PTR13) $MOD_TEST: klp_shadow_free(obj=PTR14, id=0x1234, dtor=PTR17)
$MOD_TEST: klp_shadow_get(obj=PTR12, id=0x1234) = PTR0 $MOD_TEST: klp_shadow_get(obj=PTR14, id=0x1234) = PTR0
$MOD_TEST: got expected NULL result $MOD_TEST: got expected NULL result
$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1235) = PTR10 $MOD_TEST: klp_shadow_get(obj=PTR1, id=0x1235) = PTR6
$MOD_TEST: got expected PTR10 -> PTR3 result $MOD_TEST: got expected PTR6 -> PTR5 result
$MOD_TEST: shadow_dtor(obj=PTR5, shadow_data=PTR10) $MOD_TEST: klp_shadow_get(obj=PTR9, id=0x1235) = PTR11
$MOD_TEST: klp_shadow_free_all(id=0x1235, dtor=PTR13) $MOD_TEST: got expected PTR11 -> PTR10 result
$MOD_TEST: klp_shadow_get(obj=PTR5, id=0x1234) = PTR0 $MOD_TEST: klp_shadow_get(obj=PTR14, id=0x1235) = PTR16
$MOD_TEST: shadow_get() got expected NULL result $MOD_TEST: got expected PTR16 -> PTR15 result
% rmmod test_klp_shadow_vars" $MOD_TEST: klp_shadow_free_all(id=0x1235, dtor=PTR0)
$MOD_TEST: klp_shadow_get(obj=PTR1, id=0x1235) = PTR0
$MOD_TEST: got expected NULL result
$MOD_TEST: klp_shadow_get(obj=PTR9, id=0x1235) = PTR0
$MOD_TEST: got expected NULL result
$MOD_TEST: klp_shadow_get(obj=PTR14, id=0x1235) = PTR0
$MOD_TEST: got expected NULL result
% rmmod $MOD_TEST"
exit 0 exit 0
...@@ -10,10 +10,10 @@ MOD_LIVEPATCH3=test_klp_state3 ...@@ -10,10 +10,10 @@ MOD_LIVEPATCH3=test_klp_state3
setup_config setup_config
# TEST: Loading and removing a module that modifies the system state
echo -n "TEST: system state modification ... " # Load and remove a module that modifies the system state
dmesg -C
start_test "system state modification"
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
disable_lp $MOD_LIVEPATCH disable_lp $MOD_LIVEPATCH
...@@ -41,10 +41,9 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete ...@@ -41,10 +41,9 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH" % rmmod $MOD_LIVEPATCH"
# TEST: Take over system state change by a cumulative patch # Take over system state change by a cumulative patch
echo -n "TEST: taking over system state modification ... " start_test "taking over system state modification"
dmesg -C
load_lp $MOD_LIVEPATCH load_lp $MOD_LIVEPATCH
load_lp $MOD_LIVEPATCH2 load_lp $MOD_LIVEPATCH2
...@@ -85,10 +84,9 @@ livepatch: '$MOD_LIVEPATCH2': unpatching complete ...@@ -85,10 +84,9 @@ livepatch: '$MOD_LIVEPATCH2': unpatching complete
% rmmod $MOD_LIVEPATCH2" % rmmod $MOD_LIVEPATCH2"
# TEST: Take over system state change by a cumulative patch # Take over system state change by a cumulative patch
echo -n "TEST: compatible cumulative livepatches ... " start_test "compatible cumulative livepatches"
dmesg -C
load_lp $MOD_LIVEPATCH2 load_lp $MOD_LIVEPATCH2
load_lp $MOD_LIVEPATCH3 load_lp $MOD_LIVEPATCH3
...@@ -142,10 +140,9 @@ livepatch: '$MOD_LIVEPATCH2': unpatching complete ...@@ -142,10 +140,9 @@ livepatch: '$MOD_LIVEPATCH2': unpatching complete
% rmmod $MOD_LIVEPATCH3" % rmmod $MOD_LIVEPATCH3"
# TEST: Failure caused by incompatible cumulative livepatches # Failure caused by incompatible cumulative livepatches
echo -n "TEST: incompatible cumulative livepatches ... " start_test "incompatible cumulative livepatches"
dmesg -C
load_lp $MOD_LIVEPATCH2 load_lp $MOD_LIVEPATCH2
load_failing_mod $MOD_LIVEPATCH load_failing_mod $MOD_LIVEPATCH
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment