crash-gcore-command/0002-x86-fix-the-issue-that-core-files-for-64-bit-tasks-a.patch
Tao Liu 8b31c045ac Release 1.6.4-2
Resolves: RHEL-73069

Signed-off-by: Tao Liu <ltao@redhat.com>
2025-05-05 15:57:37 +12:00

86 lines
3.4 KiB
Diff

From e03ff7341a9a624a46cea4e60ee097606b1687a8 Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
Date: Sat, 23 Nov 2024 17:30:41 +0900
Subject: [PATCH 2/2] x86: fix the issue that core files for 64-bit tasks are
generated in the 32-bit format
Core files for 64-bit tasks are falsely generated in the 32-bit
formats.
The root cause of this issue is that location of saving register
values on kernel stacks is changed by the kernel commit
65c9cc9e2c14602d98f1ca61c51ac954e9529303 (x86/fred: Reserve space for
the FRED stack frame) in Linux kernel 6.9-rc1 to add some reserved
area for FRED feature and gcore doesn't take this into
consideration. Hence, the value of CS register retrieved from kernel
stacks based on the existing logic is wrong and thus checking
execution mode of a given task based on the value also works wrong.
To fix this issue, let's take the FRED feature into account. If FRED
data structure is defined, retrieve register values from the address
next to the reserved for the FRED feature.
This logic is borrowed from the commit
48764a14bc5856f0b0bb30685336c68b832154fc (x86_64: fix for adding
top_of_kernel_stack_padding for kernel stack) and the commit
196c4b79c13d1c0e6d7b21c8321eca07d3838d6a (X86 64: fix a regression
issue about kernel stack padding) of crash utility.
---
src/libgcore/gcore_x86.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/libgcore/gcore_x86.c b/src/libgcore/gcore_x86.c
index 3ddf510..4f43956 100644
--- a/src/libgcore/gcore_x86.c
+++ b/src/libgcore/gcore_x86.c
@@ -514,10 +514,11 @@ convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_context *target
char *pt_regs_buf;
uint16_t ds;
struct machine_specific *ms = machdep->machspec;
+ ulong padding_size = VALID_SIZE(fred_frame) > 0 ? (2 * 8) : 0;
pt_regs_buf = GETBUF(SIZE(pt_regs));
- readmem(machdep->get_stacktop(target->task) - SIZE(pt_regs),
+ readmem(machdep->get_stacktop(target->task) - padding_size - SIZE(pt_regs),
KVADDR, pt_regs_buf, SIZE(pt_regs),
"convert_from_fxsr: regs",
gcore_verbose_error_handle());
@@ -1837,6 +1838,7 @@ static int genregs_get(struct task_context *target,
struct user_regs_struct active_regs;
const int active = is_task_active(target->task);
struct machine_specific *ms = machdep->machspec;
+ ulong padding_size = VALID_SIZE(fred_frame) > 0 ? (2 * 8) : 0;
BZERO(regs, sizeof(*regs));
@@ -1854,7 +1856,7 @@ static int genregs_get(struct task_context *target,
*/
pt_regs_buf = GETBUF(SIZE(pt_regs));
- readmem(machdep->get_stacktop(target->task) - SIZE(pt_regs), KVADDR,
+ readmem(machdep->get_stacktop(target->task) - padding_size - SIZE(pt_regs), KVADDR,
pt_regs_buf, SIZE(pt_regs), "genregs_get: pt_regs",
gcore_verbose_error_handle());
@@ -2188,6 +2190,7 @@ static int genregs_get32(struct task_context *target,
struct user_regs_struct *regs = (struct user_regs_struct *)buf;
char *pt_regs_buf;
ulonglong pt_regs_addr;
+ ulong padding_size = VALID_SIZE(fred_frame) > 0 ? (2 * 8) : 0;
if (is_task_active(target->task) && KVMDUMP_DUMPFILE()) {
get_regs_from_kvmdump_notes(target, regs);
@@ -2198,7 +2201,7 @@ static int genregs_get32(struct task_context *target,
pt_regs_buf = GETBUF(SIZE(pt_regs));
- pt_regs_addr = machdep->get_stacktop(target->task) - SIZE(pt_regs);
+ pt_regs_addr = machdep->get_stacktop(target->task) - padding_size - SIZE(pt_regs);
/*
* The commit 07b047fc2466249aff7cdb23fa0b0955a7a00d48
--
2.47.0