summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Merey <amerey@redhat.com>2022-04-08 19:37:11 -0400
committerAaron Merey <amerey@redhat.com>2022-04-13 14:52:55 -0400
commit8b568fdea8e1baea3d68cc38dec587e4c9219276 (patch)
treebdf0a8e064e579901da0f527f2bd6fbe93517259
parent399b55a75830f1854c8da9f29282810e82f270b6 (diff)
downloadelfutils-8b568fdea8e1baea3d68cc38dec587e4c9219276.tar.gz
PR29022: 000-permissions files cause problems for backups
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>
-rw-r--r--debuginfod/ChangeLog8
-rw-r--r--debuginfod/debuginfod-client.c94
-rw-r--r--tests/ChangeLog11
-rw-r--r--tests/Makefile.am4
-rwxr-xr-xtests/run-debuginfod-federation-link.sh4
-rwxr-xr-xtests/run-debuginfod-federation-metrics.sh4
-rwxr-xr-xtests/run-debuginfod-federation-sqlite.sh4
-rwxr-xr-xtests/run-debuginfod-negative-cache.sh (renamed from tests/run-debuginfod-000-permission.sh)6
-rwxr-xr-xtests/run-debuginfod-tmp-home.sh2
9 files changed, 90 insertions, 47 deletions
diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog
index 578d951d..d6f7b282 100644
--- a/debuginfod/ChangeLog
+++ b/debuginfod/ChangeLog
@@ -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,
diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index 41ba88a5..58ef6442 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -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);
}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index c195f9f7..6cb0d649 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -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.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b2da2c83..84c3950a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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 \
diff --git a/tests/run-debuginfod-federation-link.sh b/tests/run-debuginfod-federation-link.sh
index 4f043741..d7827436 100755
--- a/tests/run-debuginfod-federation-link.sh
+++ b/tests/run-debuginfod-federation-link.sh
@@ -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
diff --git a/tests/run-debuginfod-federation-metrics.sh b/tests/run-debuginfod-federation-metrics.sh
index 3da457e8..3d716246 100755
--- a/tests/run-debuginfod-federation-metrics.sh
+++ b/tests/run-debuginfod-federation-metrics.sh
@@ -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
diff --git a/tests/run-debuginfod-federation-sqlite.sh b/tests/run-debuginfod-federation-sqlite.sh
index 449df5db..bb3cda12 100755
--- a/tests/run-debuginfod-federation-sqlite.sh
+++ b/tests/run-debuginfod-federation-sqlite.sh
@@ -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
diff --git a/tests/run-debuginfod-000-permission.sh b/tests/run-debuginfod-negative-cache.sh
index 1f46c341..f40e99c5 100755
--- a/tests/run-debuginfod-000-permission.sh
+++ b/tests/run-debuginfod-negative-cache.sh
@@ -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
diff --git a/tests/run-debuginfod-tmp-home.sh b/tests/run-debuginfod-tmp-home.sh
index 4256f6f2..5946777a 100755
--- a/tests/run-debuginfod-tmp-home.sh
+++ b/tests/run-debuginfod-tmp-home.sh
@@ -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