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

Linux - PROT_NONE, L1TF mitigation and layer address translation fix #1335

Conversation

gcmoreira
Copy link
Contributor

This PR introduces improvements and fixes for address translation in the Linux Intel layers

PROT_NONE pages

First, this PR fixes one of the oldest issues in the queue #134, adding support for PROT_NONE protected pages.

Using the @gleeda PoC from their excellent post Using mprotect PROT_NONE on Linux.

$ ./victim 
PID 2116
buffer at 0x76f63a132000       <= PROT_NONE vma
buffer2 at 0x76f63a133000

Before:

>>> task.pid
2116

>>> proc_layer.read(0x76F63A133000, 10)
b'not here\x00\x00'

>>> proc_layer.read(0x76F63A132000, 10)
Traceback (most recent call last):
  File "/home/user/vol3/volatility3/framework/layers/linear.py", line 45, in read
    for offset, _, mapped_offset, mapped_length, layer in self.mapping(
  File "/home/user/vol3/volatility3/framework/layers/intel.py", line 295, in mapping
    for offset, size, mapped_offset, mapped_size, map_layer in self._mapping(
  File "/home/user/vol3/volatility3/framework/layers/intel.py", line 351, in _mapping
    chunk_offset, page_size, layer_name = self._translate(offset)
  File "/home/user/vol3/volatility3/framework/layers/intel.py", line 159, in _translate
    raise exceptions.PagedInvalidAddressException(
volatility3.framework.exceptions.PagedInvalidAddressException: Page Fault at entry 0x40fffffed82d920 in page entry

After:

>>> proc_layer.read(0x76F63A133000, 10)
b'not here\x00\x00'

>>> proc_layer.read(0x76F63A132000, 10)
b'find me\x00\x00\x00'

Intel Side Channel Vulnerability L1TF mitigation.

In 2018, to mitigate Intel's L1TF (L1 Terminal Fault) vulnerability, that code in Linux kernel was again updated in this commit, incorporating PTE inversion to calculate the PFN. This PR includes support for handling these cases as well.

__PHYSICAL_MASK_SHIFT and _maxphyaddr

While addressing the previous issues, I found that the changes didn't work for older kernels. After further investigation, it turned out the problem was the physical_mask and the reason was this commit.

In the Linux kernel, the __PHYSICAL_MASK_SHIFT is a mask used to extract the physical address from a PTE. In Volatility3, this is referred to as _maxphyaddr.

Until kernel version 4.17, Linux x86-64 used a 46-bit mask. With this commit, this was extended to 52 bits, applying to both 4 and 5-level page tables.

We previously used 52 bits for all Intel 64-bit systems, but this produced incorrect results for PROT_NONE pages. Since the mask value is defined by a preprocessor macro, it's difficult to detect the exact bit shift used in the current kernel.
Using 46 bits has proven reliable for our use case, as seen in tools like crashtool. See this and this.

Copy link
Member

@ikelos ikelos left a comment

Choose a reason for hiding this comment

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

Roughly happy with the concept, but needs to be more accurate on what's linux and what's general Intel. I'm a little concern that we're exposing the guts of the layer and that not that many parameters need to be accessible by the OS/outside the layer (we did name method starting with _ for a reason). If we're happy it's all important and necessary then it's not far off getting merged.

volatility3/framework/layers/intel.py Outdated Show resolved Hide resolved
volatility3/framework/layers/intel.py Outdated Show resolved Hide resolved
volatility3/framework/layers/intel.py Outdated Show resolved Hide resolved
volatility3/framework/constants/linux/__init__.py Outdated Show resolved Hide resolved
volatility3/framework/layers/intel.py Outdated Show resolved Hide resolved
@gcmoreira
Copy link
Contributor Author

Hey @ikelos, I believe everything has been addressed in this PR. Are you waiting on anything else from me, or it's just you haven't had a chance to review it yet?

Copy link
Member

@ikelos ikelos left a comment

Choose a reason for hiding this comment

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

Ok, still can't entirely see why some of those need pulling out into properties rather than just one off variables defined at the class level, but I accept the point about documenting clearly. I'd prefer not to let ~ sneak in, but I'm pretty sure Andrew managed to sneak some in in the past, so I'll let it slide if you want. Just shout when you want it merged.

Also, this is a deep change to the core Intel layer, so after merge please keep a close eye on general use for the first week or two after merge, and longer term for tickets that might be because of this for a couple months. I've cut the release branch before this so that we get a few more months testing of it before it goes live.

# Note that within the Intel class it's a class method. However, since it uses
# complement operations and we are working in Python, it would be more careful to
# limit it to the architecture's pointer size.
return ~(self.page_size - 1) & self._register_mask
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I'm not a big fan of ~ in python, just because python ints can be any size. If you're happy this will work properly I'll accept it, but I'd prefer some maths using the known actual limit to form the complement...

Copy link
Contributor Author

@gcmoreira gcmoreira Nov 27, 2024

Choose a reason for hiding this comment

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

Yep, that's exactly what I was trying to explain in that comment :) .. it's safe when there's an AND with a mask like that one.
Actually, that's a bug (or let's say, an unsafe usage) of the current Intel implementation that this PR addresses.
See https://github.com/volatilityfoundation/volatility3/blob/develop/volatility3/framework/layers/intel.py#L89

Copy link
Member

Choose a reason for hiding this comment

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

Any chance you could submit a separate PR to fix that one up (or at least file a bug against it) please?

volatility3/framework/layers/intel.py Show resolved Hide resolved
@ikelos ikelos merged commit 0233193 into volatilityfoundation:develop Nov 27, 2024
12 checks passed
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.

2 participants