From: Ross Burton Date: Fri, 17 Jul 2026 16:25:31 +0000 (+0100) Subject: hwdb: strip the root from filenames when generating hwdb.bin X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ab9be70e94dad2166b4a5b2cf80f6f46ffc9e2c3;p=thirdparty%2Fsystemd.git hwdb: strip the root from filenames when generating hwdb.bin The modern hwdb.bin format contains the filenames of the input data that makes up the database. This is useful but in offline builds where --root is used, the filenames are the full build paths including the specified root. This introduces build paths and thus information leakage and non-reproducible data. Solve this by stripping the root prefix off the original path when passing to import_file. Add TEST-17-UDEV.hwdb.sh to verify that hwdb.bin files contain the path inside the root, but not the path of the root. --- diff --git a/src/shared/hwdb-util.c b/src/shared/hwdb-util.c index b3c48e2a5f6..f6415694e1a 100644 --- a/src/shared/hwdb-util.c +++ b/src/shared/hwdb-util.c @@ -578,7 +578,7 @@ static int import_file(struct trie *trie, int fd, const char *filename, uint16_t } int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool compat) { - _cleanup_free_ char *hwdb_bin = NULL; + _cleanup_free_ char *hwdb_bin = NULL, *root_abs = NULL; _cleanup_(trie_freep) struct trie *trie = NULL; uint16_t file_priority = 1; int r, ret = 0; @@ -588,7 +588,18 @@ int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool co * source. If true, then hwdb.bin will be created without the information. systemd-hwdb command * should set the argument false, and 'udevadm hwdb' command should set it true. */ - hwdb_bin = path_join(root, hwdb_bin_dir ?: "/etc/udev", "hwdb.bin"); + r = empty_or_root_harder_to_null(&root); + if (r < 0) + return log_error_errno(r, "Failed to determine if '%s' points to the root directory: %m", strempty(root)); + + if (root) { + r = path_make_absolute_cwd(root, &root_abs); + if (r < 0) + return log_error_errno(r, "Failed to make '%s' absolute: %m", root); + path_simplify(root_abs); + } + + hwdb_bin = path_join(root_abs, hwdb_bin_dir ?: "/etc/udev", "hwdb.bin"); if (!hwdb_bin) return -ENOMEM; @@ -613,7 +624,7 @@ int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool co CLEANUP_ARRAY(files, n_files, conf_file_free_array); - r = conf_files_list_strv_full(".hwdb", root, + r = conf_files_list_strv_full(".hwdb", root_abs, CONF_FILES_REGULAR | CONF_FILES_FILTER_MASKED | CONF_FILES_WARN, conf_file_dirs, &files, &n_files); if (r < 0) @@ -635,7 +646,13 @@ int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool co ConfFile *c = *i; log_debug("Reading file \"%s\" -> \"%s\"", c->original_path, c->resolved_path); - RET_GATHER(ret, import_file(trie, c->fd, c->original_path, file_priority++, compat)); + + const char *path_in_root = path_startswith_full(c->original_path, + empty_to_root(root_abs), + PATH_STARTSWITH_RETURN_LEADING_SLASH); + assert(path_in_root); + + RET_GATHER(ret, import_file(trie, c->fd, path_in_root, file_priority++, compat)); } strbuf_complete(trie->strings); diff --git a/test/units/TEST-17-UDEV.hwdb.sh b/test/units/TEST-17-UDEV.hwdb.sh new file mode 100755 index 00000000000..c953fbdb27c --- /dev/null +++ b/test/units/TEST-17-UDEV.hwdb.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +set -eux +set -o pipefail + +if ! command -v systemd-hwdb >/dev/null; then + echo "systemd-hwdb not found, skipping." + exit 0 +fi + +# shellcheck source=test/units/util.sh +. "$(dirname "$0")"/util.sh + +at_exit() ( + set +e + + [[ -d "$ROOTFS" ]] && rm -rf "$ROOTFS" +) +trap at_exit EXIT + +ROOTFS="$(mktemp -d -t test-17-udev-hwdb.XXXX)" +HWDB=$ROOTFS/usr/lib/udev/hwdb.d + +mkdir -p "$HWDB" +cat >"$HWDB/99-test.hwdb" <