strace/0183-syscall-do-not-use-uninitialized-parts-of-struct-ptr.patch

103 lines
3.0 KiB
Diff
Raw Permalink Normal View History

From c7e0ea6d712eb214dafe7e9eae57661d9a427ea7 Mon Sep 17 00:00:00 2001
From: "Dmitry V. Levin" <ldv@strace.io>
Date: Mon, 28 Oct 2024 08:00:00 +0000
Subject: [PATCH 183/185] syscall: do not use uninitialized parts of struct
ptrace_syscall_info
* src/syscall.c (ptrace_syscall_info_is_entry,
ptrace_syscall_info_is_exit): New functions.
(get_scno): Replace ptrace_syscall_info_is_valid() with
ptrace_syscall_info_is_entry().
(get_error): Replace ptrace_syscall_info_is_valid() with
ptrace_syscall_info_is_exit().
(get_syscall_regs): Fall back to get_regs() if strace_get_syscall_info()
succeeded but couldn't obtain the necessary data.
Resolves: https://github.com/strace/strace/issues/322
---
src/syscall.c | 40 +++++++++++++++++++++++++++++++++++-----
1 file changed, 35 insertions(+), 5 deletions(-)
diff --git a/src/syscall.c b/src/syscall.c
index a6692721a..1f4d86dc1 100644
--- a/src/syscall.c
+++ b/src/syscall.c
@@ -1082,6 +1082,21 @@ ptrace_syscall_info_is_valid(void)
ptrace_sci.op <= PTRACE_SYSCALL_INFO_SECCOMP;
}
+static bool
+ptrace_syscall_info_is_entry(void)
+{
+ return ptrace_get_syscall_info_supported &&
+ (ptrace_sci.op == PTRACE_SYSCALL_INFO_ENTRY ||
+ ptrace_sci.op == PTRACE_SYSCALL_INFO_SECCOMP);
+}
+
+static bool
+ptrace_syscall_info_is_exit(void)
+{
+ return ptrace_get_syscall_info_supported &&
+ ptrace_sci.op == PTRACE_SYSCALL_INFO_EXIT;
+}
+
#define XLAT_MACROS_ONLY
#include "xlat/nt_descriptor_types.h"
#undef XLAT_MACROS_ONLY
@@ -1376,8 +1391,23 @@ get_syscall_regs(struct tcb *tcp)
if (get_regs_error != -1)
return get_regs_error;
- if (ptrace_get_syscall_info_supported)
- return strace_get_syscall_info(tcp) ? 0 : get_regs_error;
+ if (ptrace_get_syscall_info_supported) {
+ if (!strace_get_syscall_info(tcp))
+ return get_regs_error;
+
+ if ((entering(tcp) && ptrace_syscall_info_is_entry()) ||
+ (exiting(tcp) && ptrace_syscall_info_is_exit()))
+ return 0;
+
+ /*
+ * PTRACE_GET_SYSCALL_INFO succeeded but didn't help,
+ * falling back to get_regs().
+ *
+ * This can happen when get_syscall_regs() is called
+ * from startup_tcb() via get_scno().
+ */
+ debug_func_msg("ptrace_sci.op = %d", ptrace_sci.op);
+ }
return get_regs(tcp);
}
@@ -1408,7 +1438,7 @@ get_scno(struct tcb *tcp)
if (get_syscall_regs(tcp) < 0)
return -1;
- if (ptrace_syscall_info_is_valid()) {
+ if (ptrace_syscall_info_is_entry()) {
/* Apply arch-specific workarounds. */
int rc = arch_check_scno(tcp);
if (rc != 1)
@@ -1456,7 +1486,7 @@ get_scno(struct tcb *tcp)
static int
get_syscall_args(struct tcb *tcp)
{
- if (ptrace_syscall_info_is_valid()) {
+ if (ptrace_syscall_info_is_entry()) {
const unsigned int n =
MIN(ARRAY_SIZE(tcp->u_arg),
ARRAY_SIZE(ptrace_sci.entry.args));
@@ -1507,7 +1537,7 @@ get_syscall_result(struct tcb *tcp)
static void
get_error(struct tcb *tcp, const bool check_errno)
{
- if (ptrace_syscall_info_is_valid()) {
+ if (ptrace_syscall_info_is_exit()) {
if (ptrace_sci.exit.is_error) {
tcp->u_rval = -1;
tcp->u_error = -ptrace_sci.exit.rval;
--
2.13.6