|
Miroslav Franc |
eb129d |
From: Vasily Gorbik <gor@linux.ibm.com>
|
|
Miroslav Franc |
eb129d |
Date: Wed, 1 Mar 2023 17:58:06 +0100
|
|
Miroslav Franc |
eb129d |
Subject: s390/kprobes: fix current_kprobe never cleared after kprobes reenter
|
|
Miroslav Franc |
eb129d |
Git-commit: cd57953936f2213dfaccce10d20f396956222c7d
|
|
Miroslav Franc |
eb129d |
Patch-mainline: v6.3-rc1
|
|
Miroslav Franc |
eb129d |
References: git-fixes bsc#1211688
|
|
Miroslav Franc |
eb129d |
|
|
Miroslav Franc |
eb129d |
Recent test_kprobe_missed kprobes kunit test uncovers the following
|
|
Miroslav Franc |
eb129d |
problem. Once kprobe is triggered from another kprobe (kprobe reenter),
|
|
Miroslav Franc |
eb129d |
all future kprobes on this cpu are considered as kprobe reenter, thus
|
|
Miroslav Franc |
eb129d |
pre_handler and post_handler are not being called and kprobes are counted
|
|
Miroslav Franc |
eb129d |
as "missed".
|
|
Miroslav Franc |
eb129d |
|
|
Miroslav Franc |
eb129d |
Commit b9599798f953 ("[S390] kprobes: activation and deactivation")
|
|
Miroslav Franc |
eb129d |
introduced a simpler scheme for kprobes (de)activation and status
|
|
Miroslav Franc |
eb129d |
tracking by using push_kprobe/pop_kprobe, which supposed to work for
|
|
Miroslav Franc |
eb129d |
both initial kprobe entry as well as kprobe reentry and helps to avoid
|
|
Miroslav Franc |
eb129d |
handling those two cases differently. The problem is that a sequence of
|
|
Miroslav Franc |
eb129d |
calls in case of kprobes reenter:
|
|
Miroslav Franc |
eb129d |
push_kprobe() <- NULL (current_kprobe)
|
|
Miroslav Franc |
eb129d |
push_kprobe() <- kprobe1 (current_kprobe)
|
|
Miroslav Franc |
eb129d |
pop_kprobe() -> kprobe1 (current_kprobe)
|
|
Miroslav Franc |
eb129d |
pop_kprobe() -> kprobe1 (current_kprobe)
|
|
Miroslav Franc |
eb129d |
leaves "kprobe1" as "current_kprobe" on this cpu, instead of setting it
|
|
Miroslav Franc |
eb129d |
to NULL. In fact push_kprobe/pop_kprobe can only store a single state
|
|
Miroslav Franc |
eb129d |
(there is just one prev_kprobe in kprobe_ctlblk). Which is a hack but
|
|
Miroslav Franc |
eb129d |
sufficient, there is no need to have another prev_kprobe just to store
|
|
Miroslav Franc |
eb129d |
NULL. To make a simple and backportable fix simply reset "prev_kprobe"
|
|
Miroslav Franc |
eb129d |
when kprobe is poped from this "stack". No need to worry about
|
|
Miroslav Franc |
eb129d |
"kprobe_status" in this case, because its value is only checked when
|
|
Miroslav Franc |
eb129d |
current_kprobe != NULL.
|
|
Miroslav Franc |
eb129d |
|
|
Miroslav Franc |
eb129d |
Cc: stable@vger.kernel.org
|
|
Miroslav Franc |
eb129d |
Fixes: b9599798f953 ("[S390] kprobes: activation and deactivation")
|
|
Miroslav Franc |
eb129d |
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
|
|
Miroslav Franc |
eb129d |
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
|
|
Miroslav Franc |
eb129d |
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
|
|
Miroslav Franc |
eb129d |
Acked-by: Miroslav Franc <mfranc@suse.cz>
|
|
Miroslav Franc |
eb129d |
---
|
|
Miroslav Franc |
eb129d |
arch/s390/kernel/kprobes.c | 1 +
|
|
Miroslav Franc |
eb129d |
1 file changed, 1 insertion(+)
|
|
Miroslav Franc |
eb129d |
|
|
Miroslav Franc |
eb129d |
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
|
|
Miroslav Franc |
eb129d |
index c505c0ee5f47..e53192a5d593 100644
|
|
Miroslav Franc |
eb129d |
--- a/arch/s390/kernel/kprobes.c
|
|
Miroslav Franc |
eb129d |
+++ b/arch/s390/kernel/kprobes.c
|
|
Miroslav Franc |
eb129d |
@@ -233,6 +233,7 @@ static void pop_kprobe(struct kprobe_ctlblk *kcb)
|
|
Miroslav Franc |
eb129d |
{
|
|
Miroslav Franc |
eb129d |
__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
|
|
Miroslav Franc |
eb129d |
kcb->kprobe_status = kcb->prev_kprobe.status;
|
|
Miroslav Franc |
eb129d |
+ kcb->prev_kprobe.kp = NULL;
|
|
Miroslav Franc |
eb129d |
}
|
|
Miroslav Franc |
eb129d |
NOKPROBE_SYMBOL(pop_kprobe);
|
|
Miroslav Franc |
eb129d |
|