Add file descriptor and fdinfo parsing to Linux#1609
Add file descriptor and fdinfo parsing to Linux#1609Torres773 wants to merge 3 commits intofox-it:mainfrom
Conversation
|
@Torres773 thank you for your contribution! As this is your first code contribution, please read the following Contributor License Agreement (CLA). If you agree with the CLA, please reply with the following information:
Contributor License Agreement
Contribution License AgreementThis Contribution License Agreement ("Agreement") governs your Contribution(s) (as defined below) and conveys certain license rights to Fox-IT B.V. ("Fox-IT") for your Contribution(s) to Fox-IT"s open source Dissect project. This Agreement covers any and all Contributions that you ("You" or "Your"), now or in the future, Submit (as defined below) to this project. This Agreement is between Fox-IT B.V. and You and takes effect when you click an “I Accept” button, check box presented with these terms, otherwise accept these terms or, if earlier, when You Submit a Contribution.
|
|
@DissectBot agree |
| def __init__(self, proc: Path, fd_num: str): | ||
| self.number = int(fd_num) | ||
| self.path = proc.joinpath(fd_num) | ||
| self.info_path = proc.parent.joinpath("fdinfo", fd_num) | ||
| self.target = None | ||
| self.fd_info = None |
There was a problem hiding this comment.
Can you take an approach that's closer to how other items are parsed? I.e. don't do that much "post-processing" in the __init__, but prefer to do it in _parse_fd.
| @property | ||
| def link(self) -> str: | ||
| """Returns the resolved symlink""" | ||
| if not self.target is None: | ||
| return self.target | ||
| try: | ||
| self.target = self.path.readlink() | ||
| except Exception: | ||
| self.target = "unknown" | ||
| return self.target |
There was a problem hiding this comment.
Lazily resolved attributes like this are fine, but prefer to use @cached_property.
| self.fd_info = self._parse_fdinfo() | ||
| return self.fd_info | ||
|
|
||
| def _parse_fdinfo(self): |
|
Also please fix the linter. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1609 +/- ##
=======================================
Coverage 81.12% 81.12%
=======================================
Files 401 401
Lines 35091 35134 +43
=======================================
+ Hits 28467 28504 +37
- Misses 6624 6630 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| return "unknown" | ||
|
|
||
| @cached_property | ||
| def info(self)-> dict[str, str]: |
There was a problem hiding this comment.
I think putting this into a FdInfo dataclass (like Environ, PacketSocket, etc) would be nicer. This way you can access attributes as fd.info.flags instead of fd.info["flags"].
Also, please document (in the dataclass) what the specific info attributes mean.
| def info(self)-> dict[str, str]: | |
| def info(self) -> dict[str, str]: |
| @cached_property | ||
| def link(self) -> str: | ||
| """Returns the resolved symlink.""" | ||
| try: | ||
| return str(self.path.readlink()) | ||
| except Exception: | ||
| return "unknown" |
There was a problem hiding this comment.
Is unknown a value used in /proc/[pid]/fd symlink targets? If not, better to keep it as close to procfs as possible. Your test case also fails now because you cast this to a string.
Additionaly, can you implement a test case for when the Exception occurs?
| assert environ[0].contents == "1" | ||
|
|
||
| fd = list(process.fd()) | ||
| assert "socket" in fd[0].link.name |
There was a problem hiding this comment.
This not fails due to link returning a string instead of a Path
Implement structured file descriptor access within ProcProcess.
Currently, dissect.target treats /proc/[pid]/fd primarily as generic
filesystem entries. This change introduces a FileDescriptor object
that aggregates data from both the fd symbolic links and the
corresponding fdinfo metadata.
By parsing fd and fdinfo, we expose critical data such as file offsets (pos)
and access flags. This allows investigators to identify files and
other artifacts currently in use by the process
The implementation uses lazy loading for fdinfo to maintain performance
during process iteration.
How to test:
populated '.target' and '.info' attributes.