-
Notifications
You must be signed in to change notification settings - Fork 309
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
kpatch: Add subcommand '--enabling' to adjust new sysfs attribute 'st… #1419
base: master
Are you sure you want to change the base?
Conversation
fyi for reviewers, here is a sample output when loading the kernel's kselftest modules used during the test of this sysfs feature:
A few thoughts:
Note that these aren't necessarily changes that I'm requesting, but I think a greater conversation around the display and feature would make sense first. |
@joe-lawrence Hi,joe! |
2 - The question is whether the list of livepatched functions (per loaded livepatch) is still useful to the user regardless of kernel support for stack order. That would be 99% the same code as reporting with stack order considered and offer potential value to any (older) kernel that didn't have such support. 3 - I find |
@joe-lawrence However, for point 2, older kernel version which is not support this attribute can just output "unsupported" Thank you |
a2f442f
to
e9b233d
Compare
@joe-lawrence Under older version: the output can be:
If there are just only one module loaded:
|
e9b233d
to
50e4a0a
Compare
Ok nobody else seems to have a UX opinion, so you're stuck with my thoughts, @wardenjohn 😆 In that case, let's keep it as simple as possible:
|
@joe-lawrence Ok, next version I will fix according to the suggestion you given. I looked into the shellcheck complaints from github. It seems that it complaints because I don't use the variable declared in the shell code. If it is necessary, I will fix it the next version. And I don't know when will Petr push the 'stack_order' patch to linux branch. So, I suggest this patch should be merged after the attribute is pushed into the linux kernel branch. 😄 Thanks! |
cbf1ccf
to
6f037b6
Compare
@joe-lawrence I resubmit an newer version of this function. However, I separate this commit into to parts because the first commit is the real function commit. The second patch fix the complaints of using 'find' instead of 'ls' and fix the complaint about unused variables. This tow commits do the different things. So, I make them tow commits here. Thanks. |
When I suggested simpler, it was a reduced and slightly refactored version like: show_enabled_function() {
# Create a map that associates a [livepatched object, function
# name, symbol position] with its [module, stack_order], i.e.
# (vmlinux,meminfo_proc_show,1) -> (test_klp_atomic_replace, 1)
declare -A function_map
for module_dir in "$SYSFS"/*; do
if [[ ! -d "$module_dir" ]] || \
[[ ! -e "$module_dir/stack_order" ]]; then
continue
fi
stack_order=$(cat "$module_dir/stack_order")
module_name=$(basename "$module_dir")
for obj_dir in "$module_dir"/*/; do
obj_name=$(basename "$obj_dir")
for func_dir in "$obj_dir"/*; do
if [[ ! -d "$func_dir" ]]; then
continue
fi
func_name_and_pos=$(basename "$func_dir")
key="$obj_name:$func_name_and_pos"
if [[ -z "${function_map[$key]}" ]]; then
function_map[$key]="$stack_order:$module_name"
else
# Update the map only iff this livepatch has a
# higher stack_order value
IFS=':' read -r recorded_order <<< "${function_map[$key]}"
if [[ $recorded_order -lt $stack_order ]]; then
function_map[$key]="$stack_order:$module_name:$obj_name"
fi
fi
done
done
done
# Pretty print the function map if it has any contents
if [[ ${#function_map[@]} -ne 0 ]]; then
echo ""
echo "Currently livepatched functions:"
declare -a output_data=("Module Object Function/Occurrence")
for key in "${!function_map[@]}"; do
IFS=':' read -r stack_order module_name <<< "${function_map[$key]}"
obj_name=${key%%:*}
func_name_and_pos=${key##*:}
output_data+=("$module_name $obj_name $func_name_and_pos")
done
printf "%s\n" "${output_data[@]}" | column -t
fi
} A few notes:
|
@joe-lawrence I am quite curious about the 'pos'. I am a little confuse about point 2. If there is a same name in the same object file. It should be patched? And for point 3, if system have no |
Consider a patch to two functions of the same name that end up in the same livepatch target (vmlinux): diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 232026a239a6..b72c51f1a4b8 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -722,6 +722,7 @@ static ssize_t version_show(struct device *dev,
{
struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+ nop();
return sprintf(buf, "0x%x\n", uci->cpu_sig.rev);
}
diff --git a/arch/x86/kernel/ksysfs.c b/arch/x86/kernel/ksysfs.c
index 257892fcefa7..a36fcece7344 100644
--- a/arch/x86/kernel/ksysfs.c
+++ b/arch/x86/kernel/ksysfs.c
@@ -22,6 +22,7 @@
static ssize_t version_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
+ nop();
return sprintf(buf, "0x%04x\n", boot_params.hdr.version);
} It is represented in sysfs representation like so: $ tree /sys/kernel/livepatch/livepatch_version_show/
/sys/kernel/livepatch/livepatch_version_show/
├── enabled
├── force
├── transition
└── vmlinux
├── patched
├── version_show,1 # corresponds to ksysfs.c's version_show()
└── version_show,2 # corresponds to core.c's version_show() The $ readelf --wide --symbols vmlinux | awk '$4 == "FILE" { f=$0 } $NF == "version_show" { print f; print $0 }'
4772: 0000000000000000 0 FILE LOCAL DEFAULT ABS ksysfs.c
4776: ffffffff81036420 37 FUNC LOCAL DEFAULT 1 version_show
7468: 0000000000000000 0 FILE LOCAL DEFAULT ABS core.c
7476: ffffffff81057d90 48 FUNC LOCAL DEFAULT 1 version_show
...
Since nobody else has commented on the PR, I would just go with whatever is the simplest to implement and review for now. Fancier behavior can be added if someone requests it (and let them code and test it :). (From previous comments):
In future code reviews, I believe that:
|
@joe-lawrence I will soon follow up this MR after the patch of 'stack_order' is pushed to linux-6.14. Thanks. |
6f037b6
to
6659f33
Compare
@joe-lawrence I have cleanup of any potential commit in one open PR and in one commit right now. When kpatch run in a kernel not supporting 'stack_order': the output is the original type without any change.
And tested with the patched you provided before of different symbol pos. The output is like:
This livepatch modules are built by REPLACE=0 for better testing result. And yet, for the original suggestion, the And again, sorry for answering late....:) |
6659f33
to
5e63479
Compare
@joe-lawrence Hi,Joe. How about this commit now? 😄😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @wardenjohn , thanks for sticking with this MR and updating as per the reviews.
I think the code is almost good to go (see one small bug and a few other nitpicks). Double check that the kpatch manual page matches the new usage. And then, the commit message could be revised for clarity, like:
kpatch: add currenly livepatched function report to 'kpatch list'
The upstream kernel introduced the livepatch 'stack_order' sysfs
attribute in v6.14. This value provides the order in which a live patch
module was loaded into the system. With 'stack_order', a user can
determine an active live patched version of a function when several
livepatches that modify the same function have been loaded.For systems supporting 'stack_order', provide additional 'kpatch list'
information about the currently livepatched functions in the system
(livepatch module, target kernel object, and function/symbol-position).
By reporting the highest 'stack_order' for a given function, the user
can learn precisely which kpatch module(s) / function(s) are currently
active.
Quick follow up question -- what happens if there is a livepatch that is still in transition? Does it make sense to list both (the outgoing and incoming) functions/modules? Keep in mind that some transitions may take a while, so there is a window of time where some tasks may execute the old version and others the newer version. |
So , do you think that we should add a column of 'transition' ? |
|
In fact, I think keeping that way still make sence. Because a livepatch module which is in transitioning still make effect to some stask which is successfully changing status. I think this module is in a half-working status, we should make it count. |
In that case, the current function map implementation wouldn't handle that case. Perhaps it could incorporate the target livepatch state as part of its key (and listing only when its in transition)? |
OK, I will later resubmit a newer version contains the information of patch transition ;) |
fd6e3e3
to
761d8ef
Compare
761d8ef
to
e2727f9
Compare
@joe-lawrence |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Latest seems to work (though takes a while to test the permutations ;). A few nits here and previous comment about the commit message.
kpatch/kpatch
Outdated
|
||
if [[ $transition -eq 1 ]]; then | ||
transition_map[$module_name]="transition" | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This transition_map assignment can occur (once) when the transition variable is set for the given module a few lines up and outside the obj_dir and func_dir loops.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I had moved it outsize the obd_dir loops. But for the second suggestion, I didn't fix it cause further discussion was needed ;)
kpatch/kpatch
Outdated
if [[ -n ${transition_map[$module_name]} ]]; then | ||
output_data+=("$module_name $obj_name $func_name_and_pos (${transition_map[$module_name]})") | ||
fi | ||
output_data+=("$module_name $obj_name $func_name_and_pos") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this change there will be double output for a given function who's livepatch is in transition, like:
Currently livepatched functions:
Module Object Function/Occurrence
test_klp_callbacks_demo test_klp_callbacks_busy busymod_work_func,1 (transition)
test_klp_callbacks_demo test_klp_callbacks_busy busymod_work_func,1
so I think it would be clearer if this an if (transition_map entry) ... else ... block to only print one or the other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so I think it would be clearer if this an if (transition_map entry) ... else ... block to only print one or the other.
Really? If there are many module working in system. Only print it once I am afraid that it would make it somehow hard to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really? If there are many module working in system. Only print it once I am afraid that it would make it somehow hard to read.
Hmm, let me reword my suggestion. I find it confusing to list the same module / object / function occurrence twice: once from the transition_map, and then a second time from the function_map.
If there are other module / object / functions in either map, then of course those should also be printed. (But as above, only once and I suggested that the transition_map version take priority.)
Does that make more sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me understand your suggestion.
Now, my output will be
Currently livepatched functions:
Module Object Function/Occurrence
test_klp_callbacks_demo test_klp_callbacks_busy busymod_work_func,1 (transition)
test_klp_callbacks_demo test_klp_callbacks_busy busymod_work_func,1 (transition)
And you hope the status of transition will just output once just like what you show before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found it interesting that in your demo, the function is the same.
In fact, we may hardly face this situation, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function listing is the same because it has one entry in the transition_map, and then another entry in the function_map. As currently coded, it will print a line for the transition_map if present. Then it will print the second line for the function_map. IIUC, there will always be two lines for all functions from any livepatch module that is transitioning.
If you want to see this in action, run something like the "busy target module" test in the kernel livepatching kselftests (tools/testing/selftests/livepatch/test-callbacks.sh). After these lines:
...
load_mod $MOD_TARGET_BUSY block_transition=Y
load_lp_nowait $MOD_LIVEPATCH
# Wait until the livepatch reports in-transition state, i.e. that it's
# stalled on $MOD_TARGET_BUSY::busymod_work_func()
loop_until 'grep -q '^1$' $SYSFS_KLP_DIR/$MOD_LIVEPATCH/transition' ||
die "failed to stall transition"
...
the system should be in a state similar to the what I reported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joe-lawrence
Cool! I found bug, adding a else
branch will fix it!
e2727f9
to
8475a2b
Compare
…ivepatch Add function of 'kpatch list' to adjust kernel new attribute 'stack_order' of livepatch of kernel v6.14 or later. Now, using 'kpatch list' can output the enabling function in the system and the relationship from the enabling function to its object and its related module. This feature only support the kernel with 'stack_order' attribute. Suggested-by: Joe Lawrence <joe.lawrence@redhat.com> Signed-off-by: Wardenjohn <zhangwarden@gmail.com>
8475a2b
to
ff5ff0e
Compare
…ack_order' of livepatch
Add an sub command of kpatch list with '--enabling' option to adjust kernel new attribute 'stack_order' of livepatch of kernel v6.13 or later.
Now, using 'kpatch list --enabling' can output the enabling function in the system and the relationship from the livepatch module -> livepatch object -> livepatch function.
PS: This is a pre-commit. This patch should be merged after the 'stack_order' patch is merged into kernel v6.13 or later.