termux-packages icon indicating copy to clipboard operation
termux-packages copied to clipboard

GDBserver x86_64 issue and a possible solution

Open alex-curiou opened this issue 5 years ago • 6 comments

Problem description

When You try to attach the gdbserver to a running process as a root from a shell the server quits with a message: "stack corruption detected Aborted"

Steps to reproduce

  1. Connect to a x86_64 emulator by 'adb shell';
  2. become root;
  3. Try to attach to any running process with by PID (for example 5432): /data/data/com.termux/files/usr/bin/gdbserver --attach :23945 5432 or try to start any process to debug /data/data/com.termux/files/usr/bin/gdbserver :23945 /data/data/com.termux/files/usr/bin/less
  4. The server fails to start with the message: stack corruption detected Aborted

Expected behavior

The server attaches to the process with the given PID: Attached; pid = 7734 Listening on port 23945

or (for the case when the process is started by gdbserver) Process /data/data/com.termux/files/usr/bin/less created; pid = 7674 Listening on port 23945

Additional information

gdbserver during startup calls function void linux_ptrace_test_ret_to_nx(void) (from nat/linux-ptrace.c): ... elf_gregset_t regs; ... if (ptrace (PTRACE_GETREGS, child, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) &regs) < 0) ...

And elf_gregset_t is a typedef of an array of 23 elements and the kernel returns 27 elements. There are also additional usages of this typedef in GDB server.

The issue is because of NDK's sysroot/usr/include/sys/procfs.h. Just to compare. The NDK r21d version of sys/procfs.h ... #include <sys/ucontext.h> __BEGIN_DECLS typedef unsigned long elf_greg_t; typedef elf_greg_t elf_gregset_t[NGREG]; ...

GNU version bits/procfs.h (from my current Ubuntu installation) ... /* And the whole bunch of them. We could have used `struct user_regs_struct' directly in the typedef, but tradition says that the register set is an array, which does have some peculiar semantics, so leave it that way. */ #define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof (elf_greg_t)) typedef elf_greg_t elf_gregset_t[ELF_NGREG]; ...

One way to fix it is to patch the NDK's sysroot/usr/include/sys/procfs.h before the build ... typedef unsigned long elf_greg_t; #if defined(__x86_64__) #define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) typedef elf_greg_t elf_gregset_t[ELF_NGREG]; #else typedef elf_greg_t elf_gregset_t[NGREG]; #endif ...

alex-curiou avatar Sep 03 '20 16:09 alex-curiou

One way to fix it is to patch the NDK's sysroot/usr/include/sys/procfs.h before the build

Note that if Bionic libc uses elf_greg_t somewhere internally, changing its size in header files may cause further issues.

Headers, especially type definitions, must correspond to ones used by libc internally.

ghost avatar Sep 03 '20 16:09 ghost

may cause further issues

Yes I understand it. That's why it is "a possible solution". Any additional solutions are welcome. Usually there is a self-test suit to test a GNU package. Other way is to dig deep inside and to check the flow. This is GNU package to work with GNU kernel. And kernel returns from arch/x86/kernel/ptrace.c

        case PTRACE_GETREGS:
          return copy_regset_to_user (
              child, task_user_regset_view (get_current ()),
              REGSET_GENERAL, 0, sizeof(struct user_regs_struct), datap);

and sizeof(struct user_regs_struct) comes from arch/x86/include/asm/user_64.h

    struct user_regs_struct
    {
      unsigned long r15;
      unsigned long r14;
      unsigned long r13;
      unsigned long r12;
      unsigned long bp;
      unsigned long bx;
      unsigned long r11;
      unsigned long r10;
      unsigned long r9;
      unsigned long r8;
      unsigned long ax;
      unsigned long cx;
      unsigned long dx;
      unsigned long si;
      unsigned long di;
      unsigned long orig_ax;
      unsigned long ip;
      unsigned long cs;
      unsigned long flags;
      unsigned long sp;
      unsigned long ss;
      unsigned long fs_base;
      unsigned long gs_base;
      unsigned long ds;
      unsigned long es;
      unsigned long fs;
      unsigned long gs;
    };

alex-curiou avatar Sep 03 '20 17:09 alex-curiou

And as addition: now the gdbserver for x86_64 does not work at all. And nobody can test it on Android x86_64. And if we have a working version we can see feedback from community.

alex-curiou avatar Sep 03 '20 17:09 alex-curiou

Well I've reported a bug to NDK team. So we can check https://android-review.googlesource.com/c/platform/bionic/+/1419433

alex-curiou avatar Sep 03 '20 20:09 alex-curiou

The changes have been merged to fix the issue:

--- a/libc/include/sys/procfs.h
+++ b/libc/include/sys/procfs.h
@@ -26,16 +26,24 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _SYS_PROCFS_H_
-#define _SYS_PROCFS_H_
+#pragma once
 
 #include <sys/cdefs.h>
+#include <sys/ptrace.h>
 #include <sys/ucontext.h>
 
 __BEGIN_DECLS
 
+#if defined(__arm__)
+#define ELF_NGREG (sizeof(struct user_regs) / sizeof(elf_greg_t))
+#elif defined(__aarch64__)
+#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
+#else
+#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+#endif
+
 typedef unsigned long elf_greg_t;
-typedef elf_greg_t elf_gregset_t[NGREG];
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
 typedef fpregset_t elf_fpregset_t;
 
@@ -58,5 +66,3 @@
 #define ELF_PRARGSZ 80
 
 __END_DECLS
-
-#endif

The fix will be in NDK r22.

And we can apply the solution now to solve the startup issue for x86_64.

alex-curiou avatar Sep 10 '20 10:09 alex-curiou

This issue/PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Nov 18 '21 18:11 stale[bot]

Ref https://github.com/android/ndk/issues/1347

Closing. We already are using NDK r26b.

The aforementioned patch has been applied in upstream: https://android.googlesource.com/toolchain/prebuilts/ndk/r26/+/refs/heads/main/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/sys/procfs.h

truboxl avatar Nov 17 '23 10:11 truboxl