selftests/livepatch: better synchronize test_klp_callbacks_busy
authorJoe Lawrence <joe.lawrence@redhat.com>
Thu, 2 Jun 2022 20:32:33 +0000 (16:32 -0400)
committerPetr Mladek <pmladek@suse.com>
Wed, 15 Jun 2022 08:29:10 +0000 (10:29 +0200)
The test_klp_callbacks_busy module conditionally blocks a future
livepatch transition by busy waiting inside its workqueue function,
busymod_work_func().  After scheduling this work, a test livepatch is
loaded, introducing the transition under test.

Both events are marked in the kernel log for later verification, but
there is no synchronization to ensure that busymod_work_func() logs its
function entry message before subsequent selftest commands log their own
messages.  This can lead to a rare test failure due to unexpected
ordering like:

  --- expected
  +++ result
  @@ -1,7 +1,7 @@
   % modprobe test_klp_callbacks_busy block_transition=Y
   test_klp_callbacks_busy: test_klp_callbacks_busy_init
  -test_klp_callbacks_busy: busymod_work_func enter
   % modprobe test_klp_callbacks_demo
  +test_klp_callbacks_busy: busymod_work_func enter
   livepatch: enabling patch 'test_klp_callbacks_demo'
   livepatch: 'test_klp_callbacks_demo': initializing patching transition
   test_klp_callbacks_demo: pre_patch_callback: vmlinux

Force the module init function to wait until busymod_work_func() has
started (and logged its message), before exiting to the next selftest
steps.

Fixes: 547840bd5ae5 ("selftests/livepatch: simplify test-klp-callbacks busy target tests")
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20220602203233.979681-1-joe.lawrence@redhat.com
lib/livepatch/test_klp_callbacks_busy.c

index 7ac845f65be568ce2ce009adb4c66739479b04bc..133929e0ce8ff0a0ffcece81544f5c2c940c97fd 100644 (file)
@@ -16,10 +16,12 @@ MODULE_PARM_DESC(block_transition, "block_transition (default=false)");
 
 static void busymod_work_func(struct work_struct *work);
 static DECLARE_WORK(work, busymod_work_func);
+static DECLARE_COMPLETION(busymod_work_started);
 
 static void busymod_work_func(struct work_struct *work)
 {
        pr_info("%s enter\n", __func__);
+       complete(&busymod_work_started);
 
        while (READ_ONCE(block_transition)) {
                /*
@@ -37,6 +39,12 @@ static int test_klp_callbacks_busy_init(void)
        pr_info("%s\n", __func__);
        schedule_work(&work);
 
+       /*
+        * To synchronize kernel messages, hold the init function from
+        * exiting until the work function's entry message has printed.
+        */
+       wait_for_completion(&busymod_work_started);
+
        if (!block_transition) {
                /*
                 * Serialize output: print all messages from the work