Issue #10 resolved

readBytes() failed on forked process

svinota
created an issue

readBytes() returns an empty string, when operates on a forked process.

How reproducible: always

How to reproduce:

add readBytes() to strace.py and run a bash script

$ diff /usr/bin/strace.py ./strace.py 
187c187,198
<             self.displaySyscall(syscall)
---
>             if syscall.name in ('recvmsg', 'sendmsg'):
>                 # get msghdr
>                 addr = syscall.arguments[1].value
>                 # read at some bytes
>                 # actually, we should read struct msghdr, but
>                 # for the testcase it is enough to read at least one
>                 length = 1
>                 data = process.readBytes(addr, length)
>                 if not data:
>                     print "read failed -- starting debugger"
>                     import pdb
>                     pdb.set_trace()
$ cat test.sh 
#!/bin/bash

ip ad
$ python ./strace.py -f ./test.sh
execve(/home/peet/Projects/pyroute2/test.sh, ['/home/peet/Projects/pyroute2/test.sh'], [/* 40 vars */]) = 5669
*** New process 5670 ***
*** New process 5671 ***
[5671] exit_group(0)
*** Process 5671 exited normally ***
------------------------------------------------------------
PID: 5670
Signal: SIGCHLD
Child process 5671 exited normally
Signal sent by user 1000
------------------------------------------------------------
[5670] exit_group(0)
*** Process 5670 exited normally ***
------------------------------------------------------------
PID: 5669
Signal: SIGCHLD
Child process 5670 exited normally
Signal sent by user 1000
------------------------------------------------------------
*** New process 5672 ***
*** New process 5673 ***
[5673] exit_group(0)
*** Process 5673 exited normally ***
------------------------------------------------------------
PID: 5672
Signal: SIGCHLD
Child process 5673 exited normally
Signal sent by user 1000
------------------------------------------------------------
[5672] exit_group(0)
*** Process 5672 exited normally ***
------------------------------------------------------------
PID: 5669
Signal: SIGCHLD
Child process 5672 exited normally
Signal sent by user 1000
------------------------------------------------------------
*** New process 5674 ***
*** New process 5675 ***
[5675] exit_group(0)
*** Process 5675 exited normally ***
------------------------------------------------------------
PID: 5674
Signal: SIGCHLD
Child process 5675 exited normally
Signal sent by user 1000
------------------------------------------------------------
[5674] exit_group(0)
*** Process 5674 exited normally ***
------------------------------------------------------------
PID: 5669
Signal: SIGCHLD
Child process 5674 exited normally
Signal sent by user 1000
------------------------------------------------------------
*** New process 5676 ***
*** New process 5677 ***
[5677] exit_group(1)
*** Process 5677 exited with code 1 ***
------------------------------------------------------------
PID: 5676
Signal: SIGCHLD
Child process 5677 killed by signal SIGHUP
Signal sent by user 1000
------------------------------------------------------------
[5676] exit_group(0)
*** Process 5676 exited normally ***
------------------------------------------------------------
PID: 5669
Signal: SIGCHLD
Child process 5676 exited normally
Signal sent by user 1000
------------------------------------------------------------
*** New process 5678 ***
read failed -- starting debugger
> /home/peet/Projects/pyroute2/strace.py(201)syscall()
-> process.syscall()
(Pdb) addr
140736183873504L
(Pdb) process.readBytes(addr, 1)
''
(Pdb) 

SELinux state: permissive

$ getenforce 
Permissive

This issue is really a blocker, since only single processes can be straced to get syscall data.

Comments (3)

  1. Victor Stinner repo owner

    The issue is in PtraceProcess.readBytes(). I don't understand why read /proc/pid/mem doesn't work with fork. It may be related to SELinux?

    Edit ptrace/debugger/process.py to add "HAS_PROC=True" just before "class PtraceProcess(object)", so the ptrace() syscall will be used to read memory instead /proc/pid/mem file. It works using ptrace() syscall, but it's much slower.

  2. Log in to comment