Add cache to `is_linux` call (#2978)

* Add cache to avoid calling is_linux dozens of times

* Move variable out of loop

* Replace another usage of 'not .is_linux()' to .is_baremetal()

* Rename is_baremetal() -> is_pagefault_supported() (and invert meaning)

* Update pwndbg/aglib/memory.py

---------

Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>
pull/2984/head
OBarronCS 7 months ago committed by GitHub
parent 02335839dd
commit bc8d5d418f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -414,3 +414,20 @@ def resolve_renamed_struct_field(struct_name: str, possible_field_names: Set[str
return field_name
raise ValueError(f"Field name did not match any of {possible_field_names}.")
@pwndbg.lib.cache.cache_until("start", "objfile")
def is_pagefault_supported() -> bool:
"""
This function should be called before stray memory dereferences to protect against the following situations:
1. On embedded systems, it's not uncommon for MMIO regions to exist where memory reads might mutate the hardware/process state.
2. On baremetal/embedded, paging doesn't always exist, so all memory is "valid" (and often initialized to zero) - this makes every value appear to be a pointer.
As such, we disable dereferencing by default for bare metal targets.
See more discussion here: https://github.com/pwndbg/pwndbg/pull/385
"""
# TODO: use a better detection method
return pwndbg.dbg.selected_inferior().is_linux()

@ -47,7 +47,7 @@ def find_upper_stack_boundary(stack_ptr: int, max_pages: int = 1024) -> int:
# We can't get the stack size from stack layout and page fault on bare metal mode,
# so we return current page as a walkaround.
if not pwndbg.dbg.selected_inferior().is_linux():
if not pwndbg.aglib.memory.is_pagefault_supported():
return stack_ptr + pwndbg.aglib.memory.PAGE_SIZE
return pwndbg.aglib.memory.find_upper_boundary(stack_ptr, max_pages)

@ -84,7 +84,7 @@ def explore(address_maybe: int) -> pwndbg.lib.memory.Page | None:
Also assumes the entire contiguous section has the same permission.
"""
if not pwndbg.dbg.selected_inferior().is_linux():
if not pwndbg.aglib.memory.is_pagefault_supported():
return None
if auto_explore.value == "warn":

@ -59,6 +59,9 @@ def get(
limit = int(limit)
result = [address] if include_start else []
is_pagefault_supported = pwndbg.aglib.memory.is_pagefault_supported()
for _ in range(limit):
# Don't follow cycles, except to stop at the second occurrence.
if result.count(address) >= 2:
@ -71,11 +74,10 @@ def get(
try:
address = address + offset
# Avoid redundant dereferences in bare metal mode by checking
# if address is in any of vmmap pages
if not pwndbg.dbg.selected_inferior().is_linux() and not pwndbg.aglib.vmmap.find(
address
):
# On embedded systems, it's non uncommon for MMIO regions to exist where memory reads might mutate the hardware/process state.
# This check prevents the memory dereferences to protect against this case.
# See discussion here: https://github.com/pwndbg/pwndbg/pull/385
if not is_pagefault_supported and not pwndbg.aglib.vmmap.find(address):
break
next_address = int(

Loading…
Cancel
Save