PR28240 patch: debuginfod-client negative-hit caching for root user

2021-08-18 Thread Frank Ch. Eigler via Elfutils-devel
Hi -

Important patch.


commit d2cbc610a9e6552f663e29136d19597b8fdcf832 (HEAD -> master)
Author: Frank Ch. Eigler 
Date:   Wed Aug 18 18:29:34 2021 -0400

PR28240: debuginfod client root-safe negative caching

Negative cache (000-permission) files were incorrectly treated as
valid cached files for the root user, because root can open even
000-perm files without -EACCES.  Corrected this checking sequence.

Fixed the debuginfod testsuite to run to completion as root or
as an ordinary user, correcting corresponding permission checks:
stat -c %A $FILE
is right and
[ -w $FILE]  [ -r $FILE ]
were wrong.  Fixed related testsuite inconsistencies to assert
subprocess errors (rc != 0), where
   ! CMD
is right and
   CMD && false || true
and similar were wrong.

Signed-off-by: Frank Ch. Eigler 

diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog
index 9e82d78d2d4e..76155e69e51c 100644
--- a/debuginfod/ChangeLog
+++ b/debuginfod/ChangeLog
@@ -1,8 +1,14 @@
+2021-08-18  Frank Ch. Eigler  
+
+   PR28240
+   * debuginfod-client.c (debuginfod_query_server): Correct
+   negative-hit cache check sequence for root user.
+
 2021-07-26  Noah Sanci  
 
PR27982
* debuginfod-client.c (globals): added default_maxsize and
default_maxtime.
(debuginfod_query_server): Added DEBUGINFOD_MAXSIZE and
DEBUGINFOD_MAXTIME envvar processing.
* debuginfod.cxx (handler_cb): If the requested file exceeds
diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index 7d4b220f30dc..be15736b3ebd 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -726,47 +726,49 @@ debuginfod_query_server (debuginfod_client *c,
 
   rc = debuginfod_init_cache(cache_path, interval_path, maxage_path);
   if (rc != 0)
 goto out;
   rc = debuginfod_clean_cache(c, cache_path, interval_path, maxage_path);
   if (rc != 0)
 goto out;
 
-  /* If the target is already in the cache then we are done.  */
-  int fd = open (target_cache_path, O_RDONLY);
-  if (fd >= 0)
-{
-  /* Success */
-  if (path != NULL)
-*path = strdup(target_cache_path);
-  rc = fd;
-  goto out;
-}
-
   struct stat st;
-  time_t cache_miss;
-  /* Check if the file exists and it's of permission 000*/
-  if (errno == EACCES
-  && stat(target_cache_path, &st) == 0
+  /* Check if the file exists and it's of permission 000; must check
+ explicitly rather than trying to open it first (PR28240). */
+  if (stat(target_cache_path, &st) == 0
   && (st.st_mode & 0777) == 0)
 {
+  time_t cache_miss;
+
   rc = debuginfod_config_cache(cache_miss_path, cache_miss_default_s, &st);
   if (rc < 0)
 goto out;
 
   cache_miss = (time_t)rc;
   if (time(NULL) - st.st_mtime <= cache_miss)
 {
  rc = -ENOENT;
  goto out;
}
   else
 unlink(target_cache_path);
 }
+  
+  /* If the target is already in the cache, and not a 000 file (PR28240), 
+ then we are done. */
+  int fd = open (target_cache_path, O_RDONLY);
+  if (fd >= 0)
+{
+  /* Success */
+  if (path != NULL)
+*path = strdup(target_cache_path);
+  rc = fd;
+  goto out;
+}
 
   long timeout = default_timeout;
   const char* timeout_envvar = getenv(DEBUGINFOD_TIMEOUT_ENV_VAR);
   if (timeout_envvar != NULL)
 timeout = atoi (timeout_envvar);
 
   if (vfd >= 0)
 dprintf (vfd, "using timeout %ld\n", timeout);
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 3bfd1ca224fb..6366bb19bacf 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,8 +1,15 @@
+2021-08-18  Frank Ch. Eigler  
+
+   PR28240
+   * run-debuginfod-find.sh: Correct XFAIL (rc!=0) subprocess
+   invocation syntax throughout.  Correct negative-cache
+   file permission checking.
+
 2021-08-04  Mark Wielaard  
 
PR28190
* backtrace.c (callback_verify): Check for pthread_kill as first
frame. Change asserts to fprintf plus abort.
 
 2021-07-26  Noah Sanci  
 
diff --git a/tests/run-debuginfod-find.sh b/tests/run-debuginfod-find.sh
index 991d1dc57164..bccd33051969 100755
--- a/tests/run-debuginfod-find.sh
+++ b/tests/run-debuginfod-find.sh
@@ -203,52 +203,52 @@ if [ -f ${DEBUGINFOD_CACHE_PATH}/${BUILDID} ]; then
   echo "File cached after maxtime check"
   err
 fi
 
 # PR25628
 rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests
 
 # The query is designed to fail, while the 000-permission file should be 
created.
-testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo 01234567 || 
true
+! testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo 01234567
 if [ ! -f $DEBUGINFOD_CACHE_PATH/01234567/debuginfo ]; then
   echo "could not find cache in $DEBUGINFOD_CACHE_PATH"
   err
 fi
 
-if [ -r $DEBUGIN

Re: [PATCH] debuginfod: PR27917 - protect against federation loops

2021-08-18 Thread Frank Ch. Eigler via Elfutils-devel
Hi -

> 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. [...]

Thank you very much!


> Commit ab38d167c40c99 causes federation loops for non-existent
> resources to result in multiple temporary livelocks, each lasting
> for $DEBUGINFOD_TIMEOUT seconds. [...]

(FWIW, the term "livelock" is not quite right here, try just
"deadlock".)

The patch looks functional, and thank you also for including the
docs and test case.  Thorough enough!


> @@ -1862,6 +1869,12 @@ handle_buildid (MHD_Connection* conn,
>// We couldn't find it in the database.  Last ditch effort
>// is to defer to other debuginfo servers.
> 
> +  // if X-Forwarded-For: exceeds N hops,
> +  // do not delegate a local lookup miss to upstream debuginfods.
> +  if (disable_query_server)
> +throw reportable_exception(MHD_HTTP_NOT_FOUND, "not found,
> --forwared-ttl-limit reached \
> +and will not query the upstream servers");

One part I don't understand is why you added the code to check for XFF
length into handler_cb(), and then passed the disable_query_server
result flag to this function.  Was there some reason not to perform
the XFF comma-counting right here?


- FChE