1

I need to run another process that needs to ptrace() its inferior. But also gdb needs to ptrace() the same inferior as well, so this will lead to chaos.

The first and obvious solution that came to my mind was to detach the gdb whenever the other process needs to access the inferior and then attach again. However, this is also problematic when the inferior is stopped for debugging.

Then I tried to launch the other process from gdb using gdb's shell command thinking maybe it can work if gdb executes the other process as its child. But even when gdb executes it as a child, they'll have different PIDs, so the problem still continues.

Is it possible to make gdb and the other process look like they share the same PID so they can attach to the same inferior?

janw
  • 8,758
  • 11
  • 40
  • 62
Korcan Karaokçu
  • 467
  • 4
  • 18
  • Linux [prohibits](http://lxr.free-electrons.com/source/kernel/ptrace.c#L172) two processes from invoking `ptrace` on the same target. What are you trying to accomplish, exactly? – Michael Foukarakis Feb 17 '16 at 14:23
  • I want to run scanmem along with gdb to do some basic memory searching. I also tried to use gdb's `find` command to do it but it's too slow. – Korcan Karaokçu Feb 17 '16 at 14:32

3 Answers3

3

No, there's no way to do this.

Your best bet is to add new code to gdb to do what you want.

Tom Tromey
  • 21,507
  • 2
  • 45
  • 63
  • I see, this was the comment I was afraid of getting. Welp, it seems like I have no option left other than hacking into the gdb. Time to learn something brand new(and scary). – Korcan Karaokçu Feb 17 '16 at 15:30
2

It is not completely impossible. Just very very very difficult. Probably more difficult than it's worth (i.e. - than hacking gdb). It is, however, what fakeroot-ng does in order to allow strace to work.

The idea is that, if you run both your target process and gdb traced by the same debugger, you can emulate the ptrace calls done by gdb, and perform them yourself. The result is that gdb thinks it is tracing your child process, but you are, in fact, the one tracing it in practice.

Like I said above, this apprach is, in no way, simpler than hacking gdb to just do what you want.

Shachar Shemesh
  • 8,193
  • 6
  • 25
  • 57
0

Solution 1: do not use ptrace

In recent versions of Linux (since 3.2), a process can read/write another process memory without ptracing it first:

  • either by open/read/write-ing /proc/$pid/mem (before Linux 3.2, it was only possible to read from this file when the target process was stopped but since Linux 3.2 you do not need to stop the target process);

  • or using the new system calls process_vm_readv() and process_vm_write().

scanmem could be adapted to avoid ptracing the target process and use those methods instead. As scanmem only uses PTRACE_ATTACH, PTRACE_DETACH, PTRACE_PEEKDATA and and PTRACE_POKEDATA, it should be possible to simply write a ptrace-less version.

Solution 2: GDB server

Summary:

[GDB] ----------> [ tracer ] ---> [ traced ]
      GDB protocol          ptrace

You have three processes:

  • the GDB process;

  • the (other) tracer process;

  • the traced process.

The idea is that GDB does not ptrace the traced process itself.

Instead, you want to modify the tracer in order to expose a gdbserver-like interface to GDB using the GDB protocol. Instead of tracing the traced process, GDB connects to the tracer which can do the operations on the tracer on behalf of GDB.

This means that the tracer must manage its ptrace operations in order to do both the GDB stuff and its own stuff which is probably not an easy task.

This second solution is way too complex/overkill for what you cant to achieve however.

ysdx
  • 8,889
  • 1
  • 38
  • 51
  • It seems that scanmem uses ptrace. Can you point to how to get access to another process' memory without ptrace at all? – Shachar Shemesh Jun 27 '16 at 07:40
  • A simple example, is this program (https://github.com/randomstuff/unjit) I wrote which reads JIT-compiled code from another process without ptrace-ing it and disassemble it (https://github.com/randomstuff/unjit/blob/bbb84dc3ae67991dc77a0e8019d17e247e84a168/src/Disassembler.cpp#L104). – ysdx Jun 27 '16 at 07:57
  • Is there a reason you don't simply point to the syscall/proc file/whatever that was added in Linux version 3.2 that allows to do it? From reading your code, all i can see is that you use libelf to load the ELF file a given process uses, which would, of course, allow you to disassemble it, but that's not reading another process' address space. – Shachar Shemesh Jun 27 '16 at 08:41
  • The second link points to a call to `process_vm_readv` which is the system call we are talking about :) – ysdx Jun 27 '16 at 09:11
  • Updated the answer. – ysdx Jun 27 '16 at 09:13
  • AFAIK, reading from /proc/pid/mem required you to be the process' debugger. That requirement may have been relaxed, maybe in 3.2, but I don't think that "stopped" was a sufficient requirement. – Shachar Shemesh Jun 27 '16 at 10:01
  • Yes, AFAIR you needed to be ptrace-stop it yourself (at least that was sufficient) but it's not necessary anymore. – ysdx Jun 27 '16 at 10:14