Hi Frank,
On Thu, 2021-09-30 at 14:36 -0400, Frank Ch. Eigler via Elfutils-devel
wrote:
> @@ -766,24 +766,14 @@ debuginfod_query_server (debuginfod_client *c,
> 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;
> @@ -797,6 +787,18 @@ debuginfod_query_server (debuginfod_client *c,
> 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;
> + }
Isn't this a time-of-check to time-of-use (TOCTOU) race now?
At least for the root user?
> long timeout = default_timeout;
> const char* timeout_envvar = getenv(DEBUGINFOD_TIMEOUT_ENV_VAR);
> diff --git a/tests/ChangeLog b/tests/ChangeLog
> index 578e8cb15502..e5aca513f1e8 100644
> --- a/tests/ChangeLog
> +++ b/tests/ChangeLog
> @@ -1,3 +1,9 @@
> +2021-09-30 Frank Ch. Eigler <[email protected]>
> +
> + PR28240
> + * run-debuginfod-000-permission.sh, -writable.sh:
> + Correct negative-cache file permission checking.
> +
> 2021-09-30 Frank Ch. Eigler <[email protected]>
>
> * run-debuginfod-*.sh: Use ! CMD to assert expected failure.
> diff --git a/tests/run-debuginfod-000-permission.sh b/tests/run-
> debuginfod-000-permission.sh
> index 8480ad486886..301ce7e7d9d3 100755
> --- a/tests/run-debuginfod-000-permission.sh
> +++ b/tests/run-debuginfod-000-permission.sh
> @@ -56,7 +56,7 @@ if [ ! -f $DEBUGINFOD_CACHE_PATH/01234567/debuginfo
> ]; then
> err
> fi
>
> -if [ -r $DEBUGINFOD_CACHE_PATH/01234567/debuginfo ]; then
> +if [ `stat -c "%A" $DEBUGINFOD_CACHE_PATH/01234567/debuginfo` != "
> ----------" ]; then
> echo "The cache $DEBUGINFOD_CACHE_PATH/01234567/debuginfo is
> readable"
> err
> fi
> diff --git a/tests/run-debuginfod-artifact-running.sh b/tests/run-
> debuginfod-artifact-running.sh
> index 51fa9c0a40bd..b94444267ade 100755
> --- a/tests/run-debuginfod-artifact-running.sh
> +++ b/tests/run-debuginfod-artifact-running.sh
> @@ -90,10 +90,6 @@ wait_ready $PORT1 'thread_busy{role="scan"}' 0
> rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests
> filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find
> debuginfo $BUILDID`
> cmp $filename F/prog.debug
> -if [ -w $filename ]; then
> - echo "cache file writable, boo"
> - err
> -fi
I assume you are just removing the test here, instead of replacing,
because it is already tested in the next one?
> filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find
> executable F/prog`
> cmp $filename F/prog
> diff --git a/tests/run-debuginfod-writable.sh b/tests/run-debuginfod-
> writable.sh
> index 69ececb39454..9cc4ea1db92c 100755
> --- a/tests/run-debuginfod-writable.sh
> +++ b/tests/run-debuginfod-writable.sh
> @@ -79,7 +79,7 @@ wait_ready $PORT1 'thread_busy{role="scan"}' 0
> rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests
> filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find
> debuginfo $BUILDID`
> cmp $filename F/p+r%o\$g.debug
> -if [ -w $filename ]; then
> +if [ `stat -c "%A" $filename` != "-r--------" ]; then
> echo "cache file writable, boo"
> err
> fi
Cheers,
Mark