diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index 41a7d9288..4aff317a5 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -2103,6 +2103,10 @@ class xdp_sock(objects.StructType): class bpf_prog(objects.StructType): + _BPF_PROG_CHUNK_SHIFT = 6 + _BPF_PROG_CHUNK_SIZE = 1 << _BPF_PROG_CHUNK_SHIFT + _BPF_PROG_CHUNK_MASK = ~(_BPF_PROG_CHUNK_SIZE - 1) + def get_type(self) -> Union[str, None]: """Returns a string with the eBPF program type""" @@ -2147,6 +2151,58 @@ class bpf_prog(objects.StructType): return self.aux.get_name() + def bpf_jit_binary_hdr_address(self) -> int: + """Return the jitted BPF program start address + Based on bpf_jit_binary_hdr() + + Returns: + The BPF program address + """ + vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self) + vmlinux_layer = vmlinux.context.layers[vmlinux.layer_name] + + # In 5.18 (33c9805860e584b194199cab1a1e81f4e6395408) <= kernels < 6.0 (1d5f82d9dd477d5c66e0214a68c3e4f308eadd6d) + # 'bpf_prog_aux' has a 'use_bpf_prog_pack' member + bpf_prog_aux_has_use_bpf_prog_pack = vmlinux.get_type( + "bpf_prog_aux" + ).has_member("use_bpf_prog_pack") + if bpf_prog_aux_has_use_bpf_prog_pack and self.aux.use_bpf_prog_pack: + long_mask = (1 << vmlinux_layer.bits_per_register) - 1 + addr_mask = self._BPF_PROG_CHUNK_MASK & long_mask + else: + addr_mask = vmlinux_layer.page_mask + + real_start = self.bpf_func + return real_start & addr_mask + + def get_address_region(self) -> Tuple[int, int]: + """Returns the start and end memory addresses of the BPF program. + Based on bpf_get_prog_addr_region() + + Returns: + A tuple with the addresses representing the memory range (start, end) of the BPF program. + """ + vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self) + vmlinux_layer = vmlinux.context.layers[vmlinux.layer_name] + # Based on bpf_get_prog_addr_region() + bpf_start_address = self.bpf_jit_binary_hdr_address() + + if vmlinux.has_type("bpf_binary_header"): + # kernels >= 3.11 314beb9bcabfd6b4542ccbced2402af2c6f6142a + bpf_binary_header = vmlinux.object( + object_type="bpf_binary_header", offset=bpf_start_address, absolute=True + ) + pages = bpf_binary_header.pages + else: + # kernels < 3.11 The first member is always the size + pages = vmlinux.object( + object_type="unsigned int", offset=bpf_start_address, absolute=True + ) + + bpf_end_address = bpf_start_address + pages * vmlinux_layer.page_size + + return bpf_start_address, bpf_end_address + class bpf_prog_aux(objects.StructType): def get_name(self) -> Union[str, None]: