]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
PR29022: 000-permissions files cause problems for backups
authorAaron Merey <amerey@redhat.com>
Fri, 8 Apr 2022 23:37:11 +0000 (19:37 -0400)
committerAaron Merey <amerey@redhat.com>
Wed, 13 Apr 2022 18:52:55 +0000 (14:52 -0400)
000-permission files currently used for negative caching can cause
permission problems for some backup software and disk usage checkers.
Fix this by using empty files for negative caching instead.

Also use each empty file's mtime to determine the time since
last download attempt instead of the cache_miss_s file's mtime.

https://sourceware.org/bugzilla/show_bug.cgi?id=29022

Tested-by: Milian Wolff <mail@milianw.de>
Signed-off-by: Aaron Merey <amerey@redhat.com>
debuginfod/ChangeLog
debuginfod/debuginfod-client.c
tests/ChangeLog
tests/Makefile.am
tests/run-debuginfod-federation-link.sh
tests/run-debuginfod-federation-metrics.sh
tests/run-debuginfod-federation-sqlite.sh
tests/run-debuginfod-negative-cache.sh [moved from tests/run-debuginfod-000-permission.sh with 92% similarity]
tests/run-debuginfod-tmp-home.sh

index 578d951d010242f7661a391892fa309d163cb089..d6f7b2822f258faa9d7fe9c996b032c46c5cade4 100644 (file)
@@ -1,3 +1,11 @@
+2022-04-13  Aaron Merey  <amerey@redhat.com>
+
+       * debuginfod-client.c (debuginfod_query_server):
+       Drop st_mode check. Add st_size > 0 check.
+       Save target_mtime before calling
+       debuginfod_config_cache. unlink target_cache_path
+       on EACCESS. Create target_cache_path with DEFFILEMODE.
+
 2022-04-03  Frank Ch. Eigler <fche@redhat.com>
 
        * debuginfod.cxx (main): Use single dual-stack daemon setup,
index 41ba88a56911696ea41a45c80c5c4ee6df1130eb..58ef64427ed423a52182f1af19b5121fb732f4fe 100644 (file)
@@ -138,7 +138,7 @@ static const char *cache_clean_interval_filename = "cache_clean_interval_s";
 static const long cache_clean_default_interval_s = 86400; /* 1 day */
 
 /* The cache_miss_default_s within the debuginfod cache specifies how
-   frequently the 000-permision file should be released.*/
+   frequently the empty file should be released.*/
 static const long cache_miss_default_s = 600; /* 10 min */
 static const char *cache_miss_filename = "cache_miss_s";
 
@@ -767,42 +767,66 @@ debuginfod_query_server (debuginfod_client *c,
   if (rc != 0)
     goto out;
 
-  struct stat st;
-  /* 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)
+  /* Check if the target is already in the cache. */
+  int fd = open(target_cache_path, O_RDONLY);
+  if (fd >= 0)
     {
-      time_t cache_miss;
-
-      rc = debuginfod_config_cache(cache_miss_path, cache_miss_default_s, &st);
-      if (rc < 0)
-        goto out;
+      struct stat st;
+      if (fstat(fd, &st) != 0)
+        {
+          rc = -errno;
+          close (fd);
+          goto out;
+        }
 
-      cache_miss = (time_t)rc;
-      if (time(NULL) - st.st_mtime <= cache_miss)
+      /* If the file is non-empty, then we are done. */
+      if (st.st_size > 0)
         {
-         rc = -ENOENT;
-         goto out;
-       }
+          if (path != NULL)
+            {
+              *path = strdup(target_cache_path);
+              if (*path == NULL)
+                {
+                  rc = -errno;
+                  close (fd);
+                  goto out;
+                }
+            }
+          /* Success!!!! */
+          rc = fd;
+          goto out;
+        }
       else
-        /* TOCTOU non-problem: if another task races, puts a working
-           download or a 000 file in its place, unlinking here just
-           means WE will try to download again as uncached. */
-        unlink(target_cache_path);
-    }
-  
-  /* If the target is already in the cache (known not-000 - 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;
+        {
+          /* The file is empty. Attempt to download only if enough time
+             has passed since the last attempt. */
+          time_t cache_miss;
+          time_t target_mtime = st.st_mtime;
+          rc = debuginfod_config_cache(cache_miss_path,
+                                       cache_miss_default_s, &st);
+          if (rc < 0)
+            {
+              close(fd);
+              goto out;
+            }
+
+          cache_miss = (time_t)rc;
+          if (time(NULL) - target_mtime <= cache_miss)
+            {
+              close(fd);
+              rc = -ENOENT;
+              goto out;
+            }
+          else
+            /* TOCTOU non-problem: if another task races, puts a working
+               download or an empty file in its place, unlinking here just
+               means WE will try to download again as uncached. */
+            unlink(target_cache_path);
+        }
     }
+  else if (errno == EACCES)
+    /* Ensure old 000-permission files are not lingering in the cache. */
+    unlink(target_cache_path);
 
   long timeout = default_timeout;
   const char* timeout_envvar = getenv(DEBUGINFOD_TIMEOUT_ENV_VAR);
@@ -1298,11 +1322,11 @@ debuginfod_query_server (debuginfod_client *c,
         }
     } while (num_msg > 0);
 
-  /* Create a 000-permission file named as $HOME/.cache if the query
-     fails with ENOENT.*/
+  /* Create an empty file named as $HOME/.cache if the query fails
+     with ENOENT.*/
   if (rc == -ENOENT)
     {
-      int efd = open (target_cache_path, O_CREAT|O_EXCL, 0000);
+      int efd = open (target_cache_path, O_CREAT|O_EXCL, DEFFILEMODE);
       if (efd >= 0)
         close(efd);
     }
index c195f9f702913bc687b28fee15cf6b1eb478a6b5..6cb0d64986bc4328b7c12ff79d2b4b20c3f900ba 100644 (file)
@@ -1,3 +1,14 @@
+2022-04-13  Aaron Merey  <amerey@redhat.com>
+
+       * Makefile.am (TESTS): Remove run-debuginfod-000-permission.sh
+       and add run-debuginfod-negative-cache.sh.
+       (EXTRA_DIST): Likewise.
+       * run-debuginfod-federation-link.sh: Update comments about
+       negative-hit file.
+       * run-debuginfod-federation-metrics.sh: Likewise.
+       * run-debuginfod-federation-sqlite.sh: Likewise.
+       * run-debuginfod-tmp-home.sh: Likewise.
+
 2022-03-20  Mark Wielaard  <mark@klomp.org>
 
        * run-large-elf-file.sh: Check elf class of addsections binary.
index b2da2c83e15aedf1519af4d82afffb9ee0f666dc..84c3950a185da2fd2ea1f0e78ff348da9d0c7f67 100644 (file)
@@ -227,7 +227,7 @@ TESTS += run-debuginfod-dlopen.sh \
         run-debuginfod-file.sh \
         run-debuginfod-sizetime.sh \
         run-debuginfod-malformed.sh \
-        run-debuginfod-000-permission.sh \
+        run-debuginfod-negative-cache.sh \
         run-debuginfod-tmp-home.sh \
         run-debuginfod-writable.sh \
         run-debuginfod-no-urls.sh \
@@ -529,7 +529,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
             run-debuginfod-sizetime.sh \
             run-debuginfod-dlopen.sh \
             run-debuginfod-malformed.sh \
-            run-debuginfod-000-permission.sh \
+            run-debuginfod-negative-cache.sh \
             run-debuginfod-tmp-home.sh \
             run-debuginfod-writable.sh \
             run-debuginfod-no-urls.sh \
index 4f043741bc2af5c23b6506dae8d353e362705eb6..d782743604c292c401b606352f9d0be7bb138f89 100755 (executable)
@@ -136,7 +136,7 @@ file -L L/foo
 export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1
 rm -rf $DEBUGINFOD_CACHE_PATH
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
-rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop 000-perm negative-hit file
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
 export DEBUGINFOD_URLS=http://127.0.0.1:$PORT2
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
 
@@ -144,7 +144,7 @@ testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
 export DEBUGINFOD_URLS=127.0.0.1:$PORT1
 rm -rf $DEBUGINFOD_CACHE_PATH
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
-rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop 000-perm negative-hit file
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
 export DEBUGINFOD_URLS=127.0.0.1:$PORT2
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
 
index 3da457e8b42036cbd91ef41192a7fe98fef96bf1..3d7162466e532cb4dfd9f355de46875565aac388 100755 (executable)
@@ -130,7 +130,7 @@ file -L L/foo
 export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1
 rm -rf $DEBUGINFOD_CACHE_PATH
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
-rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop 000-perm negative-hit file
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
 export DEBUGINFOD_URLS=http://127.0.0.1:$PORT2
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
 
@@ -138,7 +138,7 @@ testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
 export DEBUGINFOD_URLS=127.0.0.1:$PORT1
 rm -rf $DEBUGINFOD_CACHE_PATH
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
-rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop 000-perm negative-hit file
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
 export DEBUGINFOD_URLS=127.0.0.1:$PORT2
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
 # test parallel queries in client
index 449df5dbec240d8a0d75b13c2f6480eb8f409320..bb3cda1293ce5fc769c1f7567ff4276267649da7 100755 (executable)
@@ -117,7 +117,7 @@ file -L L/foo
 export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1
 rm -rf $DEBUGINFOD_CACHE_PATH
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
-rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop 000-perm negative-hit file
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
 export DEBUGINFOD_URLS=http://127.0.0.1:$PORT2
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
 
@@ -125,7 +125,7 @@ testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
 export DEBUGINFOD_URLS=127.0.0.1:$PORT1
 rm -rf $DEBUGINFOD_CACHE_PATH
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
-rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop 000-perm negative-hit file
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
 export DEBUGINFOD_URLS=127.0.0.1:$PORT2
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
 # test parallel queries in client
similarity index 92%
rename from tests/run-debuginfod-000-permission.sh
rename to tests/run-debuginfod-negative-cache.sh
index 1f46c34199bb58e5ad4838420621b052af85e4fa..f40e99c562bac019e85e5880d23faf121ee00d1c 100755 (executable)
@@ -46,15 +46,15 @@ ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
 # 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.
+# The query is designed to fail, while the empty file should be created.
 testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo 01234567 || true
 if [ ! -f $DEBUGINFOD_CACHE_PATH/01234567/debuginfo ]; then
   echo "could not find cache in $DEBUGINFOD_CACHE_PATH"
   err
 fi
 
-if [ `stat -c "%A" $DEBUGINFOD_CACHE_PATH/01234567/debuginfo` != "----------" ]; then
-  echo "The cache $DEBUGINFOD_CACHE_PATH/01234567/debuginfo is readable"
+if [ `stat -c "%s" $DEBUGINFOD_CACHE_PATH/01234567/debuginfo` != 0 ]; then
+  echo "The cache $DEBUGINFOD_CACHE_PATH/01234567/debuginfo is not empty"
   err
 fi
 
index 4256f6f28a91b95997c6ce986afa8a7405f81d92..5946777a79721d66e4aa08b5dfd4c8f1497d1309 100755 (executable)
@@ -104,7 +104,7 @@ fi
 # priority over $HOME/.cache, $XDG_CACHE_HOME.
 cp -vr $DEBUGINFOD_CACHE_PATH tmphome/.debuginfod_client_cache || true
 # ||true is for tolerating errors, such a valgrind or something else
-#        leaving 000-perm files in there
+#        leaving negative-hit files in there
 
 # Add a file that doesn't exist in $HOME/.cache, $XDG_CACHE_HOME.
 mkdir tmphome/.debuginfod_client_cache/deadbeef