DF-0024 / fix.diff
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -809,6 +809,18 @@ } else { kldname = NULL; modname = file; + /* + * Reject bare module names too long to safely assemble in + * linker_search_path (prefix + sep + name + ".ko" + NUL must + * fit in MAXPATHLEN). 32 is a conservative overhead covering + * any reasonable linker_path prefix plus separator, ".ko" and + * the NUL terminator. Without this check linker_search_path() + * overflows its kmalloc(MAXPATHLEN) buffer via strcpy(). + */ + if (strlen(modname) > MAXPATHLEN - 32) { + error = ENAMETOOLONG; + goto out; + } } lockmgr(&kld_lock, LK_EXCLUSIVE); @@ -1458,6 +1470,10 @@ buf = kmalloc(MAXPATHLEN, M_LINKER, M_WAITOK); cp = linker_path; name_len = strlen(name); + size_t ext_max = 0; + for (ext = exts; *ext != NULL; ext++) + if (strlen(*ext) > ext_max) + ext_max = strlen(*ext); for (;;) { /* find the end of this component */ for (ep = cp; (*ep != 0) && (*ep != ';'); ep++) @@ -1469,6 +1485,13 @@ else sep = 0; + /* Skip components whose assembly would overflow MAXPATHLEN */ + if (prefix_len + sep + name_len + ext_max + 1 > MAXPATHLEN) { + if (*ep == 0) + break; + cp = ep + 1; + continue; + } result = buf; strncpy(result, cp, prefix_len); if (sep) |