-
Notifications
You must be signed in to change notification settings - Fork 455
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
Pointers smear memory protection #1243
base: develop
Are you sure you want to change the base?
Pointers smear memory protection #1243
Conversation
This is a significant shift in semantics. I'm not immediately against it, but I definitely want to consider the ramifications. This could technically differ from the current functionality (if 0 happens to be mapped, or people are using it just to check for 0 rather than readability). It will require at least a MINOR bump of the framework, and possibly a MAJOR bump too. It would also be good to identify places in existing plugins where this functionality is already expected (so 3) and or one of 1 or 2 to see how prevalent of an issue this is. I'm sure there's instances where windows says something is a pointer, but actually use it to just hold a number, and where the 0 test might be used legitimately which this functionality may now break. Similarly pointers in python are just integers, and this change will make the integer logic and pointer logic diverge. It wasn't called |
If, in a hypothetical scenario, a pointer to 0 is readable in a specific layer and someone wants to check for 0 specifically, why are they evaluating it as a boolean? shouldn't they use
Could you point me out to where you think this would break so that I can test it? In Linux, the XArray and RadixTree extensively use pointers as values. These pointers, when evaluated in a boolean context, will return
I assume you're talking about pointers in Anyway, if you don't think it has a chance of being merged, fair enough, let's close this PR and not waste any more time. |
Yes, but you're arguing for change, saying that both are doable actually holds to keep things as they are, rather than uproot them. Why are you evaluating an
I don't have specific examples, but I recall from the past instances where a struct said it was a pointer but actually that was just to get a structure that fit the size of a register but didn't actually point to anything in particular. That's only a recollection though, but you still haven't convinced me why we should be changing a fundamental test for what's supposed to be an integer, rather than just using the provided method that's already in place?
Yes, I meant pointers in volatility (and technically pointers in C, I think). They are just integers. I disagree that augmenting integers is diverging. Adding methods and states just augments an integer, but essentially is still works the same way. This changes the way the underlying type works. I don't recall if we cap pointers to only live within their address space, but I suspect/hope we don't.
I think it's very unlikely I'll merge it, but it does raise a good point and I haven't ruled it out. At the moment though, the advantages (particularly compared to |
- lsof plugin: source code refactored - lsof plugin: Added the 'device' column to complete the inode information. An inode number is specific to the filesystem/device it belongs to. - lsof/sockstat plugins: Add threads support. Threads may or may not share the file descriptor table with the thread group leader, depending on whether the CLONE_FILES flag is included in the clone() syscall. Also, once started, a thread can unshare the fd table with its parent. Refer to the unshare() libc syscall wrapper man page, unshare(2). Additionally, note that the Linux lsof command in user space includes thread listings by default as well. Now, there are two columns to identify the thread group ID (PID) and the task/thread ID (TID). - Added inode getters from both, the dentry and file structs. From kernels +3.9 the file struct cached the inode pointer. So, when possible, we get this value. - Improve smear protection in these plugins and various APIs (volatilityfoundation#1243)
Context
When working on Linux Page Cache and IDR I realized that Volatility3 doesn't really check if a pointer is valid when doing something like:
What that actually does is check if
ptr != 0
.For instance, when the pointer is zero:
As shown above, in those cases, it works as expected:
inode
evaluates toFalse
, andTrue
is returned due to theor
statement.However, when smear memory happens, the above code will not abort, potentially leading to a crash or incorrect behavior.
The above means that inode evaluated to
True
and theor True
wasn't executed.Volatility3 code assesment
From analyzing the Volatility3 source code, the following three cases were identified:
Volatility3 pointers don't have a
is_valid()
method as in Volatility2. It does have anis_readable()
method, however, it's used in only a few places, and it requires the developer to be aware of this method, something that doesn't seem to be the case for most of us.Developers who are unaware of the
is_readable()
method are usinglayer.is_valid(ptr.vol.offset, ptr.vol.size)
or simplylayer.is_valid(ptr.vol.offset)
instead to verify pointers. However, this requires first obtaining the respective layer, and since it is not used widely, it is likely unknown to most developers.Finally, the remaining developers are assuming and trusting that with simply doing the following will be enough. This applies to most cases in the Volatility3 source code:
Benefits of this Pull Request
This PR takes advantage of the Python3's built-in object truth value testing to verify a pointer has a valid address in its memory layer.
This will provide immediate benefits to those using the source code in (3) and will allow to simplify the source code in (1), (2) and future implementations.
Refer to 305eeda to see how the changes in this PR can benefit the framework.