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

Fix remote use of gef.memory.maps #1109

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

gordonmessmer
Copy link
Contributor

Description

This change passes both the "display" path and the local "real" path for each section or file to the print_got_for function in GotCommand. Without this change, the got command does not work properly in a remote debugging session.

Checklist

  • My code follows the code style of this project.
  • My change includes a change to the documentation, if required.
  • If my change adds new code, adequate tests have been added.
  • I have read and agree to the CONTRIBUTING document.

Copy link

🤖 Coverage update for 5c68a97 🟢

Old New
Commit bdf8219 5c68a97
Score 71.4923% 71.4923% (0)

@gordonmessmer
Copy link
Contributor Author

One way to make this commit a little nicer would be to add an interface that both Sections and the GefSessionManager.file property could implement, each providing both a display path (.path) and a local path (.realpath) attribute/property.

Copy link

github-actions bot commented Jun 1, 2024

🤖 Coverage update for 2e6166f 🟢

Old New
Commit f0b6d1d 2e6166f
Score 71.5991% 71.5991% (0)

@gordonmessmer
Copy link
Contributor Author

I've rebased this commit on the new main branch.

Currently, this patch allows the got command without --all to work, and it allows shared objects whose paths are canonical to work with using the --all option, but non-canonical paths are silently ignored. So, it's partially functional, but not really elegant.

It could be merged as-is. If you have any suggestions on making it better fit the code style of the project, I can work on those. I could also look for a way to print a warning for files that can't be found (which will probably always be non-canonical paths). At a stretch, I could even try to add some simple searches for likely alternate paths when the realpath isn't present.

@hugsy
Copy link
Owner

hugsy commented Jun 1, 2024

No problem. --all is about to be merged anyway.
Also I usually never review draft PR, so when you deem it ready, mark it as such as you can also assign me for review so I get a notification.

Cheers

@gordonmessmer gordonmessmer marked this pull request as ready for review June 1, 2024 19:34
Copy link

github-actions bot commented Jun 1, 2024

🤖 Coverage update for 8cd572b 🟢

Old New
Commit f0b6d1d 8cd572b
Score 71.5991% 71.5991% (0)

@gordonmessmer
Copy link
Contributor Author

I added a patch that performs one permutation to find paths that aren't found at the expected path. With that patch, remote debugging against a Red Hat system provides the full expected output for got --all.

@gordonmessmer
Copy link
Contributor Author

(I did not remove the note about the bug from the got documentation, because shared objects that are not found due to other symlinks could still result in their absence from the output.)

Copy link

github-actions bot commented Jun 1, 2024

🤖 Coverage update for 4443d0d 🟢

Old New
Commit f0b6d1d 4443d0d
Score 71.5991% 71.5991% (0)

@gordonmessmer
Copy link
Contributor Author

Another way to make this implementation less messy would be to always use maps, rather than using maps for --all and gef.session.file/get_filepath otherwise.

I don't have strong feelings about patch 3, but it's an option. I could squash that and the first, or drop it.

@gordonmessmer
Copy link
Contributor Author

"you can also assign me for review so I get a notification"

@hugsy as a non-project member, I don't think I can. 😆

gef.py Outdated Show resolved Hide resolved
gef.py Show resolved Hide resolved
gef.py Outdated Show resolved Hide resolved
gef.py Outdated Show resolved Hide resolved
gef.py Outdated Show resolved Hide resolved
@Grazfather Grazfather requested a review from hugsy June 2, 2024 21:27
Copy link

github-actions bot commented Jun 2, 2024

🤖 Coverage update for c37d58a 🟢

Old New
Commit f0b6d1d c37d58a
Score 71.5991% 71.5991% (0)

Copy link

github-actions bot commented Jun 3, 2024

🤖 Coverage update for fec8600 🟢

Old New
Commit f0b6d1d fec8600
Score 71.6907% 71.6907% (0)

Copy link
Owner

@hugsy hugsy left a 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 to add a test case on this function specifically (i.e. search_for_realpath)


remote_path = pathlib.Path(self.path)
# First, try the canonical path in the remote session root.
candidate1 = gef.session.remote.root / remote_path.relative_to(remote_path.anchor)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to check if the session is remote before using gef.session.remote otherwise, it will throw an exception

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, search_for_realpath() is only called after checking if the session is remote (line 718). Would you like an assert here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Or just mark the function private, so that it doesn't gain new users which haven't already checked gef.session.remote?)

gef.py Show resolved Hide resolved
gef.py Show resolved Hide resolved
@gordonmessmer
Copy link
Contributor Author

So I think the outstanding work is test for search_for_realpath, and make that function private (and assert gef.session.remote).

If I resolved anything by mistake, please let me know.

Copy link

🤖 Coverage update for ee8b8ba 🟢

Old New
Commit f0b6d1d ee8b8ba
Score 71.6798% 71.6798% (0)

Copy link

🤖 Coverage update for 58546bf 🟢

Old New
Commit f0b6d1d 58546bf
Score 71.6798% 71.6798% (0)

@gordonmessmer
Copy link
Contributor Author

I'll have to think about this some more... The test currently checked in succeeds on ubuntu 22.04, but not 20.04.

I could just not assert that a lib in /usr was found, but that opens the possibility of some future test platform not exhibiting this behavior, and the test doing nothing at all.

@gordonmessmer gordonmessmer changed the title Fix remote use of the got command Fix remote use of gef.memory.maps Jun 19, 2024
Copy link

🤖 Coverage update for bcaddfc 🟢

Old New
Commit f0b6d1d bcaddfc
Score 71.6798% 71.6798% (0)

@gordonmessmer
Copy link
Contributor Author

What's important to you in these tests?

Both Debian and Fedora family systems have the same issue that I originally noticed with remote debugging: /lib and /lib64 are symlinks into /usr, and the files retrieved by gdb haven't been resolved by realpath(), so they don't match the paths indicated in /proc/pid/maps. That makes testing easier, because I don't need to introduce tests on a different platform, nor to I need to modify the local tmp root to reproduce the issue.

But Debian also makes ld.so a symlink, and that makes testing on Debian(/Ubuntu) very difficult, because fixing up that path isn't simple and predictable the way that fixing the /usr symlinks is, so remote binaries on Debian systems always have a map that's missing, which looks like a failure in the realpath property of map sections.

On both Ubuntu 20.04 and 22.04, the maps file will contain only the binary executable, ld.so, and virtual objects, typically. But if I add gdb.execute("b main"); gdb.execute("continue") before checking maps, I'll get a copy of maps after runtime linking is complete on Ubuntu 22.04 -- but not on Ubuntu 20.04. That's making testing difficult, because one platform doesn't behave like the other for reasons that aren't obvious to me.

I think the right way to do test the realpath property would be an isolated unit test, not a functional test, but gef isn't designed to be imported for unit testing.

These tests pass, but only because on Ubuntu 20.04 they don't do anything.

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

Successfully merging this pull request may close these issues.

None yet

3 participants