diff --git a/CHANGELOG.md b/CHANGELOG.md index 08e1257eb..3bcdbd48e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ The table below shows which release corresponds to each branch, and what date th - [#2328][2328] Lookup using $PATHEXT file extensions in `which` on Windows - [#2189][2189] Explicitly define p64/u64 functions for IDE support - [#2339][2339] Fix: Allow setting attributes on gdb Breakpoints +- [#2323][2323] Retry failed lookups after one week in libcdb [2242]: https://github.com/Gallopsled/pwntools/pull/2242 [2277]: https://github.com/Gallopsled/pwntools/pull/2277 @@ -99,6 +100,7 @@ The table below shows which release corresponds to each branch, and what date th [2328]: https://github.com/Gallopsled/pwntools/pull/2328 [2189]: https://github.com/Gallopsled/pwntools/pull/2189 [2339]: https://github.com/Gallopsled/pwntools/pull/2339 +[2323]: https://github.com/Gallopsled/pwntools/pull/2323 ## 4.12.0 (`beta`) diff --git a/pwnlib/libcdb.py b/pwnlib/libcdb.py index 0fb186b7f..142c95d23 100644 --- a/pwnlib/libcdb.py +++ b/pwnlib/libcdb.py @@ -5,6 +5,7 @@ from __future__ import division import os +import time import six import tempfile @@ -29,6 +30,9 @@ urls = os.environ['DEBUGINFOD_URLS'].split(' ') DEBUGINFOD_SERVERS = urls + DEBUGINFOD_SERVERS +# Retry failed lookups after some time +NEGATIVE_CACHE_EXPIRY = 60 * 60 * 24 * 7 # 1 week + # https://gitlab.com/libcdb/libcdb wasn't updated after 2019, # but still is a massive database of older libc binaries. def provider_libcdb(hex_encoded_id, hash_type): @@ -109,6 +113,10 @@ def search_by_hash(hex_encoded_id, hash_type='build_id', unstrip=True): cache, cache_valid = _check_elf_cache('libcdb', hex_encoded_id, hash_type) if cache_valid: return cache + + # We searched for this buildid before, but didn't find anything. + if cache is None: + return None # Run through all available libc database providers to see if we have a match. for provider in PROVIDERS: @@ -141,6 +149,10 @@ def _search_debuginfo_by_hash(base_url, hex_encoded_id): cache, cache_valid = _check_elf_cache('libcdb_dbg', hex_encoded_id, 'build_id') if cache_valid: return cache + + # We searched for this buildid before, but didn't find anything. + if cache is None: + return None # Try to find separate debuginfo. url = '/buildid/{}/debuginfo'.format(hex_encoded_id) @@ -191,8 +203,11 @@ def _check_elf_cache(cache_type, hex_encoded_id, hash_type): data = read(cache) if not data.startswith(b'\x7FELF'): - log.info_once("Skipping unavailable ELF %s", hex_encoded_id) - return cache, False + # Retry failed lookups after some time + if time.time() > os.path.getmtime(cache) + NEGATIVE_CACHE_EXPIRY: + return cache, False + log.info_once("Skipping invalid cached ELF %s", hex_encoded_id) + return None, False log.info_once("Using cached data from %r", cache) return cache, True