-
-
Notifications
You must be signed in to change notification settings - Fork 739
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
Error handling in GefRemoteSessionManager.sync
#1045
Conversation
In case of failure, we still want to initialize every possible thing to still provide the best user experience as possible. The only consequences of an early return here is to make everything un-initialized, even if we could init other things after the return
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.
gef.py
Outdated
if self.file.exists(): | ||
gef.binary = Elf(self.lfile) |
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.
This is problematic as it will prevent any function/command depending on gef.binary
for instance checksec
) to work at all. Are you doing this check because of the support for rr
? If so, we probably still need the way I mentioned to detect we're running rr
so that we can gracefully handle that case.
I'm not super sure the best way about this, but that if
is definitely problematic.
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.
This is not related to rr, actually this has never failed in my tests, but raising an exception in the setup of the session would mean that the session would be running (since it is actually managed by gdb itself) but the gef session's wrapper would be completely broken.
I think having some commands not working (like checksec) is better than having nothing working.
But I agree with you that something needs to be done to prevent having a "bad" fail when running those commands, and instead having a clean error message
gef.py
Outdated
if not self.sync(str(self.file)): | ||
warn(f"'{fpath}' could not be fetched on the remote system.") | ||
success = False |
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 here is a good reason to throw: not having the executable will be very problematic (as explained below) and hard to recover from.
if not self.sync(str(self.file)): | |
warn(f"'{fpath}' could not be fetched on the remote system.") | |
success = False | |
if not self.sync(str(self.file)): | |
raise FileNotFoundError |
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.
gef.py
Outdated
if not self.sync(f"/proc/{self.pid}/maps"): | ||
warn(f"'{fpath}' could not be fetched on the remote system.") | ||
success = False |
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.
if not self.sync(f"/proc/{self.pid}/maps"): | |
warn(f"'{fpath}' could not be fetched on the remote system.") | |
success = False | |
try: | |
self.sync(f"/proc/{self.pid}/maps") | |
except gdb.error as e: | |
warn(f"sync('{fpath}' failed, reason: {str(e)}") | |
[...] setup the mock /proc/maps here[...] |
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.
Waiting for what you think about this before changing anything :)
#1045 (comment)
warn(f"Failed to create a proper environment for {gef.session.remote}") | ||
return False |
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.
Raising is better here too, especially since we're in a callback function. Failing setup
is not something easily recoverable.
Also need to None
the session.
warn(f"Failed to create a proper environment for {gef.session.remote}") | |
return False | |
gef.session.remote = None | |
raise EnvironmentError("Failed to create a remote environment") |
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.
This function is directly called from gdb:
pi if target_remote_posthook(): ...
iirc raising an exception here creates a full stack trace in the gdb console.
If this fails, there are many warning that are raised and that helps to know what happened, without disturbing the user (we actually want to warn him that everything will not work as intended, but since we try our best to make everything work as good as possible we don't want to print errors and stacktraces in most situations)
I still think we don't want to raise anything here, but there was a reset missing :)
Even if we don't raise an exception (still discussing about it) we need to manage properly the cases were the binary was not setup.
with environ.open("wb") as fd: | ||
fd.write(b"PATH=/bin\x00HOME=/tmp\x00") | ||
|
||
fpath = f"/proc/{self.pid}/cmdline" |
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 nice if we could just tell gef to use a buffer instead of having to write stuff to disk when faking stuff. It would be even nicer if we didn't have to fake it.
Catching up on this @ValekoZ there's been many changes since this PR (which now make a conflict with gef in main). Can you update this PR (or close if doesn't apply anymore) ? Thanks! |
Most of the work seems to have been rewritten in other PRs, we can close this one :) |
Description
def sync(self, src: str, dst: Optional[str] = None) -> bool:
should not raise an error when failing to download a file, but return false instead.Then, error handling should be managed better in functions that call this
sync
functionThis issue was found while reproducing #1044
Before
After
Checklist