summaryrefslogtreecommitdiff
path: root/debuginfod/debuginfod.cxx
diff options
context:
space:
mode:
authorDi Chen <dichen@redhat.com>2021-08-20 13:03:21 +0800
committerMark Wielaard <mark@klomp.org>2021-08-27 19:40:55 +0200
commitd3f914023abcd6ae76b168da97518e5e7dbd761a (patch)
treed5f3ed04d6a459eb858ef0a4906f389b8fcff01a /debuginfod/debuginfod.cxx
parent610623458b7e98ed3e912e4b7ca8050f6ce4c698 (diff)
downloadelfutils-d3f914023abcd6ae76b168da97518e5e7dbd761a.tar.gz
debuginfod: PR27917 - protect against federation loops
If someone misconfigures a debuginfod federation to have loops, and a nonexistent buildid lookup is attempted, bad things will happen, as is documented. This patch aims to reduce the risk by adding an option to debuginfod that functions kind of like an IP packet's TTL: a limit on the length of XFF: header that debuginfod is willing to process. If X-Forwarded-For: exceeds N hops, it will not delegate a local lookup miss to upstream debuginfods. Commit ab38d167c40c99 causes federation loops for non-existent resources to result in multiple temporary deadlocks, each lasting for $DEBUGINFOD_TIMEOUT seconds. Since concurrent requests for each unique resource are now serialized, federation loops can result in one server thread waiting to acquire a lock while the server thread holding the lock waits for the first thread to respond to an http request. This PR can help protect against the above multiple temporary deadlocks behaviour. Ex. if --forwarded-ttl-limit=0 then the timeout behaviour of local loops should be avoided. https://sourceware.org/bugzilla/show_bug.cgi?id=27917 Signed-off-by: Di Chen <dichen@redhat.com>
Diffstat (limited to 'debuginfod/debuginfod.cxx')
-rw-r--r--debuginfod/debuginfod.cxx18
1 files changed, 18 insertions, 0 deletions
diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
index b560fdcb..6e182a84 100644
--- a/debuginfod/debuginfod.cxx
+++ b/debuginfod/debuginfod.cxx
@@ -374,6 +374,8 @@ static const struct argp_option options[] =
#define ARGP_KEY_FDCACHE_PREFETCH_FDS 0x1006
{ "fdcache-prefetch-fds", ARGP_KEY_FDCACHE_PREFETCH_FDS, "NUM", 0,"Number of files allocated to the \
prefetch cache.", 0},
+#define ARGP_KEY_FORWARDED_TTL_LIMIT 0x1007
+ {"forwarded-ttl-limit", ARGP_KEY_FORWARDED_TTL_LIMIT, "NUM", 0, "Limit of X-Forwarded-For hops, default 8.", 0},
{ NULL, 0, NULL, 0, NULL, 0 },
};
@@ -421,6 +423,7 @@ static long fdcache_prefetch;
static long fdcache_mintmp;
static long fdcache_prefetch_mbs;
static long fdcache_prefetch_fds;
+static unsigned forwarded_ttl_limit = 8;
static string tmpdir;
static void set_metric(const string& key, double value);
@@ -553,6 +556,9 @@ parse_opt (int key, char *arg,
if( fdcache_mintmp > 100 || fdcache_mintmp < 0 )
argp_failure(state, 1, EINVAL, "fdcache mintmp percent");
break;
+ case ARGP_KEY_FORWARDED_TTL_LIMIT:
+ forwarded_ttl_limit = (unsigned) atoi(arg);
+ break;
case ARGP_KEY_ARG:
source_paths.insert(string(arg));
break;
@@ -1880,6 +1886,17 @@ handle_buildid (MHD_Connection* conn,
if (xff != "")
xff += string(", "); // comma separated list
+ unsigned int xff_count = 0;
+ for (auto&& i : xff){
+ if (i == ',') xff_count++;
+ }
+
+ // if X-Forwarded-For: exceeds N hops,
+ // do not delegate a local lookup miss to upstream debuginfods.
+ if (xff_count >= forwarded_ttl_limit)
+ throw reportable_exception(MHD_HTTP_NOT_FOUND, "not found, --forwared-ttl-limit reached \
+and will not query the upstream servers");
+
// Compute the client's numeric IP address only - so can't merge with conninfo()
const union MHD_ConnectionInfo *u = MHD_get_connection_info (conn,
MHD_CONNECTION_INFO_CLIENT_ADDRESS);
@@ -3718,6 +3735,7 @@ main (int argc, char *argv[])
obatched(clog) << "groom time " << groom_s << endl;
obatched(clog) << "prefetch fds " << fdcache_prefetch_fds << endl;
obatched(clog) << "prefetch mbs " << fdcache_prefetch_mbs << endl;
+ obatched(clog) << "forwarded ttl limit " << forwarded_ttl_limit << endl;
if (scan_archives.size()>0)
{