Initial canonical helper addition

The intel 64-bit 4-page paging mechanism allows for 48-bit virtual
addresses.  They introduced a convention that the higher bits must
be set a particular way to avoid operating system developers abusing
those bits and creating problems that would be difficult to resolve in
the future.

Volatility requires that addresses for mapping or translation fit within
the available bounds of the virtual address space.  This unfortunately
means that addresses that have the protections against abuse in place
can may live outside this range.

This provides two function (canonicalize and decanonicalize) which will
either set the appropriate sign extension or remove it.  The
decanonicalize function will return an adress outside of the address
range if the original value was not canonical.
This commit is contained in:
Mike Auty
2023-01-05 10:55:30 +00:00
parent 92ece08c5f
commit c1e425217b
+22
View File
@@ -56,6 +56,11 @@ class Intel(linear.LinearlyMappedLayer):
)
self._entry_size = struct.calcsize(self._entry_format)
self._entry_number = self.page_size // self._entry_size
self._canonical_prefix = self._mask(
(1 << self._bits_per_register) - 1,
self._bits_per_register,
self._maxvirtaddr,
)
# These can vary depending on the type of space
self._index_shift = int(
@@ -106,6 +111,23 @@ class Intel(linear.LinearlyMappedLayer):
"""Returns whether a particular page is valid based on its entry."""
return bool(entry & 1)
def canonicalize(self, addr: int) -> int:
"""Canonicalizes an address by performing an appropiate sign extension on the higher addresses"""
if self._bits_per_register <= self._maxvirtaddr:
return addr & self.address_mask
elif addr < (1 << self._maxvirtaddr - 1):
return addr
return self._mask(addr, self._maxvirtaddr, 0) + self._canonical_prefix
def decanonicalize(self, addr: int) -> int:
"""Removes canonicalization to ensure an adress fits within the correct range if it has been canonicalized
This will produce an address outside the range if the canonicalization is incorrect
"""
if addr < (1 << self._maxvirtaddr - 1):
return addr
return addr ^ self._canonical_prefix
def _translate(self, offset: int) -> Tuple[int, int, str]:
"""Translates a specific offset based on paging tables.