aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2026-05-06 13:11:16 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2026-05-06 14:16:54 +0000
commit748402ebf2d7a08b13d0b21694afdaad55cfa9cd (patch)
tree663206f996e9bcbf9224e367f724090b1b2b1fc1
parent486c2dfaa7b9ed1ed79662584c9b0f4fd0c23d67 (diff)
devmatch: read linker.hints from all module paths
Previously, devmatch would stop at the first linker.hints file found in kern.module_path. This meant modules installed in /boot/modules/ were invisible to devmatch if /boot/kernel/ contained a linker.hints file (which it always does). Merge hints from all directories in kern.module_path. This allows third-party or out-of-tree kernel modules in /boot/modules/ to be auto-loaded by devmatch just like built-in modules. Reviewed by: imp Differential Revivion: https://reviews.freebsd.org/D56847
-rw-r--r--sbin/devmatch/devmatch.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/sbin/devmatch/devmatch.c b/sbin/devmatch/devmatch.c
index 62bfc2c521ed..6c6c5f3bcf79 100644
--- a/sbin/devmatch/devmatch.c
+++ b/sbin/devmatch/devmatch.c
@@ -102,6 +102,9 @@ read_linker_hints(void)
size_t buflen, len;
if (linker_hints == NULL) {
+ void *all_hints = NULL;
+ size_t all_len = 0;
+
if (sysctlbyname("kern.module_path", NULL, &buflen, NULL, 0) < 0)
errx(1, "Can't find kernel module path.");
modpath = malloc(buflen);
@@ -111,13 +114,39 @@ read_linker_hints(void)
errx(1, "Can't find kernel module path.");
p = modpath;
while ((q = strsep(&p, ";")) != NULL) {
+ void *h;
+
snprintf(fn, sizeof(fn), "%s/linker.hints", q);
- hints = read_hints(fn, &len);
- if (hints == NULL)
+ h = read_hints(fn, &len);
+ if (h == NULL)
continue;
- break;
+ if (len < sizeof(int) ||
+ *(int *)(intptr_t)h != LINKER_HINTS_VERSION) {
+ free(h);
+ continue;
+ }
+ if (all_hints == NULL) {
+ all_hints = h;
+ all_len = len;
+ } else {
+ void *merged;
+
+ merged = realloc(all_hints, all_len + len - sizeof(int));
+ if (merged == NULL) {
+ free(h);
+ continue;
+ }
+ all_hints = merged;
+ memcpy((char *)all_hints + all_len,
+ (char *)h + sizeof(int),
+ len - sizeof(int));
+ all_len += len - sizeof(int);
+ free(h);
+ }
}
- if (q == NULL) {
+ hints = all_hints;
+ len = all_len;
+ if (hints == NULL) {
if (quiet_flag)
exit(EX_UNAVAILABLE);
else