vstinner / python-ptrace Goto Github PK
View Code? Open in Web Editor NEWpython-ptrace is a Python binding of ptrace library.
Home Page: http://python-ptrace.readthedocs.io/
License: GNU General Public License v2.0
python-ptrace is a Python binding of ptrace library.
Home Page: http://python-ptrace.readthedocs.io/
License: GNU General Public License v2.0
Hi! 👋
On Arch Linux we have recently switched to becoming more specific about the licenses upstreams are using. For this we rely on SPDX license identifiers.
https://rfc.archlinux.page/0016-spdx-license-identifiers/
This project carries a GPL-2.0 license file but does not state whether this is GPL-2.0-only
or GPL-2.0-or-later
.
Usually, if there are no additional infos one would err on the side of caution and default to GPL-2.0-only
, but maybe there is some discussion or piece of information I am missing.
I'd be happy about further input from your side on this topic! :)
cc @anthraxx (package maintainer)
I can't figure out how to detach from a process, preventing me from later re-attaching:
Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ptrace.debugger
>>> debugger = ptrace.debugger.PtraceDebugger()
>>> process = debugger.addProcess(485, False)
>>> process.readBytes(0x00673364, 4)
';\xaa4\x1d'
>>> debugger.deleteProcess(process)
>>> debugger.quit()
>>> process = debugger.addProcess(485, False)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/ptrace/debugger/debugger.py", line 74, in addProcess
process = PtraceProcess(self, pid, is_attached, parent=parent)
File "/usr/lib/python2.7/dist-packages/ptrace/debugger/process.py", line 167, in __init__
self.attach()
File "/usr/lib/python2.7/dist-packages/ptrace/debugger/process.py", line 184, in attach
ptrace_attach(self.pid)
File "/usr/lib/python2.7/dist-packages/ptrace/binding/func.py", line 157, in ptrace_attach
ptrace(PTRACE_ATTACH, pid)
File "/usr/lib/python2.7/dist-packages/ptrace/binding/func.py", line 150, in ptrace
raise PtraceError(message, errno=errno, pid=pid)
ptrace.error.PtraceError: ptrace(cmd=16, pid=485, 0, 0) error #1: Operation not permitted
when I use "strace.py -f " to tracing ansible apt module, it throw me a bug that system call breaks. I used gdb to debug but couldn't attach on the proess. Using ps to check process I found that python-ptrace was still monitoring the ansible module, So I killed the forks, and the ptrace received an interrupt siginal.
I am curious about why adding the argument "-f " may lead the python-ptrace program getting stuck?
Originally reported by: gfxmonk (Bitbucket: gfxmonk, GitHub: gfxmonk)
I'm ptracing a process, and using readCString to get the filename argument for certain file-related syscalls.
Under the hood, this uses process.readBytes. In my case (linux 3.15.4, fedora 20) HAS_PTRACE_IO is False, and HAS_PROC is True - so it's using the /proc//mem method to read bytes from the process.
I copied this function into my source so I could mess with it, and I've found that in some case (I can't figure out why or when), mem.read() returns the empty string (a.k.a EOF).
When this happens, the surrounding readCString function just keeps reading empty chunks until it thinks it's hit the max_size limit, at which point it returns an empty string and claims that truncated
is true. Which is itself kind of weird, it might be better if readBytes just raised EOFError when mem.read(size) returns the empty string.
But the real confusion is why I'm getting EOF on /dev/pid/mem in the first place. If I change the code of process.readBytes to include the following retry code:
try:
mem = self.read_mem_file
mem.seek(address)
rv = mem.read(size)
if not rv:
mem = self.read_mem_file = open(self.read_mem_file.name, 'rb', 0)
mem.seek(address)
rv = mem.read(size)
return rv
[ ... ]
Then bizzarely, it works - that is, even though I've just got an EOF when reading byte XYZ of /dev/pid/mem, reopening that exact same file and seeking to the same location gives me some contents.
I poked around in lsof
to check that /dev/pid/mem isn't changing inode between when it was first opened and when it gives an EOF, and it doesn't seem to be.
I also attached an strace
to the python process that's running the ptrace code, and saw that it really does do a:
read(5, "", 256) = 0
(5 is the FD for the pid's memory file)
So it's not python returning preemptively with an EOF, it's the OS. I can't figure out why. I had never heard of /dev/pid/mem before, so perhaps you might know why it might behave trhis way?
Originally reported by: Anonymous
Solution:
Add #include <sys/types.h> to cptrace/cptrace.c
When building on openSUSE:Tumbleweed build fails in testsuite:
https://build.opensuse.org/public/build/openSUSE:Factory/standard/x86_64/python-python-ptrace/_log
Originally reported by: Felipe Prenholato (Bitbucket: chronossc, GitHub: chronossc)
I have a install of pythonbrew with Python 2.6.8 (without SSLv2 support) for running old applications.
This install runs Django 1.2.1.
When trying to run Django 1.2.1 server or shell, I ends with a error "UNKNOW OS!".
I checked and that happens because ptrace.os_tools don't recognize linux3 platform as Linux.
To make it work I changed code in following way:
#!diff
--- os_tools.py_original 2012-08-04 01:29:03.985275595 -0300
+++ os_tools.py 2012-08-04 01:28:55.305275224 -0300
@@ -17,7 +17,7 @@
RUNNING_PYTHON3 = version_info[0] == 3
RUNNING_PYPY = ("pypy" in version.lower())
RUNNING_WINDOWS = (platform == 'win32')
-RUNNING_LINUX = (platform == 'linux2')
+RUNNING_LINUX = (platform in ('linux2', 'linux3'))
RUNNING_FREEBSD = (platform.startswith('freebsd')
or platform.startswith('gnukfreebsd'))
RUNNING_OPENBSD = platform.startswith('openbsd')
Originally reported by: muflone (Bitbucket: muflone, GitHub: muflone)
Hi
Many syscalls (rt_sigreturn, pread64, pwrite64, mremap) lack of their prototype in the SYSCALL_PROTOTYPES list.
Is there any reason for this lacking?
If not, can I provide you a whole list of prototypes to add in prototypes.py?
Any hints to properly populate it?
Hi, I'm trying to track the process containerd, but I always get no output.
I used the following command, which did not produce any output:
sudo python3 strace.py -f -p 1363
I also tried the example in the documentation and rewrote it to:
import signal
import ptrace.debugger
def debugger_example(pid):
debugger = ptrace.debugger.PtraceDebugger()
print("Attach the running process %s" % pid)
process = debugger.addProcess(pid, False)
# process is a PtraceProcess instance
print("IP before: %#x" % process.getInstrPointer())
print("Execute a single step")
process.singleStep()
# singleStep() gives back control to the process. We have to wait
# until the process is trapped again to retrieve the control on the
# process.
process.waitSignals(signal.SIGTRAP)
print("IP after: %#x" % process.getInstrPointer())
process.detach()
debugger.quit()
def main():
debugger_example(1363)
if __name__ == "__main__":
main()
The error obtained is the following,
/home/zzc/Desktop/zzc/python3.6_sudo.sh /home/zzc/Desktop/zzc/python-ptrace/zzc-test.py
Attach the running process 1363
Traceback (most recent call last):
File "/home/zzc/Desktop/zzc/python-ptrace/zzc-test.py", line 30, in <module>
main()
File "/home/zzc/Desktop/zzc/python-ptrace/zzc-test.py", line 26, in main
debugger_example(1363)
File "/home/zzc/Desktop/zzc/python-ptrace/zzc-test.py", line 10, in debugger_example
process = debugger.addProcess(pid, False)
File "/home/zzc/Desktop/zzc/python-ptrace/ptrace/debugger/debugger.py", line 83, in addProcess
parent=parent, is_thread=is_thread)
File "/home/zzc/Desktop/zzc/python-ptrace/ptrace/debugger/process.py", line 172, in __init__
self.attach()
File "/home/zzc/Desktop/zzc/python-ptrace/ptrace/debugger/process.py", line 189, in attach
ptrace_attach(self.pid)
File "/home/zzc/Desktop/zzc/python-ptrace/ptrace/binding/func.py", line 177, in ptrace_attach
ptrace(PTRACE_ATTACH, pid)
File "/home/zzc/Desktop/zzc/python-ptrace/ptrace/binding/func.py", line 168, in ptrace
raise PtraceError(message, errno=errno, pid=pid)
ptrace.error.PtraceError: ptrace(cmd=16, pid=1363, 0, 0) error #1: Operation not permitted
Process finished with exit code 1
I want to know what I should do.
Originally reported by: Peter Saveliev (Bitbucket: svinota, GitHub: svinota)
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.
Hello i having weird error,
but I can see it in https://github.com/haypo/python-ptrace/blob/master/ptrace/binding/linux_struct.py#L16
any idea? is the 0.9.2 version installed with easy_install
Thanks
I apologize if this is an ignorant question. I have a parent process which spawns two children and I need one of the children (created via multiprocessing
) to be able to ptrace the other (started via subprocess.Popen
) but I am recieving the permission error: ptrace.error.PtraceError: ptrace(cmd=16, pid=15151, 0, 0) error #1: Operation not permitted
Here is sample code that demonstrates what I am trying to do and the error I am encountering:
import multiprocessing
import subprocess
import time
import ptrace.debugger
def ptrace_test(pid):
debugger = ptrace.debugger.PtraceDebugger()
process = debugger.addProcess(pid, False)
# Other stuff
child = subprocess.Popen("/usr/bin/ls")
proc = multiprocessing.Process(target=ptrace_test, args=(child.pid,))
proc.start()
proc.join()
Originally reported by: Pavel Šimerda (Bitbucket: pavlix, GitHub: pavlix)
For a network application testing project, I need to ptrace both client and server processes but tracing the SSH server apparently fails. So I also tried with strace.py
and it quits with a traceback.
Reproducer:
Run the two comments in two terminal emulators alpha and beta. The behavior seems to be the same whether you make sure the SSH authentication succeeds or no.
alpha# ./strace.py -f -o trace.python-ptrace -- which sshd
-D
beta$ ssh localhost true
Expected result:
With -D option, SSH server should run until you kill it and accept any incoming connections.
Actual result:
The first connection results in crashing the server with a traceback.
Trying to _analyze() or display() a ProcessSignal of type SIGSEGV raised by a "RET" condition currently raises an Exception, as the current instruction handler has no detection for the RET opcode.
This segfault signal can be raised when an invalid address is at the top of the stack, then a RET is executed looking to pop the value into RIP. This is a valuable use-case for detecting buffer overflows / attempted RET2Libc attacks in binaries without stack protection canaries
Originally reported by: Luca Clementi (Bitbucket: lclementi, GitHub: lclementi)
If you apply the patch below to your strace.py it will block indefinitely.
I think it is a problem connected with the (clone/fork) where the two process get stuck waiting for each other.
The problem sees in ptrace/debugger/debugger.py at the function:
def addProcess(self, pid, is_attached, parent=None):
Do you have any suggestion on where to look?
Luca
#!diff
--- strace.py 2013-02-28 18:59:07.268588674 -0800
+++ strace.py.modified 2013-02-28 18:59:01.356588768 -0800
@@ -12,6 +12,7 @@
from ptrace.compatibility import any
from ptrace.error import PTRACE_ERRORS, writeError
from ptrace.ctypes_tools import formatAddress
+import ptrace
import re
class SyscallTracer(Application):
@@ -73,6 +74,9 @@
self.createLogOptions(parser)
self.options, self.program = parser.parse_args()
+ self.program = ["bash","-c","/usr/bin/find /tmp &> /dev/null "]
+ self.program[0] = ptrace.tools.locateProgram(self.program[0])
+
if self.options.list_syscalls:
syscalls = SYSCALL_NAMES.items()
Originally reported by: Pavel Šimerda (Bitbucket: pavlix, GitHub: pavlix)
I found a number of issues when using python-ptrace in my network-testing project, collected tracebacks and prepared patches for all of them. You can find all details in the patch files.
Originally reported by: Peter Saveliev (Bitbucket: svinota, GitHub: svinota)
From time to time, using strace.py -f cmd
, I get somethig like that:
[2506] rt_sigprocmask(SIG_SETMASK, <sigset=()>, NULL, 8) = 0
[2511] rt_sigaction(SIGTSTP, 0x00007fffdcd78370, 0x00007fffdcd78410, 8) = 0
[2506] rt_sigaction(SIGCHLD, 0x00007fffdcd784d0, 0x00007fffdcd78570, 8) = 0
[2511] rt_sigaction(SIGTTIN, 0x00007fffdcd78370, 0x00007fffdcd78410, 8) = 0
[2506] close(4) = 0
[2511] rt_sigaction(SIGTTOU, 0x00007fffdcd78380, 0x00007fffdcd78420, 8) = 0
[2511] rt_sigaction(SIGINT, 0x00007fffdcd784a0, 0x00007fffdcd78540, 8) = 0
[2511] rt_sigaction(SIGQUIT, 0x00007fffdcd784a0, 0x00007fffdcd78540, 8) = 0
[2511] rt_sigaction(SIGCHLD, 0x00007fffdcd784a0, 0x00007fffdcd78540, 8) = 0
[2511] rt_sigaction(SIGCHLD, 0x00007fffdcd784d0, 0x00007fffdcd78570, 8) = 0
[2511] rt_sigaction(SIGINT, 0x00007fffdcd784d0, 0x00007fffdcd78570, 8) = 0
[2511] dup2(4, 1) = 1
[2511] close(4) = 0
[2511] close(3) = 0
[2511] rt_sigprocmask(SIG_BLOCK, NULL, <sigset=()>, 8) = 0
[2511] rt_sigprocmask(SIG_BLOCK, NULL, <sigset=()>, 8) = 0
[2511] rt_sigprocmask(SIG_BLOCK, NULL, <sigset=()>, 8) = 0
[2511] rt_sigprocmask(SIG_BLOCK, <sigset=(SIGINT, SIGCHLD)>, <sigset=()>, 8) = 0
waitpid() warning: Unknown PID 2512
At this point strace hangs until Ctrl-C.
Traced file — a testcase for tracing forked processes:
#!/bin/bash
ip ad
How reproducible: possibility ~0.3
How to reproduce:
$ strace.py -f ./test.sh
Possibly, some race condition.
Originally reported by: Anonymous
When I try to run strace.py with a 32bits program in Ubuntu Linux x64 I get the following message:
Format argument filename of function lstat() value error: [ProcessError] readBytes(0x0000000000000003, 256) error: [Errno 5] Input/output error
Traceback (most recent call last):
File "/the/path/python-ptrace/ptrace/func_arg.py", line 31, in getText
text = self.createText()
File "/the/path/python-ptrace/ptrace/syscall/syscall_argument.py", line 106, in createText
return self.readCString(value)
File "/the/path/python-ptrace/ptrace/syscall/syscall_argument.py", line 183, in readCString
char, truncated = self.function.process.readCString(address, max_size)
File "/the/path/python-ptrace/ptrace/debugger/process.py", line 637, in readCString
data = self.readBytes(address, chunk_length)
File "/the/path/python-ptrace/ptrace/debugger/process.py", line 566, in readBytes
formatAddress(address), size, err))
ProcessError: readBytes(0x0000000000000003, 256) error: [Errno 5] Input/output error
Any idea about what is wrong? I tried to look at the source but I'm a bit lost.
Originally reported by: 0x71 (Bitbucket: 0x71, GitHub: 0x71)
Hey,
I am trying to extract the return value of an interrupted syscall.
Having a look at ptrace / func_arg.py and func_call.py , it seems that self.resvalue is initialized but never updated or set while the result type, all arguments and the syscall itself can be extracted properly.
Is there a way to extract the return value?
Best Regards
Originally reported by: Anonymous
Hi,
I'm writing a tool that needs to catch when a process segfaults. For this purpose I'm using a code that ends up doing this:
signal = process.waitSignals(11)
print signal
However, even when the signal 11 (SIGSEGV) is received an exception is raised. This in an example changing the simple_dbg.py example to instead of wait for an event wait for a signal with the code previously mentioned:
Traceback (most recent call last):
File "examples/simple_dbg.py", line 65, in <module>
main()
File "examples/simple_dbg.py", line 61, in main
playWithProcess(process)
File "examples/simple_dbg.py", line 15, in playWithProcess
signal = process.waitSignals(11)
File "/usr/local/lib/python2.7/dist-packages/python_ptrace-0.8-py2.7.egg/ptrace/debugger/process.py", line 726, in waitSignals
return self.debugger.waitSignals(*signals, **{'pid': self.pid})
File "/usr/local/lib/python2.7/dist-packages/python_ptrace-0.8-py2.7.egg/ptrace/debugger/debugger.py", line 192, in waitSignals
raise event
ptrace.debugger.process_event.ProcessExit: Process 3691 killed by signal SIGSEGV
Am I missing something or doing something wrong?
Let assume I have this code (it is incomplete):
pid = createChild(arguments, False, env)
dbg = PtraceDebugger()
process = dbg.addProcess(pid, is_attached)
process.cont()
There seems to be no way to handle the stderr and stdout, there are something called pass_fd
in the createChild function, but there is no documentation (that I can find) how to do it, trying to use os.pipe()
on it seems to not work os.read(..)
seems to be blocked
Can you provide an example? or direct me in the right way?
Hi! 👋
We're currently about to upgrade to Python 3.12 on Arch Linux.
This project is one of the projects still using the imp
module in the latest released version.
Would it be possible to create a new release for this project, so that we can use that instead of applying 80e0c97?
That'd be much appreciated! 🙇
cc @anthraxx (package maintainer)
Originally reported by: Peter Saveliev (Bitbucket: svinota, GitHub: svinota)
Running the debugger on 32bit RHEL, I've got following error:
#!
$ strace.py ip link
execve(/sbin/ip, ['/sbin/ip', 'link'], [/* 40 vars */]) = 2970
brk(NULL) = 0x091ac000
mmap2(NULL, 4096, <PROT_READ|PROT_WRITE> (3), 34, -1, 0) = 0xb776d000
access('/etc/ld.so.preload', <R_OK> (4)) = -2 (No such file or directory)
open('/etc/ld.so.cache', O_RDONLY) = 3
fstat64(3, 0xbfbd0198) = 0
mmap2(NULL, 14032, <PROT_READ> (1), 2, 3, 0) = 0xb7769000
close(3) = 0
open('/lib/libresolv.so.2', O_RDONLY) = 3
read(3, 0xbfbd02b8, 512) = 512 (0x00000200)
fstat64(3, 0xbfbd01e0) = 0
mmap2(NULL, 104520, <PROT_READ|PROT_EXEC> (5), 2050, 3, 0) = 0x00ec2000
mprotect(0x00ed7000, 4096, 0) = 0
mmap2(0x00ed8000, 8192, <PROT_READ|PROT_WRITE> (3), 2066, 3, 21) = 0x00ed8000
mmap2(0x00eda000, 6216, <PROT_READ|PROT_WRITE> (3), 50, -1, 0) = 0x00eda000
close(3) = 0
open('/lib/libdl.so.2', O_RDONLY) = 3
read(3, 0xbfbd029c, 512) = 512 (0x00000200)
fstat64(3, 0xbfbd01c4) = 0
mmap2(NULL, 16500, <PROT_READ|PROT_EXEC> (5), 2050, 3, 0) = 0x00d28000
mmap2(0x00d2b000, 8192, <PROT_READ|PROT_WRITE> (3), 2066, 3, 2) = 0x00d2b000
close(3) = 0
open('/lib/libc.so.6', O_RDONLY) = 3
read(3, 0xbfbd0280, 512) = 512 (0x00000200)
fstat64(3, 0xbfbd01a8) = 0
mmap2(NULL, 1665416, <PROT_READ|PROT_EXEC> (5), 2050, 3, 0) = 0x00abd000
mprotect(0x00c4d000, 4096, 0) = 0
mmap2(0x00c4e000, 12288, <PROT_READ|PROT_WRITE> (3), 2066, 3, 400) = 0x00c4e000
mmap2(0x00c51000, 10632, <PROT_READ|PROT_WRITE> (3), 50, -1, 0) = 0x00c51000
close(3) = 0
mmap2(NULL, 4096, <PROT_READ|PROT_WRITE> (3), 34, -1, 0) = 0xb7768000
mmap2(NULL, 4096, <PROT_READ|PROT_WRITE> (3), 34, -1, 0) = 0xb7767000
set_thread_area(<user_desc entry_number=6L, base_addr=3077999408L, limit=1048575L, _bits_='Q'>) = 0
mprotect(0x00c4e000, 8192, 1) = 0
mprotect(0x00d2b000, 4096, 1) = 0
mprotect(0x00ed8000, 4096, 1) = 0
mprotect(0x00594000, 4096, 1) = 0
munmap(0xb7769000, 14032) = 0
Debugger error: [KeyError] 's'
Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/python_ptrace-0.6.4-py2.6.egg/EGG-INFO/scripts/strace.py", line 247, in _main
self.runDebugger()
File "/usr/lib/python2.6/site-packages/python_ptrace-0.6.4-py2.6.egg/EGG-INFO/scripts/strace.py", line 235, in runDebugger
self.syscallTrace(process)
File "/usr/lib/python2.6/site-packages/python_ptrace-0.6.4-py2.6.egg/EGG-INFO/scripts/strace.py", line 181, in syscallTrace
self.syscall(process)
File "/usr/lib/python2.6/site-packages/python_ptrace-0.6.4-py2.6.egg/EGG-INFO/scripts/strace.py", line 185, in syscall
syscall = state.event(self.syscall_options)
File "/usr/lib/python2.6/site-packages/python_ptrace-0.6.4-py2.6.egg/ptrace/debugger/syscall_state.py", line 15, in event
return self.enter(options)
File "/usr/lib/python2.6/site-packages/python_ptrace-0.6.4-py2.6.egg/ptrace/debugger/syscall_state.py", line 24, in enter
self.syscall.enter(regs)
File "/usr/lib/python2.6/site-packages/python_ptrace-0.6.4-py2.6.egg/ptrace/syscall/ptrace_syscall.py", line 37, in enter
setupSocketCall(self, self.process, self[0], self[1].value)
File "/usr/lib/python2.6/site-packages/python_ptrace-0.6.4-py2.6.egg/ptrace/syscall/socketcall.py", line 52, in setupSocketCall
function.restype, formats = SYSCALL_PROTOTYPES[function.name]
KeyError: 's'
Terminate <PtraceProcess #2970>
How reproducible: always
Steps to reproduce: try to debug on 32bit arch any program that uses netlink, e.g. ip or tc from iproute
The bug is blocker for svinota/pyroute2#4
Originally reported by: Anonymous
This issue can be seen when writing data using PTRACE_POKETEXT on 64-bit systems: the most significant 4 bytes of the written 8 byte word are always 0.
In cptrace.c the arguments to the ptrace call are converted using the PyArg_ParseTupleAndKeywords format string "Ii|iiO". This should be changed to "Ii|llO". I haven't tested this, but the rest of the code looks ok on first inspection (the variables are correctly declared as unsigned long).
Originally reported by: Anonymous
python-ptrace is very good. however ,docs should be specifyed1
Originally reported by: Pavel Šimerda (Bitbucket: pavlix, GitHub: pavlix)
In network-testing project, I'm using my own subclass of the ptrace debugger with some added functionality. It would be good to look at it and decide if parts of it could be moved to python-ptrace debugger itself.
https://github.com/pavlix/network-testing/blob/master/network_testing/debug.py
Originally reported by: Anonymous
Hi,
I was very excited to use python-ptrace for a project, but I stumbled upon a bug in the example strace.py file (but I think the problem is deeper).
I tried to run the following C program in both strace and strace.py :
#!C
#include <stdio.h>
int main(void)
{
int fd[2];
pipe(fd);
return 0;
}
If I run this program with strace, I get the following output
#!shell
pipe([3, 4]) = 0
but if I use strace.py, I get this :
#!shell
pipe(<(0, 2)>) = 0
The file descriptors are obviously wrong, because they correspond to stdin and stderr.
I use Ubuntu 13.10 (x86_64 architecture).
When process.detach is called the file handle to /proc/pid/mem is left open.
The implementation
class PTraceProcess:
...
def isTraced(self):
if not HAS_PROC:
self.notImplementedError()
stat = readProcessStat(self.pid)
return (stat.state == 'T')
is checking for T
, but that is for stopped by a signal; from man proc
:
/proc/[pid]/stat
Status information about the process. This is used by ps(1). It is defined in the kernel source file fs/proc/array.c.
...
(3) state %c
One of the following characters, indicating process state:
....
T Stopped (on a signal) or (before Linux 2.6.33) trace stopped
t Tracing stop (Linux 2.6.33 onward)
should be t
. Probably class ProcessState
needs reworking too.
Hey ! I was checking out the new commits when I came accross this issue:
Using this script:
python-ptrace> cat ../test.py
#!/usr/bin/env python
import subprocess
message = ["Message", "à", "écrire"]
processes = [subprocess.Popen(["echo", mot]) for mot in message]
[proc.wait() for proc in processes]
I get the following from python-ptrace
:
python-ptrace> ./strace.py ../test.py
[ ... ]
Debugger error: [ProcessSignal] Signal signal<133>
Traceback (most recent call last):
File "/home/jb/Projects/python-ptrace/./strace.py", line 259, in _main
exitcode = self.runDebugger()
File "/home/jb/Projects/python-ptrace/./strace.py", line 243, in runDebugger
return self.syscallTrace(process)
File "/home/jb/Projects/python-ptrace/./strace.py", line 188, in syscallTrace
self.syscall(event.process)
File "/home/jb/Projects/python-ptrace/./strace.py", line 193, in syscall
syscall = state.event(self.syscall_options)
File "/home/jb/Projects/python-ptrace/ptrace/debugger/syscall_state.py", line 15, in event
return self.exit()
File "/home/jb/Projects/python-ptrace/ptrace/debugger/syscall_state.py", line 40, in exit
self.process.waitSignals(SIGTRAP)
File "/home/jb/Projects/python-ptrace/ptrace/debugger/process.py", line 736, in waitSignals
return self.debugger.waitSignals(*signals, **{'pid': self.pid})
File "/home/jb/Projects/python-ptrace/ptrace/debugger/debugger.py", line 209, in waitSignals
raise event
ptrace.debugger.ptrace_signal.ProcessSignal: Signal signal<133>
Terminate <PtraceProcess #2181>
This does not happen when using strace.py python test.py
, but does when launching strace.py --fork python test.py
.
I remember the documentation specifically stating lack of support for forks, has this been added ?
hi,
i want to know the program execution process ,when i use the -f option, the process will be very slowly。
for example, i excute command "apt-get install gedit" , it takes about 5 seconds. if i use " python2.7 ./strace.py -f apt-get install gedit",it takes 2.5 min, the time is unacceptable.
i alse use linux strace, excute cmd "strace -f apt-get install gedit", it taks 20 second.
do you know the reason of being slowly?
Why not display error message in the same way? Some functions use "print(xxxx, file=stderr)" directly, and the others use "error(xxxxxx)".
Besides, "file=stderr" is gone in python3, it should be rewritten.
Originally reported by: Symeon P. (Bitbucket: symeonp, GitHub: symeonp)
Ubuntu 14.04.1 LTS 32bit,
reproduced also on a 64bit version.
I am using also the latest version of python-ptrace.
GNOME nautilus 3.10.1
Linux ubuntuvm 3.13.0-36-generic #63-Ubuntu SMP Wed Sep 3 21:30:45 UTC 2014 i686 i686 i686 GNU/Linux
#!python
Starting program: /usr/bin/nautilus /home/user/Desktop/jpc
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
[New Thread 0xb4cb8b40 (LWP 4874)]
[New Thread 0xb4299b40 (LWP 4876)]
[New Thread 0xb38ffb40 (LWP 4877)]
[New Thread 0xb26e3b40 (LWP 4879)]
[New Thread 0xae133b40 (LWP 4880)]
[Thread 0xb38ffb40 (LWP 4877) exited]
[New Thread 0xad932b40 (LWP 4885)]
Program received signal SIGFPE, Arithmetic exception.
[Switching to Thread 0xad932b40 (LWP 4885)]
--------------------------------------------------------------------------[regs]
EAX: 0x00000000 EBX: 0xAD413000 ECX: 0xB2F05620 EDX: 0x00000000 o d I t s Z a P c
ESI: 0xB2F06F28 EDI: 0x00000000 EBP: 0xB2F09794 ESP: 0xAD930EF0 EIP: 0xAD3E27E9
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
--------------------------------------------------------------------------[code]
=> 0xad3e27e9: div edi
0xad3e27eb: xor edx,edx
0xad3e27ed: mov DWORD PTR [ecx-0x20],edi
0xad3e27f0: movzx esi,BYTE PTR [ebp-0x1]
0xad3e27f4: mov DWORD PTR [ecx-0x8],0x0
0xad3e27fb: mov DWORD PTR [ecx-0x4],0x0
0xad3e2802: mov DWORD PTR [ecx-0x1c],esi
0xad3e2805: mov DWORD PTR [esp+0x10],eax
--------------------------------------------------------------------------------
0xad3e27e9 in ?? () from /usr/lib/i386-linux-gnu/libjasper.so.1
#!python
.... snip ....
Warning: Format argument utime of futex() value error: [ProcessError] readBytes(0x00000001, 8) error: [Errno 5] Input/output error
Traceback (most recent call last):
File "/home/user/Desktop/python-ptrace/ptrace/syscall/syscall_argument.py", line 115, in createText
text = self.formatValuePointer(argtype[:-1])
File "/home/user/Desktop/python-ptrace/ptrace/syscall/syscall_argument.py", line 160, in formatValuePointer
return self.readStruct(address, struct)
File "/home/user/Desktop/python-ptrace/ptrace/func_arg.py", line 71, in readStruct
data = self.function.process.readStruct(address, struct)
File "/home/user/Desktop/python-ptrace/ptrace/debugger/process.py", line 633, in readStruct
bytes = self.readBytes(address, sizeof(struct))
File "/home/user/Desktop/python-ptrace/ptrace/debugger/process.py", line 566, in readBytes
formatAddress(address), size, err))
ProcessError: readBytes(0x00000001, 8) error: [Errno 5] Input/output error
futex(0x09a0fd64, 133, 1, 0x00000001, 0x09a0fd60, 67108865) = 1
futex(0x09a0a2e0, 129, 1, <timespec tv_sec=0, tv_nsec=0>, NULL, 3064070720) = 1
time(NULL) = 1411652277 (0x54241ab5)
syscall<331>(0xbf8d2698, 0x00000000, 0xb6989000, 0xbf8d2698, 0xbf8d281c, 0x00000000) = 0
syscall<331>(0xbf8d2688, 0x00000000, 0xb6989000, 0xbf8d2688, 0xbf8d281c, 0x00000000) = 0
syscall<331>(0xbf8d2690, 0x00080000, 0xb6989000, 0xbf8d2690, 0xbf8d281c, 0x00000001) = 0
clone(<SIGCHLD|CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID> (18874385), NULL, NULL, NULL, 0xb4603b28) = 5947 (0x0000173b)
Warning: Format argument utime of futex() value error: [ProcessError] readBytes(0x000000f0, 8) error: [Errno 5] Input/output error
Traceback (most recent call last):
File "/home/user/Desktop/python-ptrace/ptrace/syscall/syscall_argument.py", line 115, in createText
text = self.formatValuePointer(argtype[:-1])
File "/home/user/Desktop/python-ptrace/ptrace/syscall/syscall_argument.py", line 160, in formatValuePointer
return self.readStruct(address, struct)
File "/home/user/Desktop/python-ptrace/ptrace/func_arg.py", line 71, in readStruct
data = self.function.process.readStruct(address, struct)
File "/home/user/Desktop/python-ptrace/ptrace/debugger/process.py", line 633, in readStruct
bytes = self.readBytes(address, sizeof(struct))
File "/home/user/Desktop/python-ptrace/ptrace/debugger/process.py", line 566, in readBytes
formatAddress(address), size, err))
ProcessError: readBytes(0x000000f0, 8) error: [Errno 5] Input/output error
futex(0xb2600010, 129, 1, 0x000000f0, 0xbf8d25b0, 3213698568) = 1
close(23) = 0
close(25) = 0
close(27) = 0
read(22, 0xbf8d26a8, 8) = 0
close(22) = 0
select(27, <fdset=(24, 26)>, NULL, NULL, NULL) = 2
Debugger error: [ValueError] Invalid status: 255
Traceback (most recent call last):
File "strace.py", line 247, in _main
self.runDebugger()
File "strace.py", line 235, in runDebugger
self.syscallTrace(process)
File "strace.py", line 170, in syscallTrace
event.display()
File "/home/user/Desktop/python-ptrace/ptrace/debugger/ptrace_signal.py", line 216, in display
self._analyze()
File "/home/user/Desktop/python-ptrace/ptrace/debugger/ptrace_signal.py", line 68, in _analyze
self.childExit()
File "/home/user/Desktop/python-ptrace/ptrace/debugger/ptrace_signal.py", line 211, in childExit
self.reason = ChildExit(child.pid, child.status, child.uid)
File "/home/user/Desktop/python-ptrace/ptrace/debugger/signal_reason.py", line 154, in __init__
message = formatProcessStatus(status, "Child process %s" % pid)
File "/home/user/Desktop/python-ptrace/ptrace/process_tools.py", line 110, in formatProcessStatus
raise ValueError("Invalid status: %r" % status)
ValueError: Invalid status: 255
Quit debugger
Terminate <PtraceProcess #5937>
Hopefully you should be able to reproduce it on a latest Ubuntu system with nautilus.
I am attaching also the test cases.
Many thanks Victor!
Cheers,
Symeon.
Hi, this is my first time posting an Issue, apologies if its done in an incorrect way.
I really like this library. I extended it a bit to support using PTRACE_SEIZE and the various upsides this brings, however I can only test on my 64 Bit Linux and dont really now the constants values for other OSes nor can I test it.
Should I provide my fix even though it wont work on BSD?
Thank you for providing the library!
For file : ptrace/debugger/child.py
def createChild(arguments, no_stdout, env=None):
"""
Create a child process:
- arguments: list of string where (e.g. ['ls', '-la'])
- no_stdout: if True, use null device for stdout/stderr
- env: environment variables dictionary
Use:
- env={} to start with an empty environment
- env=None (default) to copy the environment
"""
errpipe_read, errpipe_write = pipe()
_set_cloexec_flag(errpipe_write)
# Fork process
pid = fork()
if pid:
close(errpipe_write)
_createParent(pid, errpipe_read)
return pid
else:
close(errpipe_read)
_createChild(arguments, no_stdout, env, errpipe_write)`
It's very strange, if I remove 'close(errpipe_write)' line before '_createParent(pid, errpipe_read)'. the '_createParent' will be blocked. I can not understand this case of unix pipe, I think it's waiting for the data from the child.
Can anyone help me?
Currently on 32-bit arm is supported. Do you plan to add aarch64
support?
uname
would return aarch64
instead of arm
*
Originally reported by: teythoon (Bitbucket: teythoon, GitHub: teythoon)
This patch converts all class definitions to new-style classes. This is important for a pet project of mine that subclasses PtraceProcess and another mixin class and mixing old- and new-style classes using multiple inheritance doesn't work too well.
Originally reported by: Peter Saveliev (Bitbucket: svinota, GitHub: svinota)
root@localhost:~# ./strace.py ps
execve(/bin/ps, ['/bin/ps'], [/* 40 vars */]) = 19393
Debugger error: [NotImplementedError]
Traceback (most recent call last):
File "./strace.py", line 247, in _main
self.runDebugger()
File "./strace.py", line 235, in runDebugger
self.syscallTrace(process)
File "./strace.py", line 181, in syscallTrace
self.syscall(process)
File "./strace.py", line 185, in syscall
syscall = state.event(self.syscall_options)
File "/usr/lib/python2.7/dist-packages/ptrace/debugger/syscall_state.py", line 15, in event
return self.enter(options)
File "/usr/lib/python2.7/dist-packages/ptrace/debugger/syscall_state.py", line 24, in enter
self.syscall.enter(regs)
File "/usr/lib/python2.7/dist-packages/ptrace/syscall/ptrace_syscall.py", line 33, in enter
argument_values = self.readArgumentValues(regs)
File "/usr/lib/python2.7/dist-packages/ptrace/syscall/ptrace_syscall.py", line 74, in readArgumentValues
raise NotImplementedError()
NotImplementedError
Terminate <PtraceProcess #19393>
*** Error in `python': double free or corruption (!prev): 0x02340d90 ***
Aborted
root@localhost:~# cat /proc/cpuinfo
Processor : ARMv7 Processor rev 9 (v7l)
processor : 0
BogoMIPS : 1993.93
processor : 1
BogoMIPS : 1993.93
processor : 2
BogoMIPS : 1993.93
processor : 3
BogoMIPS : 1993.93
Features : swp half thumb fastmult vfp edsp neon vfpv3 tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc09
CPU revision : 9
Hardware : cardhu
Revision : 0000
Serial : 02458200e04f4300
root@localhost:~#
Platform -- Debian sid on asus transformer pad tf300t, using Android kernel:
root@localhost:~# uname -a
Linux localhost 3.1.10-00003-gb0003ba #1 SMP PREEMPT Fri Dec 28 17:34:15 CST 2012 armv7l GNU/Linux
If ARM platform is not supported, it would be better to raise an exception on import for non-distribution installations AND restrict platforms for distribution packaging.
If it is supported, it would be nice to have it fixed.
Originally reported by: teythoon (Bitbucket: teythoon, GitHub: teythoon)
This patch converts all class definitions to new-style classes. This is important for a pet project of mine that subclasses PtraceProcess and another mixin class and mixing old- and new-style classes using multiple inheritance doesn't work too well.
Originally reported by: Michael Witt (Bitbucket: MichaelHTW, GitHub: Unknown)
Hi,
I recently discovered this library and wanted to use it for process syscall tracing. Soon I discovered that tracing of processed created with the clone-syscall (or more commonly known as threads) are not supported.
As I needed this functionality for tracing on linux-based systems I added the missing functionality. I've forked the repository and pushed my changes here https://bitbucket.org/MichaelHTW/python-ptrace-withclone/commits/f163841b72a76232ac4d3721dc3f30b5cf581173.
In case there are others out there that might require this functionality feel free to integrate.
Best regards and thanks for the great work
Michael
Originally reported by: Kevin Chen (Bitbucket: kvchen, GitHub: kvchen)
Here's a summary of what I'm trying to do:
dbg = PtraceDebugger()
process = dbg.addProcess(pid, False)
map = readProcessMappings(process)
while True:
process.kill(19) # Send SIGSTOP to pause the process
process.readWord(0x189f9e0) # Read some memory address
process.cont()
After printing out the value on the first iteration, ptrace complains that the process PID could not be found for subsequent iterations:
ptrace.error.PtraceError: ptrace(cmd=1, pid=10679, 25819616, 0) error #3: No such process
I assume that there's something I don't know about ptrace, since it works if I stop the process and continually read memory without ever resuming it. Any pointers for what I'm doing wrong?
Hello, sys_rt_sigreturn is missing on your syscalls prototypes list
Originally reported by: Pavel Šimerda (Bitbucket: pavlix, GitHub: pavlix)
When debugging ssh/sshd with python-ptrace I found another issue. While strace.py
without -f
option works as expected, strace.py -f
somehow breaks signal handling. A similar thing happens in my own python-ptrace based test driver. Any ideas welcome.
What is the rationale behind the closing of file descriptors before executing a child ?
I noticed this pythonic behaviour in the subprocess
module for Windows portability, but is there a case against an option to turn that off while creating a child ? strace
does not do that, and my use case relies on opened file descriptors to communicate.
I can provide a pull request for that too, just wanted to know if there is a particular case this is required.
Sorry for the spam on an old repo !
Originally reported by: Pavel Šimerda (Bitbucket: pavlix, GitHub: pavlix)
I found a trivially reproducable difference between strace.py and genuine strace outputs showing that python-ptrace probably doesn't parse select()
arguments properly.
How to test:
$ strace -e select -o trace.strace ssh localhost true
$ python strace.py -e select -o trace.python-ptrace ssh localhost true
Expected result:
Output files should be roughly the same.
Actual result:
The second command results in a file that wrongly suggest the select was run on a huge number of file descriptors.
I found a bug in cpu.py:
CPU_SUB_REGISTERS = {
# main register name, shift, mask
'al': ('rax', 0, 0xff),
'bl': ('rbx', 0, 0xff),
'cl': ('rcx', 0, 0xff),
'dl': ('rdx', 0, 0xff),
'ah': ('rax', 8, 0xff),
'bh': ('rbx', 8, 0xff),
'ch': ('rcx', 8, 0xff),
'dh': ('rdx', 8, 0xff),
'ax': ('rax', 0, 0xffff),
'bx': ('rbx', 0, 0xffff),
'cx': ('rcx', 0, 0xffff),
'dx': ('rdx', 0, 0xffff),
'eax': ('rax', 32, None),
'ebx': ('rbx', 32, None),
'ecx': ('rcx', 32, None),
'edx': ('rdx', 32, None),
}
here the shift and mask for eax
, ebx
, ecx
, edx
is wrong, the correct version should be:"
CPU_SUB_REGISTERS = {
# main register name, shift, mask
'al': ('rax', 0, 0xff),
'bl': ('rbx', 0, 0xff),
'cl': ('rcx', 0, 0xff),
'dl': ('rdx', 0, 0xff),
'ah': ('rax', 8, 0xff),
'bh': ('rbx', 8, 0xff),
'ch': ('rcx', 8, 0xff),
'dh': ('rdx', 8, 0xff),
'ax': ('rax', 0, 0xffff),
'bx': ('rbx', 0, 0xffff),
'cx': ('rcx', 0, 0xffff),
'dx': ('rdx', 0, 0xffff),
'eax': ('rax', 0, 0xffffffff),
'ebx': ('rbx', 0, 0xffffffff),
'ecx': ('rcx', 0, 0xffffffff),
'edx': ('rdx', 0, 0xffffffff),
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.