]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hwdb: strip the root from filenames when generating hwdb.bin 43062/head
authorRoss Burton <ross.burton@arm.com>
Fri, 17 Jul 2026 16:25:31 +0000 (17:25 +0100)
committerRoss Burton <ross.burton@arm.com>
Mon, 20 Jul 2026 13:31:15 +0000 (14:31 +0100)
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.

src/shared/hwdb-util.c
test/units/TEST-17-UDEV.hwdb.sh [new file with mode: 0755]

index b3c48e2a5f685d3b6b07f8bbef703e102b7bc8dc..f6415694e1ab814fd693e92b471a7ee62533c1d3 100644 (file)
@@ -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 (executable)
index 0000000..c953fbd
--- /dev/null
@@ -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" <<EOF
+scsi:*
+  ID_TEST=test
+EOF
+
+systemd-hwdb update --root "$ROOTFS" --usr
+
+# check the rootfs path does not appear in hwdb.bin
+run_and_grep -n "$ROOTFS" strings "$ROOTFS/usr/lib/udev/hwdb.bin"
+# check the path in the rootfs does appear in hwdb.bin
+run_and_grep 99-test.hwdb strings "$ROOTFS/usr/lib/udev/hwdb.bin"