[LTP] [PATCH v3 2/2] ptrace07: fix the broken case caused by hardcoded xstate size
Pengfei Xu
pengfei.xu@intel.com
Tue Oct 18 14:10:47 CEST 2022
Should not use a hardcoded xstate size(512 * 8 = 4096 bytes), and use maximum
XSAVE size specified by CPUID.(EAX=0DH, ECX=0H):EBX instead.
If the CPU's maximum XSAVE size exceeds the hard-coded xstate size 4096 bytes,
it will cause the ptrace07 case to break as below:
"
./ptrace07
tst_test.c:1528: TINFO: Timeout per run is 0h 00m 30s
ptrace07.c:142: TBROK: PTRACE_SETREGSET failed with unexpected error: EFAULT (14)
tst_test.c:1571: TINFO: Killed the leftover descendant processes
Summary:
passed 0
failed 0
broken 1
skipped 0
warnings 0
"
Reported-by: Eric DeVolder <eric.devolder@oracle.com>
Reviewed-by: Chang S. Bae <chang.seok.bae@intel.com>
Signed-off-by: Pengfei Xu <pengfei.xu@intel.com>
---
testcases/kernel/syscalls/ptrace/ptrace07.c | 29 ++++++++++++++++++---
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/testcases/kernel/syscalls/ptrace/ptrace07.c b/testcases/kernel/syscalls/ptrace/ptrace07.c
index da62cadb0..c2c2ad77c 100644
--- a/testcases/kernel/syscalls/ptrace/ptrace07.c
+++ b/testcases/kernel/syscalls/ptrace/ptrace07.c
@@ -35,6 +35,7 @@
#include "config.h"
#include "ptrace.h"
#include "tst_test.h"
+#include "cpuid.h"
#ifndef PTRACE_GETREGSET
# define PTRACE_GETREGSET 0x4204
@@ -48,6 +49,8 @@
# define NT_X86_XSTATE 0x202
#endif
+#define CPUID_LEAF_XSTATE 0xd
+
static void check_regs_loop(uint32_t initval)
{
const unsigned long num_iters = 1000000000;
@@ -83,11 +86,22 @@ static void do_test(void)
int i;
int num_cpus = tst_ncpus();
pid_t pid;
- uint64_t xstate[512];
- struct iovec iov = { .iov_base = xstate, .iov_len = sizeof(xstate) };
+ uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+ uint64_t *xstate;
+ /*
+ * CPUID.(EAX=0DH, ECX=0H):EBX: maximum size (bytes, from the beginning
+ * of the XSAVE/XRSTOR save area) required by enabled features in XCR0.
+ */
+ __cpuid_count(CPUID_LEAF_XSTATE, ecx, eax, ebx, ecx, edx);
+ xstate = aligned_alloc(64, ebx);
+ struct iovec iov = { .iov_base = xstate, .iov_len = ebx };
int status;
bool okay;
+ if (!xstate)
+ tst_brk(TBROK, "aligned_alloc() failed for xstate buffer");
+ tst_res(TINFO, "CPUID.(EAX=%u, ECX=0):EAX=%u, EBX=%u, ECX=%u, EDX=%u",
+ CPUID_LEAF_XSTATE, eax, ebx, ecx, edx);
pid = SAFE_FORK();
if (pid == 0) {
TST_CHECKPOINT_WAKE(0);
@@ -102,12 +116,15 @@ static void do_test(void)
sched_yield();
TEST(ptrace(PTRACE_ATTACH, pid, 0, 0));
- if (TST_RET != 0)
+ if (TST_RET != 0) {
+ free(xstate);
tst_brk(TBROK | TTERRNO, "PTRACE_ATTACH failed");
+ }
SAFE_WAITPID(pid, NULL, 0);
TEST(ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov));
if (TST_RET != 0) {
+ free(xstate);
if (TST_ERR == EIO)
tst_brk(TCONF, "GETREGSET/SETREGSET is unsupported");
@@ -138,6 +155,7 @@ static void do_test(void)
tst_res(TINFO,
"PTRACE_SETREGSET with reserved bits failed with EINVAL");
} else {
+ free(xstate);
tst_brk(TBROK | TTERRNO,
"PTRACE_SETREGSET failed with unexpected error");
}
@@ -152,8 +170,10 @@ static void do_test(void)
* worry about potential stops after this point.
*/
TEST(ptrace(PTRACE_DETACH, pid, 0, 0));
- if (TST_RET != 0)
+ if (TST_RET != 0) {
+ free(xstate);
tst_brk(TBROK | TTERRNO, "PTRACE_DETACH failed");
+ }
/* If child 'pid' crashes, only report it as info. */
SAFE_WAITPID(pid, &status, 0);
@@ -173,6 +193,7 @@ static void do_test(void)
}
if (okay)
tst_res(TPASS, "wasn't able to set invalid FPU state");
+ free(xstate);
}
static struct tst_test test = {
--
2.31.1
More information about the ltp
mailing list