FAILED: patch "[PATCH] kprobes: Fix possible use-after-free issue on kprobe" failed to apply to 5.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.4.y
git checkout FETCH_HEAD
git cherry-pick -x 325f3fb551f8cd672dbbfc4cf58b14f9ee3fc9e8
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2024041525-compel-delta-953a@gregkh' --subject-prefix 'PATCH 5.4.y' HEAD^..
Possible dependencies:
325f3fb551f8 ("kprobes: Fix possible use-after-free issue on kprobe registration") 1efda38d6f9b ("kprobes: Prohibit probes in gate area")28f6c37a2910 ("kprobes: Forbid probing on trampoline and BPF code areas")223a76b268c9 ("kprobes: Fix coding style issues")9c89bb8e3272 ("kprobes: treewide: Cleanup the error messages for kprobes")02afb8d6048d ("kprobe: Simplify prepare_kprobe() by dropping redundant version") 9840cfcb97fc ("Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 325f3fb551f8cd672dbbfc4cf58b14f9ee3fc9e8 Mon Sep 17 00:00:00 2001
From: Zheng Yejian <[email protected]>
Date: Wed, 10 Apr 2024 09:58:02 +0800
Subject: [PATCH] kprobes: Fix possible use-after-free issue on kprobe
registration
When unloading a module, its state is changing MODULE_STATE_LIVE ->
MODULE_STATE_GOING -> MODULE_STATE_UNFORMED. Each change will take
a time. is_module_text_address() and __module_text_address() works with MODULE_STATE_LIVE and MODULE_STATE_GOING.
If we use is_module_text_address() and __module_text_address() separately, there is a chance that the first one is succeeded but the next one is failed because module->state becomes MODULE_STATE_UNFORMED between those operations.
In check_kprobe_address_safe(), if the second __module_text_address() is failed, that is ignored because it expected a kernel_text address. But it may have failed simply because module->state has been changed to MODULE_STATE_UNFORMED. In this case, arm_kprobe() will try to modify non-exist module text address (use-after-free).
To fix this problem, we should not use separated is_module_text_address() and __module_text_address(), but use only __module_text_address() once and do try_module_get(module) which is only available with MODULE_STATE_LIVE.
kernel/kprobes.c +12 -6
@@ -1567,10 +1567,17 @@ static int check_kprobe_address_safe(struct kprobe *p,jump_label_lock ();preempt_disable (); -/* Ensure it is not in reserved area nor out of text */ - if (!(core_kernel_text((unsigned long) p->addr) || - is_module_text_address((unsigned long) p->addr)) || - in_gate_area_no_mm((unsigned long) p->addr) || +/* Ensure the address is in a text area, and find a module if exists. */ + *probed_mod =NULL ; +if (!core_kernel_text ((unsigned long ) p->addr)) { + *probed_mod =__module_text_address ((unsigned long ) p->addr); +if (!(*probed_mod)) { + ret = -EINVAL ; + goto out; + } + } +/* Ensure it is not in reserved area. */ + if (in_gate_area_no_mm((unsigned long) p->addr) || within_kprobe_blacklist((unsigned long) p->addr) || jump_label_text_reserved(p->addr, p->addr) || static_call_text_reserved(p->addr, p->addr) ||
@@ -1580,8 +1587,7 @@ static int check_kprobe_address_safe(struct kprobe *p, goto out; } -/* Check if 'p' is probing a module. */ - *probed_mod =__module_text_address ((unsigned long ) p->addr); +/* Get module refcount and reject __init functions for loaded modules. */ if (*probed_mod) {/* * We must hold a refcount of the probed module while updating
PATCH 1/1 kprobes: Fix possible use-after-free issue on kprobe registration
commit 325f3fb551f8cd672dbbfc4cf58b14f9ee3fc9e8 upstream.
When unloading a module, its state is changing MODULE_STATE_LIVE ->
MODULE_STATE_GOING -> MODULE_STATE_UNFORMED. Each change will take
a time. is_module_text_address() and __module_text_address() works with MODULE_STATE_LIVE and MODULE_STATE_GOING.
If we use is_module_text_address() and __module_text_address() separately, there is a chance that the first one is succeeded but the next one is failed because module->state becomes MODULE_STATE_UNFORMED between those operations.
In check_kprobe_address_safe(), if the second __module_text_address() is failed, that is ignored because it expected a kernel_text address. But it may have failed simply because module->state has been changed to MODULE_STATE_UNFORMED. In this case, arm_kprobe() will try to modify non-exist module text address (use-after-free).
To fix this problem, we should not use separated is_module_text_address() and __module_text_address(), but use only __module_text_address() once and do try_module_get(module) which is only available with MODULE_STATE_LIVE.
[Fix conflicts due to lack of
commit 223a76b268c9 ("kprobes: Fix coding style issues")]
--- kernel/kprobes.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
kernel/kprobes.c +12 -6
@@ -1593,10 +1593,17 @@ static int check_kprobe_address_safe(struct kprobe *p,jump_label_lock ();preempt_disable (); -/* Ensure it is not in reserved area nor out of text */ -if (!(core_kernel_text ((unsigned long ) p->addr) || -is_module_text_address ((unsigned long ) p->addr)) || -in_gate_area_no_mm ((unsigned long ) p->addr) || +/* Ensure the address is in a text area, and find a module if exists. */ + *probed_mod =NULL ; +if (!core_kernel_text ((unsigned long ) p->addr)) { + *probed_mod =__module_text_address ((unsigned long ) p->addr); +if (!(*probed_mod)) { + ret = -EINVAL ; + goto out; + } + } +/* Ensure it is not in reserved area. */ +if (in_gate_area_no_mm ((unsigned long ) p->addr) ||within_kprobe_blacklist ((unsigned long ) p->addr) ||jump_label_text_reserved (p->addr, p->addr) ||find_bug ((unsigned long )p->addr)) {
@@ -1604,8 +1611,7 @@ static int check_kprobe_address_safe(struct kprobe *p, goto out; } -/* Check if are we probing a module */ - *probed_mod =__module_text_address ((unsigned long ) p->addr); +/* Get module refcount and reject __init functions for loaded modules. */ if (*probed_mod) {/* * We must hold a refcount of the probed module while updating
Signature · 1 line
2.25.1