diff --git a/elfutils-0.189-debuginfod_config_cache-double-close.patch b/elfutils-0.189-debuginfod_config_cache-double-close.patch new file mode 100644 index 0000000..3380b71 --- /dev/null +++ b/elfutils-0.189-debuginfod_config_cache-double-close.patch @@ -0,0 +1,73 @@ +diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c +index ef4d47e3..d92d8d62 100644 +--- a/debuginfod/debuginfod-client.c ++++ b/debuginfod/debuginfod-client.c +@@ -248,7 +248,7 @@ debuginfod_write_callback (char *ptr, size_t size, size_t nmemb, void *data) + + /* handle config file read and write */ + static int +-debuginfod_config_cache(char *config_path, ++debuginfod_config_cache(debuginfod_client *c, char *config_path, + long cache_config_default_s, + struct stat *st) + { +@@ -277,17 +277,27 @@ debuginfod_config_cache(char *config_path, + } + + long cache_config; ++ /* PR29696 - NB: When using fdopen, the file descriptor is NOT ++ dup'ed and will be closed when the stream is closed. Manually ++ closing fd after fclose is called will lead to a race condition ++ where, if reused, the file descriptor will compete for its ++ regular use before being incorrectly closed here. */ + FILE *config_file = fdopen(fd, "r"); + if (config_file) + { + if (fscanf(config_file, "%ld", &cache_config) != 1) +- cache_config = cache_config_default_s; +- fclose(config_file); ++ cache_config = cache_config_default_s; ++ if (0 != fclose (config_file) && c->verbose_fd >= 0) ++ dprintf (c->verbose_fd, "fclose failed with %s (err=%d)\n", ++ strerror (errno), errno); + } + else +- cache_config = cache_config_default_s; +- +- close (fd); ++ { ++ cache_config = cache_config_default_s; ++ if (0 != close (fd) && c->verbose_fd >= 0) ++ dprintf (c->verbose_fd, "close failed with %s (err=%d)\n", ++ strerror (errno), errno); ++ } + return cache_config; + } + +@@ -303,7 +313,7 @@ debuginfod_clean_cache(debuginfod_client *c, + struct stat st; + + /* Create new interval file. */ +- rc = debuginfod_config_cache(interval_path, ++ rc = debuginfod_config_cache(c, interval_path, + cache_clean_default_interval_s, &st); + if (rc < 0) + return rc; +@@ -320,7 +330,7 @@ debuginfod_clean_cache(debuginfod_client *c, + utime (interval_path, NULL); + + /* Read max unused age value from config file. */ +- rc = debuginfod_config_cache(max_unused_path, ++ rc = debuginfod_config_cache(c, max_unused_path, + cache_default_max_unused_age_s, &st); + if (rc < 0) + return rc; +@@ -1110,7 +1135,7 @@ debuginfod_query_server (debuginfod_client *c, + + close(fd); /* no need to hold onto the negative-hit file descriptor */ + +- rc = debuginfod_config_cache(cache_miss_path, ++ rc = debuginfod_config_cache(c, cache_miss_path, + cache_miss_default_s, &st); + if (rc < 0) + goto out; diff --git a/elfutils.spec b/elfutils.spec index 7955ff1..c27e88f 100644 --- a/elfutils.spec +++ b/elfutils.spec @@ -1,6 +1,6 @@ Name: elfutils Version: 0.189 -%global baserelease 2 +%global baserelease 3 Release: %{baserelease}%{?dist} URL: http://elfutils.org/ %global source_url ftp://sourceware.org/pub/elfutils/%{version}/ @@ -80,6 +80,8 @@ Patch2: elfutils-0.189-c99-compat.patch Patch3: elfutils-0.189-elfcompress.patch # libelf: Replace list of elf_getdata_rawchunk results with a tree Patch4: elfutils-0.189-elf_getdata_rawchunk.patch +# PR29696: Removed secondary fd close in cache config causing race condition +Patch5: elfutils-0.189-debuginfod_config_cache-double-close.patch %description Elfutils is a collection of utilities, including stack (to show @@ -448,8 +450,9 @@ exit 0 %systemd_postun_with_restart debuginfod.service %changelog -* Thu Jun 22 2023 Mark Wielaard +* Thu Jun 22 2023 Mark Wielaard - 0.189-3 - Add elfutils-0.189-elf_getdata_rawchunk.patch +- Add elfutils-0.189-debuginfod_config_cache-double-close.patch * Sat Apr 22 2023 Mark Wielaard - 0.189-2 - Add elfutils-0.189-c99-compat.patch