Closed k4lizen closed 2 months ago
This is due to fish forking multiple times when running fish -c somescript
and we're returning the pid of the original fish process instead of the forked one which actually runs the script.
I don't use fish, so you're welcome to propose a pull request for the misc.run_in_new_terminal
function to return the correct pid around:
https://github.com/Gallopsled/pwntools/blob/75cc3c3d5cd1e4d03dee1cf31ba67dd8139b941c/pwnlib/util/misc.py#L305
This is due to fish forking multiple times when running
fish -c somescript
and we're returning the pid of the original fish process instead of the forked one which actually runs the script.
I only see one process here.
But your screenshot shows 3 processes?
When I run fish -c "sleep 999"
I see the fish process staying alive instead of being replaced by the sleep binary
# fish -c "sleep 999"
# other terminal:
pstree -p `whoami` | grep sleep
zsh(367594)---fish(368747)---sleep(368753)
compared to bash or zsh:
# bash -c "sleep 999"
# other terminal:
pstree -p `whoami` | grep sleep
zsh(367594)---sleep(368783)
I've asked about this in fish's matrix channel and it's expected behavior - BUT I've confused myself with terminal emulators and shells. This issue isn't in pwntools since we don't run shell -c command
at all but an instance of #2321 which boils down to a bug in gdbserver. pwntools 4.13.0 would print a more helpful error message suggesting you to set the SHELL environment variable to some other shell than fish like bash.
So try doing p = gdb.debug(['./start'], env={"SHELL": "/bin/bash"})
instead.
Looking a bit more: gdbserver supports a --no-startup-with-shell
argument which might help too.
--startup-with-shell
Start PROG using a shell. I.e., execs a shell that
then execs PROG. (default)
--no-startup-with-shell
Exec PROG directly instead of using a shell.
Disables argument globbing and variable substitution
on UNIX-like systems.
@Arusekk can you think of why we don't start the program directly but have it go through a shell in gdb.debug? We don't do that when starting directly using process()
and I don't think we support the shell=True
argument when debugging?
~@iacore~ @k4lizen can you test if adding that flag fixes your issue please? in gdb.py in _gdbserver_args(), can you add the argument? Change that line to
gdbserver_args = [gdbserver, '--multi', '--no-startup-with-shell']
in your /home/maker/.local/lib/python3.11/site-packages/pwnlib/gdb.py
So try doing p = gdb.debug(['./start'], env={"SHELL": "/bin/bash"}) instead.
This does seem to work.
gdbserver_args = [gdbserver, '--multi', '--no-startup-with-shell']
This also seems to work.
A bit off topic but im seeing some weird behaviour with the SHELL
env variable, like doing fish; bash; fish;
points to bash sometimes. Or setting the variable to fish and going into zsh still has it pointing to fish.
But anyways yeah, the proposed fixes seem good (and works with my template script with tmux settings etc).
But your screenshot shows 3 processes?
I run fish -c xxx
in fish shell (I use fish already).
When I run
fish -c "sleep 999"
I see the fish process staying alive instead of being replaced by the sleep binary
This is expected. -c runs the script in script mode, not execv. You are likely looking for fish -c 'exec sleep 999'
, which calls execv.
compared to bash or zsh: ...
It's not mentioned in sh, so I guess it's not even part of POSIX. fish is also not a POSIX-compliant shell, so..
Yes, faho mentioned this too and it seems the other shells are doing it wrong, but as I said, this is out of our control and done inside gdbserver.
No idea either, I guess nobody thought about it when it worked correctly (before fish even existed), and this is most likely GDB not supporting fish, not us not thinking :wink:
We're passing --no-startup-with-shell
now, but the --wrapper
argument appears to require a shell. So it's only passed when env
is None and argv0 is unchanged. This will make debugging with a forking shell work most of the time, hopefully.
Hangs with:
Regardless of if tmux is active. Tried on both kitty terminal and gnome terminal. Ctrl+C gives: