162306a36Sopenharmony_ci#!/bin/bash
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci# Copyright (C) 2018 Joe Lawrence <joe.lawrence@redhat.com>
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci. $(dirname $0)/functions.sh
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciMOD_LIVEPATCH=test_klp_callbacks_demo
862306a36Sopenharmony_ciMOD_LIVEPATCH2=test_klp_callbacks_demo2
962306a36Sopenharmony_ciMOD_TARGET=test_klp_callbacks_mod
1062306a36Sopenharmony_ciMOD_TARGET_BUSY=test_klp_callbacks_busy
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cisetup_config
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci# Test a combination of loading a kernel module and a livepatch that
1662306a36Sopenharmony_ci# patches a function in the first module.  Load the target module
1762306a36Sopenharmony_ci# before the livepatch module.  Unload them in the same order.
1862306a36Sopenharmony_ci#
1962306a36Sopenharmony_ci# - On livepatch enable, before the livepatch transition starts,
2062306a36Sopenharmony_ci#   pre-patch callbacks are executed for vmlinux and $MOD_TARGET (those
2162306a36Sopenharmony_ci#   klp_objects currently loaded).  After klp_objects are patched
2262306a36Sopenharmony_ci#   according to the klp_patch, their post-patch callbacks run and the
2362306a36Sopenharmony_ci#   transition completes.
2462306a36Sopenharmony_ci#
2562306a36Sopenharmony_ci# - Similarly, on livepatch disable, pre-patch callbacks run before the
2662306a36Sopenharmony_ci#   unpatching transition starts.  klp_objects are reverted, post-patch
2762306a36Sopenharmony_ci#   callbacks execute and the transition completes.
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistart_test "target module before livepatch"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ciload_mod $MOD_TARGET
3262306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH
3362306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH
3462306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH
3562306a36Sopenharmony_ciunload_mod $MOD_TARGET
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cicheck_result "% modprobe $MOD_TARGET
3862306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_init
3962306a36Sopenharmony_ci% modprobe $MOD_LIVEPATCH
4062306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
4162306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
4262306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: vmlinux
4362306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
4462306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting patching transition
4562306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing patching transition
4662306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: vmlinux
4762306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
4862306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': patching complete
4962306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
5062306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
5162306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
5262306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
5362306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting unpatching transition
5462306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing unpatching transition
5562306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
5662306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
5762306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': unpatching complete
5862306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH
5962306a36Sopenharmony_ci% rmmod $MOD_TARGET
6062306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_exit"
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci# This test is similar to the previous test, but (un)load the livepatch
6462306a36Sopenharmony_ci# module before the target kernel module.  This tests the livepatch
6562306a36Sopenharmony_ci# core's module_coming handler.
6662306a36Sopenharmony_ci#
6762306a36Sopenharmony_ci# - On livepatch enable, only pre/post-patch callbacks are executed for
6862306a36Sopenharmony_ci#   currently loaded klp_objects, in this case, vmlinux.
6962306a36Sopenharmony_ci#
7062306a36Sopenharmony_ci# - When a targeted module is subsequently loaded, only its
7162306a36Sopenharmony_ci#   pre/post-patch callbacks are executed.
7262306a36Sopenharmony_ci#
7362306a36Sopenharmony_ci# - On livepatch disable, all currently loaded klp_objects' (vmlinux and
7462306a36Sopenharmony_ci#   $MOD_TARGET) pre/post-unpatch callbacks are executed.
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistart_test "module_coming notifier"
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH
7962306a36Sopenharmony_ciload_mod $MOD_TARGET
8062306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH
8162306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH
8262306a36Sopenharmony_ciunload_mod $MOD_TARGET
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cicheck_result "% modprobe $MOD_LIVEPATCH
8562306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
8662306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
8762306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: vmlinux
8862306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting patching transition
8962306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing patching transition
9062306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: vmlinux
9162306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': patching complete
9262306a36Sopenharmony_ci% modprobe $MOD_TARGET
9362306a36Sopenharmony_cilivepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
9462306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
9562306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
9662306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_init
9762306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
9862306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
9962306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
10062306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
10162306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting unpatching transition
10262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing unpatching transition
10362306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
10462306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
10562306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': unpatching complete
10662306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH
10762306a36Sopenharmony_ci% rmmod $MOD_TARGET
10862306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_exit"
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci# Test loading the livepatch after a targeted kernel module, then unload
11262306a36Sopenharmony_ci# the kernel module before disabling the livepatch.  This tests the
11362306a36Sopenharmony_ci# livepatch core's module_going handler.
11462306a36Sopenharmony_ci#
11562306a36Sopenharmony_ci# - First load a target module, then the livepatch.
11662306a36Sopenharmony_ci#
11762306a36Sopenharmony_ci# - When a target module is unloaded, the livepatch is only reverted
11862306a36Sopenharmony_ci#   from that klp_object ($MOD_TARGET).  As such, only its pre and
11962306a36Sopenharmony_ci#   post-unpatch callbacks are executed when this occurs.
12062306a36Sopenharmony_ci#
12162306a36Sopenharmony_ci# - When the livepatch is disabled, pre and post-unpatch callbacks are
12262306a36Sopenharmony_ci#   run for the remaining klp_object, vmlinux.
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistart_test "module_going notifier"
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ciload_mod $MOD_TARGET
12762306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH
12862306a36Sopenharmony_ciunload_mod $MOD_TARGET
12962306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH
13062306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cicheck_result "% modprobe $MOD_TARGET
13362306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_init
13462306a36Sopenharmony_ci% modprobe $MOD_LIVEPATCH
13562306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
13662306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
13762306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: vmlinux
13862306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
13962306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting patching transition
14062306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing patching transition
14162306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: vmlinux
14262306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_LIVE] Normal state
14362306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': patching complete
14462306a36Sopenharmony_ci% rmmod $MOD_TARGET
14562306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_exit
14662306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
14762306a36Sopenharmony_cilivepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
14862306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
14962306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
15062306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
15162306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
15262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting unpatching transition
15362306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing unpatching transition
15462306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
15562306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': unpatching complete
15662306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH"
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci# This test is similar to the previous test, however the livepatch is
16062306a36Sopenharmony_ci# loaded first.  This tests the livepatch core's module_coming and
16162306a36Sopenharmony_ci# module_going handlers.
16262306a36Sopenharmony_ci#
16362306a36Sopenharmony_ci# - First load the livepatch.
16462306a36Sopenharmony_ci#
16562306a36Sopenharmony_ci# - When a targeted kernel module is subsequently loaded, only its
16662306a36Sopenharmony_ci#   pre/post-patch callbacks are executed.
16762306a36Sopenharmony_ci#
16862306a36Sopenharmony_ci# - When the target module is unloaded, the livepatch is only reverted
16962306a36Sopenharmony_ci#   from the $MOD_TARGET klp_object.  As such, only pre and
17062306a36Sopenharmony_ci#   post-unpatch callbacks are executed when this occurs.
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistart_test "module_coming and module_going notifiers"
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH
17562306a36Sopenharmony_ciload_mod $MOD_TARGET
17662306a36Sopenharmony_ciunload_mod $MOD_TARGET
17762306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH
17862306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cicheck_result "% modprobe $MOD_LIVEPATCH
18162306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
18262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
18362306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: vmlinux
18462306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting patching transition
18562306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing patching transition
18662306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: vmlinux
18762306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': patching complete
18862306a36Sopenharmony_ci% modprobe $MOD_TARGET
18962306a36Sopenharmony_cilivepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
19062306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
19162306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
19262306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_init
19362306a36Sopenharmony_ci% rmmod $MOD_TARGET
19462306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_exit
19562306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
19662306a36Sopenharmony_cilivepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
19762306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
19862306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
19962306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
20062306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
20162306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting unpatching transition
20262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing unpatching transition
20362306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
20462306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': unpatching complete
20562306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH"
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci# A simple test of loading a livepatch without one of its patch target
20962306a36Sopenharmony_ci# klp_objects ever loaded ($MOD_TARGET).
21062306a36Sopenharmony_ci#
21162306a36Sopenharmony_ci# - Load the livepatch.
21262306a36Sopenharmony_ci#
21362306a36Sopenharmony_ci# - As expected, only pre/post-(un)patch handlers are executed for
21462306a36Sopenharmony_ci#   vmlinux.
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistart_test "target module not present"
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH
21962306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH
22062306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cicheck_result "% modprobe $MOD_LIVEPATCH
22362306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
22462306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
22562306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: vmlinux
22662306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting patching transition
22762306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing patching transition
22862306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: vmlinux
22962306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': patching complete
23062306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
23162306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
23262306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
23362306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting unpatching transition
23462306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing unpatching transition
23562306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
23662306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': unpatching complete
23762306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH"
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci# Test a scenario where a vmlinux pre-patch callback returns a non-zero
24162306a36Sopenharmony_ci# status (ie, failure).
24262306a36Sopenharmony_ci#
24362306a36Sopenharmony_ci# - First load a target module.
24462306a36Sopenharmony_ci#
24562306a36Sopenharmony_ci# - Load the livepatch module, setting its 'pre_patch_ret' value to -19
24662306a36Sopenharmony_ci#   (-ENODEV).  When its vmlinux pre-patch callback executes, this
24762306a36Sopenharmony_ci#   status code will propagate back to the module-loading subsystem.
24862306a36Sopenharmony_ci#   The result is that the insmod command refuses to load the livepatch
24962306a36Sopenharmony_ci#   module.
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistart_test "pre-patch callback -ENODEV"
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ciload_mod $MOD_TARGET
25462306a36Sopenharmony_ciload_failing_mod $MOD_LIVEPATCH pre_patch_ret=-19
25562306a36Sopenharmony_ciunload_mod $MOD_TARGET
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cicheck_result "% modprobe $MOD_TARGET
25862306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_init
25962306a36Sopenharmony_ci% modprobe $MOD_LIVEPATCH pre_patch_ret=-19
26062306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
26162306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
26262306a36Sopenharmony_citest_klp_callbacks_demo: pre_patch_callback: vmlinux
26362306a36Sopenharmony_cilivepatch: pre-patch callback failed for object 'vmlinux'
26462306a36Sopenharmony_cilivepatch: failed to enable patch '$MOD_LIVEPATCH'
26562306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': canceling patching transition, going to unpatch
26662306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing unpatching transition
26762306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': unpatching complete
26862306a36Sopenharmony_cimodprobe: ERROR: could not insert '$MOD_LIVEPATCH': No such device
26962306a36Sopenharmony_ci% rmmod $MOD_TARGET
27062306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_exit"
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci# Similar to the previous test, setup a livepatch such that its vmlinux
27462306a36Sopenharmony_ci# pre-patch callback returns success.  However, when a targeted kernel
27562306a36Sopenharmony_ci# module is later loaded, have the livepatch return a failing status
27662306a36Sopenharmony_ci# code.
27762306a36Sopenharmony_ci#
27862306a36Sopenharmony_ci# - Load the livepatch, vmlinux pre-patch callback succeeds.
27962306a36Sopenharmony_ci#
28062306a36Sopenharmony_ci# - Set a trap so subsequent pre-patch callbacks to this livepatch will
28162306a36Sopenharmony_ci#   return -ENODEV.
28262306a36Sopenharmony_ci#
28362306a36Sopenharmony_ci# - The livepatch pre-patch callback for subsequently loaded target
28462306a36Sopenharmony_ci#   modules will return failure, so the module loader refuses to load
28562306a36Sopenharmony_ci#   the kernel module.  No post-patch or pre/post-unpatch callbacks are
28662306a36Sopenharmony_ci#   executed for this klp_object.
28762306a36Sopenharmony_ci#
28862306a36Sopenharmony_ci# - Pre/post-unpatch callbacks are run for the vmlinux klp_object.
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistart_test "module_coming + pre-patch callback -ENODEV"
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH
29362306a36Sopenharmony_ciset_pre_patch_ret $MOD_LIVEPATCH -19
29462306a36Sopenharmony_ciload_failing_mod $MOD_TARGET
29562306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH
29662306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_cicheck_result "% modprobe $MOD_LIVEPATCH
29962306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
30062306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
30162306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: vmlinux
30262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting patching transition
30362306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing patching transition
30462306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: vmlinux
30562306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': patching complete
30662306a36Sopenharmony_ci% echo -19 > /sys/module/$MOD_LIVEPATCH/parameters/pre_patch_ret
30762306a36Sopenharmony_ci% modprobe $MOD_TARGET
30862306a36Sopenharmony_cilivepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
30962306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
31062306a36Sopenharmony_cilivepatch: pre-patch callback failed for object '$MOD_TARGET'
31162306a36Sopenharmony_cilivepatch: patch '$MOD_LIVEPATCH' failed for module '$MOD_TARGET', refusing to load module '$MOD_TARGET'
31262306a36Sopenharmony_cimodprobe: ERROR: could not insert '$MOD_TARGET': No such device
31362306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
31462306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
31562306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
31662306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting unpatching transition
31762306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing unpatching transition
31862306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
31962306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': unpatching complete
32062306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH"
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci# Test loading multiple targeted kernel modules.  This test-case is
32462306a36Sopenharmony_ci# mainly for comparing with the next test-case.
32562306a36Sopenharmony_ci#
32662306a36Sopenharmony_ci# - Load a target "busy" kernel module which kicks off a worker function
32762306a36Sopenharmony_ci#   that immediately exits.
32862306a36Sopenharmony_ci#
32962306a36Sopenharmony_ci# - Proceed with loading the livepatch and another ordinary target
33062306a36Sopenharmony_ci#   module.  Post-patch callbacks are executed and the transition
33162306a36Sopenharmony_ci#   completes quickly.
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cistart_test "multiple target modules"
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ciload_mod $MOD_TARGET_BUSY block_transition=N
33662306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH
33762306a36Sopenharmony_ciload_mod $MOD_TARGET
33862306a36Sopenharmony_ciunload_mod $MOD_TARGET
33962306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH
34062306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH
34162306a36Sopenharmony_ciunload_mod $MOD_TARGET_BUSY
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cicheck_result "% modprobe $MOD_TARGET_BUSY block_transition=N
34462306a36Sopenharmony_ci$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init
34562306a36Sopenharmony_ci$MOD_TARGET_BUSY: busymod_work_func enter
34662306a36Sopenharmony_ci$MOD_TARGET_BUSY: busymod_work_func exit
34762306a36Sopenharmony_ci% modprobe $MOD_LIVEPATCH
34862306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
34962306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
35062306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: vmlinux
35162306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
35262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting patching transition
35362306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing patching transition
35462306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: vmlinux
35562306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
35662306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': patching complete
35762306a36Sopenharmony_ci% modprobe $MOD_TARGET
35862306a36Sopenharmony_cilivepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
35962306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
36062306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
36162306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_init
36262306a36Sopenharmony_ci% rmmod $MOD_TARGET
36362306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_exit
36462306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
36562306a36Sopenharmony_cilivepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
36662306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
36762306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
36862306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
36962306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
37062306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
37162306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting unpatching transition
37262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing unpatching transition
37362306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
37462306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
37562306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': unpatching complete
37662306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH
37762306a36Sopenharmony_ci% rmmod $MOD_TARGET_BUSY
37862306a36Sopenharmony_ci$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci# A similar test as the previous one, but force the "busy" kernel module
38262306a36Sopenharmony_ci# to block the livepatch transition.
38362306a36Sopenharmony_ci#
38462306a36Sopenharmony_ci# The livepatching core will refuse to patch a task that is currently
38562306a36Sopenharmony_ci# executing a to-be-patched function -- the consistency model stalls the
38662306a36Sopenharmony_ci# current patch transition until this safety-check is met.  Test a
38762306a36Sopenharmony_ci# scenario where one of a livepatch's target klp_objects sits on such a
38862306a36Sopenharmony_ci# function for a long time.  Meanwhile, load and unload other target
38962306a36Sopenharmony_ci# kernel modules while the livepatch transition is in progress.
39062306a36Sopenharmony_ci#
39162306a36Sopenharmony_ci# - Load the "busy" kernel module, this time make its work function loop
39262306a36Sopenharmony_ci#
39362306a36Sopenharmony_ci# - Meanwhile, the livepatch is loaded.  Notice that the patch
39462306a36Sopenharmony_ci#   transition does not complete as the targeted "busy" module is
39562306a36Sopenharmony_ci#   sitting on a to-be-patched function.
39662306a36Sopenharmony_ci#
39762306a36Sopenharmony_ci# - Load a second target module (this one is an ordinary idle kernel
39862306a36Sopenharmony_ci#   module).  Note that *no* post-patch callbacks will be executed while
39962306a36Sopenharmony_ci#   the livepatch is still in transition.
40062306a36Sopenharmony_ci#
40162306a36Sopenharmony_ci# - Request an unload of the simple kernel module.  The patch is still
40262306a36Sopenharmony_ci#   transitioning, so its pre-unpatch callbacks are skipped.
40362306a36Sopenharmony_ci#
40462306a36Sopenharmony_ci# - Finally the livepatch is disabled.  Since none of the patch's
40562306a36Sopenharmony_ci#   klp_object's post-patch callbacks executed, the remaining
40662306a36Sopenharmony_ci#   klp_object's pre-unpatch callbacks are skipped.
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_cistart_test "busy target module"
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ciload_mod $MOD_TARGET_BUSY block_transition=Y
41162306a36Sopenharmony_ciload_lp_nowait $MOD_LIVEPATCH
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci# Wait until the livepatch reports in-transition state, i.e. that it's
41462306a36Sopenharmony_ci# stalled on $MOD_TARGET_BUSY::busymod_work_func()
41562306a36Sopenharmony_ciloop_until 'grep -q '^1$' /sys/kernel/livepatch/$MOD_LIVEPATCH/transition' ||
41662306a36Sopenharmony_ci	die "failed to stall transition"
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ciload_mod $MOD_TARGET
41962306a36Sopenharmony_ciunload_mod $MOD_TARGET
42062306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH
42162306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH
42262306a36Sopenharmony_ciunload_mod $MOD_TARGET_BUSY
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_cicheck_result "% modprobe $MOD_TARGET_BUSY block_transition=Y
42562306a36Sopenharmony_ci$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_init
42662306a36Sopenharmony_ci$MOD_TARGET_BUSY: busymod_work_func enter
42762306a36Sopenharmony_ci% modprobe $MOD_LIVEPATCH
42862306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
42962306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
43062306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: vmlinux
43162306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
43262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting patching transition
43362306a36Sopenharmony_ci% modprobe $MOD_TARGET
43462306a36Sopenharmony_cilivepatch: applying patch '$MOD_LIVEPATCH' to loading module '$MOD_TARGET'
43562306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: $MOD_TARGET -> [MODULE_STATE_COMING] Full formed, running module_init
43662306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_init
43762306a36Sopenharmony_ci% rmmod $MOD_TARGET
43862306a36Sopenharmony_ci$MOD_TARGET: ${MOD_TARGET}_exit
43962306a36Sopenharmony_cilivepatch: reverting patch '$MOD_LIVEPATCH' on unloading module '$MOD_TARGET'
44062306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET -> [MODULE_STATE_GOING] Going away
44162306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
44262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': reversing transition from patching to unpatching
44362306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting unpatching transition
44462306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing unpatching transition
44562306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
44662306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: $MOD_TARGET_BUSY -> [MODULE_STATE_LIVE] Normal state
44762306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': unpatching complete
44862306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH
44962306a36Sopenharmony_ci% rmmod $MOD_TARGET_BUSY
45062306a36Sopenharmony_ci$MOD_TARGET_BUSY: busymod_work_func exit
45162306a36Sopenharmony_ci$MOD_TARGET_BUSY: ${MOD_TARGET_BUSY}_exit"
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci# Test loading multiple livepatches.  This test-case is mainly for comparing
45562306a36Sopenharmony_ci# with the next test-case.
45662306a36Sopenharmony_ci#
45762306a36Sopenharmony_ci# - Load and unload two livepatches, pre and post (un)patch callbacks
45862306a36Sopenharmony_ci#   execute as each patch progresses through its (un)patching
45962306a36Sopenharmony_ci#   transition.
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cistart_test "multiple livepatches"
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH
46462306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH2
46562306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH2
46662306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH
46762306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH2
46862306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_cicheck_result "% modprobe $MOD_LIVEPATCH
47162306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
47262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
47362306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: vmlinux
47462306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting patching transition
47562306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing patching transition
47662306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: vmlinux
47762306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': patching complete
47862306a36Sopenharmony_ci% modprobe $MOD_LIVEPATCH2
47962306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH2'
48062306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': initializing patching transition
48162306a36Sopenharmony_ci$MOD_LIVEPATCH2: pre_patch_callback: vmlinux
48262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': starting patching transition
48362306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': completing patching transition
48462306a36Sopenharmony_ci$MOD_LIVEPATCH2: post_patch_callback: vmlinux
48562306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': patching complete
48662306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH2/enabled
48762306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': initializing unpatching transition
48862306a36Sopenharmony_ci$MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux
48962306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': starting unpatching transition
49062306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': completing unpatching transition
49162306a36Sopenharmony_ci$MOD_LIVEPATCH2: post_unpatch_callback: vmlinux
49262306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': unpatching complete
49362306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
49462306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing unpatching transition
49562306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_unpatch_callback: vmlinux
49662306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting unpatching transition
49762306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing unpatching transition
49862306a36Sopenharmony_ci$MOD_LIVEPATCH: post_unpatch_callback: vmlinux
49962306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': unpatching complete
50062306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH2
50162306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH"
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci# Load multiple livepatches, but the second as an 'atomic-replace'
50562306a36Sopenharmony_ci# patch.  When the latter loads, the original livepatch should be
50662306a36Sopenharmony_ci# disabled and *none* of its pre/post-unpatch callbacks executed.  On
50762306a36Sopenharmony_ci# the other hand, when the atomic-replace livepatch is disabled, its
50862306a36Sopenharmony_ci# pre/post-unpatch callbacks *should* be executed.
50962306a36Sopenharmony_ci#
51062306a36Sopenharmony_ci# - Load and unload two livepatches, the second of which has its
51162306a36Sopenharmony_ci#   .replace flag set true.
51262306a36Sopenharmony_ci#
51362306a36Sopenharmony_ci# - Pre and post patch callbacks are executed for both livepatches.
51462306a36Sopenharmony_ci#
51562306a36Sopenharmony_ci# - Once the atomic replace module is loaded, only its pre and post
51662306a36Sopenharmony_ci#   unpatch callbacks are executed.
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_cistart_test "atomic replace"
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH
52162306a36Sopenharmony_ciload_lp $MOD_LIVEPATCH2 replace=1
52262306a36Sopenharmony_cidisable_lp $MOD_LIVEPATCH2
52362306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH2
52462306a36Sopenharmony_ciunload_lp $MOD_LIVEPATCH
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_cicheck_result "% modprobe $MOD_LIVEPATCH
52762306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH'
52862306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': initializing patching transition
52962306a36Sopenharmony_ci$MOD_LIVEPATCH: pre_patch_callback: vmlinux
53062306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': starting patching transition
53162306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': completing patching transition
53262306a36Sopenharmony_ci$MOD_LIVEPATCH: post_patch_callback: vmlinux
53362306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH': patching complete
53462306a36Sopenharmony_ci% modprobe $MOD_LIVEPATCH2 replace=1
53562306a36Sopenharmony_cilivepatch: enabling patch '$MOD_LIVEPATCH2'
53662306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': initializing patching transition
53762306a36Sopenharmony_ci$MOD_LIVEPATCH2: pre_patch_callback: vmlinux
53862306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': starting patching transition
53962306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': completing patching transition
54062306a36Sopenharmony_ci$MOD_LIVEPATCH2: post_patch_callback: vmlinux
54162306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': patching complete
54262306a36Sopenharmony_ci% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH2/enabled
54362306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': initializing unpatching transition
54462306a36Sopenharmony_ci$MOD_LIVEPATCH2: pre_unpatch_callback: vmlinux
54562306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': starting unpatching transition
54662306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': completing unpatching transition
54762306a36Sopenharmony_ci$MOD_LIVEPATCH2: post_unpatch_callback: vmlinux
54862306a36Sopenharmony_cilivepatch: '$MOD_LIVEPATCH2': unpatching complete
54962306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH2
55062306a36Sopenharmony_ci% rmmod $MOD_LIVEPATCH"
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ciexit 0
554