Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RecursionError in is_executable() #2110

Open
lucasballr opened this issue Apr 4, 2024 · 6 comments
Open

RecursionError in is_executable() #2110

lucasballr opened this issue Apr 4, 2024 · 6 comments
Labels

Comments

@lucasballr
Copy link

lucasballr commented Apr 4, 2024

Description

I am auditing an old version of nginx. I installed the .deb package of pwndbg v2024.02.14 in an ubuntu 16.04 container. Running the program works just fine, but when it forks for a connection, I get a recursion error in pwndbg.

Steps to reproduce

In a Dockerfile:
FROM ubuntu:16.04
...
RUN wget http://nginx.org/download/nginx-1.3.9.tar.gz
&& tar -xzvf nginx-1.3.9.tar.gz
&& rm nginx-1.3.9.tar.gz
RUN wget https://github.com/pwndbg/pwndbg/releases/download/2024.02.14/pwndbg_2024.02.14_amd64.deb
RUN apt install ./pwndbg_2024.02.14_amd64.deb

pwndbg --args /usr/local/nginx/sbin/nginx -g 'daemon off;'

run and connect with a basic connection.
If you break during the parsing of that http connection, the error will occur.

My setup

Gdb: 13.2
Python: 3.11.5 (main, Aug 24 2023, 12:23:19) [GCC 12.3.0]
Pwndbg: 2024.02.14
Capstone: 5.0.1280
Unicorn: 2.0.1

@lucasballr lucasballr added the bug label Apr 4, 2024
@disconnect3d
Copy link
Member

@lucasballr can you show the error?

@disconnect3d
Copy link
Member

Also please provide full steps to reproduce the issue. The dockerfile doesn't build nginx etc. :/

@disconnect3d
Copy link
Member

I was able to build and run this nginx using the following additional commands:

apt install gcc wget tar make curl
./configure --without-http_rewrite_module --without-http_gzip_module
make -j2
make install

Idk where to break, I just hit ctrl+c and could reproduce the issue:

pwndbg> set exception-verbose on
Set whether to print a full stacktrace for exceptions raised in Pwndbg commands to 'on'.
pwndbg> set exception-debugger on                                               
Set whether to debug exceptions raised in Pwndbg commands to 'on'.
pwndbg> r                                                                       
Starting program: /usr/local/nginx/sbin/nginx -g daemon\ off\;
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Attaching after Thread 0x79a7304c2700 (LWP 4908) fork to child process 4911]
[New inferior 2 (process 4911)]
[Detaching after fork from parent process 4908]
[Inferior 1 (process 4908) detached]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
^C
Thread 2.1 "nginx" received signal SIGINT, Interrupt.
[Switching to Thread 0x79a7304c2700 (LWP 4911)]
0x000079a72fb8caf3 in epoll_wait () from /lib/x86_64-linux-gnu/libc.so.6
Traceback (most recent call last):
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/events.py", line 115, in caller
    func()
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/lib/cache.py", line 141, in decorator
    value = func(*a, **kw)
            ^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/stack.py", line 71, in is_executable
    ehdr = pwndbg.gdblib.elf.exe()
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/proc.py", line 149, in wrapper
    return func(*a, **kw)
           ^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/lib/cache.py", line 141, in decorator
    value = func(*a, **kw)
            ^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/elf.py", line 224, in exe
    return load(e)
           ^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/elf.py", line 262, in load
    return get_ehdr(pointer)[1]
           ^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/elf.py", line 292, in get_ehdr
    vmmap = pwndbg.gdblib.vmmap.find(pointer)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/lib/cache.py", line 141, in decorator
    value = func(*a, **kw)
            ^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/vmmap.py", line 175, in find
    return explore(address)
           ^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/abi.py", line 64, in caller
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/vmmap.py", line 204, in explore
    flags |= 1 if not pwndbg.gdblib.stack.is_executable() else 0
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/lib/cache.py", line 141, in decorator
    value = func(*a, **kw)
            ^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/stack.py", line 71, in is_executable
    ehdr = pwndbg.gdblib.elf.exe()
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/proc.py", line 149, in wrapper
    return func(*a, **kw)
           ^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/lib/cache.py", line 141, in decorator
    value = func(*a, **kw)
            ^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/elf.py", line 224, in exe
    return load(e)
           ^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/elf.py", line 262, in load
    return get_ehdr(pointer)[1]
           ^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/elf.py", line 292, in get_ehdr
    vmmap = pwndbg.gdblib.vmmap.find(pointer)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/lib/cache.py", line 141, in decorator
    value = func(*a, **kw)
            ^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/vmmap.py", line 175, in find
    return explore(address)
           ^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/abi.py", line 64, in caller
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/vmmap.py", line 204, in explore
    flags |= 1 if not pwndbg.gdblib.stack.is_executable() else 0
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/lib/cache.py", line 141, in decorator
    value = func(*a, **kw)
            ^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/stack.py", line 71, in is_executable
    ehdr = pwndbg.gdblib.elf.exe()
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/pwndbg/lib/python3.11/site-packages/pwndbg/gdblib/proc.py", line 149, in wrapper
    return func(*a, **kw)

@disconnect3d
Copy link
Member

disconnect3d commented Apr 24, 2024

The problem seems to be comming from the fact that we reconfigure GDB to attach to the child process when a fork occurs, and it causes problem[s] with some of our logic.

If we do set follow-fork-mode parent, the ctrl+c does not trigger the above issues.

@disconnect3d
Copy link
Member

This is really interesting. There is some quirk with debugging this nginx process that if we do set follow-fork-mode child with pure GDB and run it, then interrupt it, the process is defunct/dies somehow:

root@e77a643dfa31:/nginx-1.3.9# gdb --quiet --ex 'set follow-fork-mode child' --args /usr/local/nginx/sbin/nginx -g 'daemon off;'
Reading symbols from /usr/local/nginx/sbin/nginx...done.
(gdb) r
Starting program: /usr/local/nginx/sbin/nginx -g daemon\ off\;
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New process 5382]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
^C
Thread 2.1 "nginx" received signal SIGINT, Interrupt.
[Switching to Thread 0x7cf8c5b65700 (LWP 5382)]
0x00007cf8c522faf3 in __epoll_wait_nocancel ()
    at ../sysdeps/unix/syscall-template.S:84
84	../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) info proc mappings
process 5382
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile

(gdb) info proc
process 5382
cmdline = ''
warning: unable to read link '/proc/5382/cwd'
warning: unable to read link '/proc/5382/exe'

(gdb) !cat /proc/5382/maps

(gdb) !ps auxf
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          41  0.0  0.0  18244  3200 pts/1    Ss+  22:35   0:00 bash
root           1  0.0  0.0  18248  3200 pts/0    Ss   22:34   0:00 bash
root        5376  0.7  0.2  81136 37364 pts/0    S+   22:50   0:00 gdb --quiet --ex set follow-fork-mode child --args /usr/local/nginx/sbin/nginx -g daemon off;
root        5378  0.0  0.0  17968  2432 pts/0    S    22:50   0:00  \_ nginx: master process /usr/local/nginx/sbin/nginx -g daemon off;
nobody      5382  0.0  0.0      0     0 pts/0    Z    22:50   0:00  |   \_ [nginx] <defunct>
root        5387  0.0  0.0   4508  1536 pts/0    S+   22:50   0:00  \_ sh -c ps auxf
root        5388  0.0  0.0  34428  2816 pts/0    R+   22:50   0:00      \_ ps auxf
(gdb) 

@disconnect3d
Copy link
Member

So in this case, we do not have vmmaps bcoz the process died when it started? or sth? lol

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants