-
Notifications
You must be signed in to change notification settings - Fork 304
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....:) |
…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 <[email protected]> Signed-off-by: Wardenjohn <[email protected]>
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.
@@ -55,7 +55,7 @@ usage () { | |||
echo >&2 | |||
usage_cmd "info <module>" "show information about a patch module" | |||
echo >&2 | |||
usage_cmd "list" "list installed patch modules" | |||
usage_cmd "list" "list installed patch modules, and list the enabling functions and its relationship from patch module to the function enabling in the system if 'stack_order' attribute is supported." |
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'd simplify this to, "If the system supports the livepatch 'stack_order' sysfs attribute, provide the list of currently livepatched functions".
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.
Also, this usage text change should be reflected in the manpage file: man/kpatch.1
fi | ||
stack_order=$(cat "$module_dir/stack_order") | ||
module_name=$(basename "$module_dir") | ||
for obj_dir in "$module_dir"/*/; do |
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.
nit: all the other directory iterators do so on the base directory and then check that the entry is a directory itself (for example, $func_dir
). Might as well make it consistent here.
else | ||
# Update the map only iff this livepatch has a | ||
# higher stack_order value | ||
IFS=':' read -r recorded_order module_name <<< "${function_map[$key]}" |
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 think there is a subtle bug here, where module_name
is read in from the function_map, but then a few lines later, the map is updated with $stack_order:$module_name:$obj_name
so the net effect is that the map gets the previous (now lower stack_order) livepatch module name.
I think the simplest fix would be to rename this sole variable instance like:
IFS=':' read -r recorded_order recorded_module_name ...
that way it's read and stashed in an unused temporary variable. The higher stack_order livepatch in question module_name
is left intact and the map update should now be accurate.
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.
Bravo! I didn't realize that there may have such problem. Thank you for pointing it out!
…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.