-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Add port
, gdb_args
, and gdbserver_args
to gdb.debug()
#2382
Conversation
+ port: specifies the port that should be used by the gdbserver (this is useful for alpine) + gdb_args: allows forwarding arguments to the gdb binary spawned by gdb.attach() (just a passthrough) aslo downgraded "GDB Python API is supported only for local processes" to a warning, because it seems to work on some systems.
additionally added the optional argument |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thank you! Allowing more control over the way debugging is initiated seems useful for one-off problems.
Your "plugin" looks nice, do you have plans to upstream features? I'd rather have nice docker and qemu integration than patchwork changes to make the external tool work. :D
pwnlib/gdb.py
Outdated
@@ -612,7 +622,7 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api= | |||
gdbscript = gdbscript or '' | |||
|
|||
if api and runner is not tubes.process.process: | |||
raise ValueError('GDB Python API is supported only for local processes') | |||
log.warn('GDB Python API is supported only for local processes') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like changing this without tests that proove full support. Then we could just remove the warning altogether. Which runner did work for you other than a process?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ssh.process works for me.
This makes sense IMO, because gdb is still run on the host session therefore attaching the gdb api through a unix socket still works. Changing it into a warning for ssh.process and an error for everything else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
7305502: GDB Python API is now a warning for ssh.process and an error for everything else
pwnlib/gdb.py
Outdated
if not port: | ||
# Find what port we need to connect to | ||
if ssh or context.native or (context.os == 'android'): | ||
port = _gdbserver_port(gdbserver, ssh) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should still parse the output even though the port is specified explicitly. There were problems with shells forking when gdbserver uses them causing stalls which were detected by a timeout on the message in _gdbserver_port
recently. And this way we're sure gdbserver is up and running before trying to attach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
7305502: now using gdbserver_port to check if the correct port was set
+ gdb.debug port is now also used for qemu + GDB Python API is now tested for tubes.process.process a warning for ssh.process and an error for everything else + updated docs to use mention that gdbserver ports are randomized by default + now using gdbserver_port to check if the correct port was set + fixed CHANGELOG.md structure
Addressed change requests in 7305502. regarding:
The initial reason this has turned into a "plugin" i maintain myself is so i can basically make changes whenever i encounter a problem or run into an issue (or want to add a new feature). Generally speaking I don't mind adding the functionality to upstream, but this might require some time because
Maybe we can move this discussion somewhere else? My discord tag is @gfelber (I'm also on the official discord server). |
port
, gdb_args
, and gdbserver_args
to gdb.debug()
pwnlib/gdb.py
Outdated
raise ValueError('GDB Python API is supported only for local processes') | ||
if runner is not ssh.process: | ||
raise ValueError('GDB Python API is supported only for local processes') | ||
log.warn('GDB Python API for ssh processes is not officially tested') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to add the tests instead of this vague warning. I think we can copy the API tests and slap a ssh=shell
argument to the .debug
call.
See here for instructions on how to test locally. make -C travis/docker ANDROID=no TARGET=gdb.rst
should do the job.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, lol. gdb tests are disabled in the docker testing setup apparently. CI will do the work then.
pwntools/travis/docker/doctest3
Lines 27 to 29 in 51e8eb0
# GDB tests currently don't work inside Docker for unknown reasons. | |
# Disable these tests until we can get them working. | |
echo > ~/pwntools/docs/source/gdb.rst |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tried running the gdb tests in docker and they all passed, so I guess we can just remove that line from doctest3 and include them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0ee8d36 so i added some test cases (the same as non ssh) and i was wondering how this test case is supposed to work (IMO it doesn't make sense for gdb.attach to work on remote targets and the test case doesn't work for me).
Attach to the remote process from a :class:`.remote` or :class:`.listen` tube,
as long as it is running on the same machine.
>>> server = process(['socat', 'tcp-listen:12345,reuseaddr,fork', 'exec:/bin/bash,nofork'])
>>> sleep(1) # Wait for socat to start
>>> io = remote('127.0.0.1', 12345)
>>> sleep(1) # Wait for process to fork
>>> pid = gdb.attach(io, gdbscript='''
... call puts("Hello from remote debugger!")
... detach
... quit
... ''')
>>> io.recvline()
b'Hello from remote debugger!\n'
>>> io.sendline(b'echo Hello from bash && exit')
>>> io.recvall()
b'Hello from bash\n'
this is the error i get
Document: gdb
-------------
**********************************************************************
File "../../pwnlib/gdb.py", line ?, in default
Failed example:
io.recvline()
Exception raised:
Traceback (most recent call last):
File "/usr/lib/python3.10/doctest.py", line 1350, in __run
exec(compile(example.source, filename, "single",
File "<doctest default[5]>", line 1, in <module>
io.recvline()
File "/home/pwntools/pwntools/pwnlib/tubes/tube.py", line 527, in recvline
return self.recvuntil(self.newline, drop = not keepends, timeout = timeout)
File "/home/pwntools/pwntools/pwnlib/tubes/tube.py", line 341, in recvuntil
res = self.recv(timeout=self.timeout)
File "/home/pwntools/pwntools/pwnlib/tubes/tube.py", line 106, in recv
return self._recv(numb, timeout) or b''
File "/home/pwntools/pwntools/pwnlib/tubes/tube.py", line 176, in _recv
if not self.buffer and not self._fillbuffer(timeout):
File "/home/pwntools/pwntools/pwnlib/tubes/tube.py", line 155, in _fillbuffer
data = self.recv_raw(self.buffer.get_fill_size())
File "/home/pwntools/pwntools/pwnlib/tubes/sock.py", line 39, in recv_raw
data = self.sock.recv(numb, *a)
File "/home/pwntools/pwntools/docs/source/conf.py", line 446, in alrm_handler
raise EndlessLoop()
EndlessLoop
i also added some timeouts to the other recvline commands for the tests
+ gdb.debug port is now also used for qemu + GDB Python API is now tested for tubes.process.process a warning for ssh.process and an error for everything else + updated docs to use mention that gdbserver ports are randomized by default + now using gdbserver_port to check if the correct port was set + fixed CHANGELOG.md structure + added timeouts for recvline() gdb tests + also run gdb api tests for ssh runner
hey are there any outstanding issues? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, sorry. I wanted to check why you had to add the timeout everywhere instead of having a timeout set on the context but didn't get to it.
I can clean up later if there is something to cleanup.
Thank you!
Zeah i guess context would have been better for the docs, but i realized that there are different acceptable timeout margins (e.g. some use 1s others 30s), so decided to set it to 1s for most use cases and in special cases increased it |
There were additional `timeout=X` additions in #2382 which caused tests to fail randomly when a timeout was reached. The tests run through occationally, so it's not an infinite loop. But flakey tests are annoying and I don't see a reason for the timeout additions to the doctests for the core patch of that PR other than failing early during manual tests of new functionality. CI running smoothly is more important than fast failing during development on the gdb module imo.
added two arguments to gdb.debug()
also downgraded "GDB Python API is supported only for local processes" to a warning, because it seems to work.
These changes are made for compatibility with my pwntools "plugin" vagd which currently uses a workaround on Pwngd.debug() (basically the same behaviour as the patch)