diff --git a/volatility3/framework/constants/_version.py b/volatility3/framework/constants/_version.py index 07b9e45ec3..7f71c277e7 100644 --- a/volatility3/framework/constants/_version.py +++ b/volatility3/framework/constants/_version.py @@ -1,7 +1,7 @@ # We use the SemVer 2.0.0 versioning scheme VERSION_MAJOR = 2 # Number of releases of the library with a breaking change -VERSION_MINOR = 26 # Number of changes that only add to the interface -VERSION_PATCH = 2 # Number of changes that do not change the interface +VERSION_MINOR = 27 # Number of changes that only add to the interface +VERSION_PATCH = 0 # Number of changes that do not change the interface VERSION_SUFFIX = "" PACKAGE_VERSION = ( diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index c980ee6b17..a97cf2a5a4 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -1094,14 +1094,11 @@ def get_vma_iter(self) -> Iterable[interfaces.objects.ObjectInterface]: vm_area_struct objects """ for vma in self._do_get_vma_iter(): - try: - vma.vm_start - vma.vm_end - vma.get_protection() - - yield vma - except exceptions.InvalidAddressException: + if not vma.is_valid(): vollog.debug(f"Skipping invalid vm_area_struct at {vma.vol.offset:#x}") + continue + + yield vma class super_block(objects.StructType): @@ -1237,6 +1234,39 @@ def _parse_flags(self, vm_flags, parse_flags) -> str: retval = retval + "-" return retval + def is_valid(self) -> bool: + """Validate a VMA struct to prevent processing smeared entries.""" + try: + start = self.vm_start + end = self.vm_end + self.get_protection() + except exceptions.InvalidAddressException: + return False + + layer = self._context.layers[self.vol.layer_name] + length = end - start + if ( + (start > end) + or (start == 0 and length == 0) + or (length % layer.page_size != 0) + ): + return False + + if self.vm_file != 0: + try: + inode = self.vm_file.get_inode() + except exceptions.InvalidAddressException: + return False + + # Verify that a file-backed VMA's page offset + # is not greater than the size of the file's inode. + # Check only inode sizes greater than 0 to account for + # special devices (e.g. "/dev/dri/card0") and prevent false negatives. + if inode.i_size > 0 and self.get_page_offset() > inode.i_size: + return False + + return True + # only parse the rwx bits def get_protection(self) -> str: return self._parse_flags(self.vm_flags & 0b1111, vm_area_struct.perm_flags)