diff options
author | Masahiro Yamada | 2020-06-01 14:57:18 +0900 |
---|---|---|
committer | Masahiro Yamada | 2020-06-06 23:38:13 +0900 |
commit | f531c1b5de65bc687bdcca69e7649fe2db5b6d87 (patch) | |
tree | ae7ada97d1cd77e9826c4d35cfa334096f9fb0b7 | |
parent | ac5100f54329676469688d1b5415cd8d6428c909 (diff) |
modpost: fix potential mmap'ed file overrun in get_src_version()
I do not know how reliably this function works, but it looks dangerous
to me.
strchr(sources, '\n');
... continues searching until it finds '\n' or it reaches the '\0'
terminator. In other words, 'sources' should be a null-terminated
string.
However, grab_file() just mmaps a file, so 'sources' is not terminated
with null byte. If the file does not contain '\n' at all, strchr() will
go beyond the mmap'ed memory.
Use read_text_file(), which loads the file content into a malloc'ed
buffer, appending null byte.
Here we are interested only in the first line of *.mod files. Use
get_line() helper to get the first line.
This also makes missing *.mod file a fatal error.
Commit 4be40e22233c ("kbuild: do not emit src version warning for
non-modules") ignored missing *.mod files.
I do not fully understand what that commit addressed, but commit
91341d4b2c19 ("kbuild: introduce new option to enhance section mismatch
analysis") introduced partial section checks by using modpost. built-in.o
was parsed by modpost. Even modules had a problem because *.mod files
were created after the modpost check.
Commit b7dca6dd1e59 ("kbuild: create *.mod with full directory path and
remove MODVERDIR") stopped doing that. Now that modpost is only invoked
after the directory descend, *.mod files should always exist at the
modpost stage.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
-rw-r--r-- | scripts/mod/sumversion.c | 28 |
1 files changed, 11 insertions, 17 deletions
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index f27f22420cbc..5fb142db6195 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -392,40 +392,34 @@ out: /* Calc and record src checksum. */ void get_src_version(const char *modname, char sum[], unsigned sumlen) { - void *file; - unsigned long len; + char *buf, *pos, *firstline; struct md4_ctx md; - char *sources, *end, *fname; + char *fname; char filelist[PATH_MAX + 1]; /* objects for a module are listed in the first line of *.mod file. */ snprintf(filelist, sizeof(filelist), "%.*smod", (int)strlen(modname) - 1, modname); - file = grab_file(filelist, &len); - if (!file) - /* not a module or .mod file missing - ignore */ - return; + buf = read_text_file(filelist); - sources = file; - - end = strchr(sources, '\n'); - if (!end) { + pos = buf; + firstline = get_line(&pos); + if (!firstline) { warn("bad ending versions file for %s\n", modname); - goto release; + goto free; } - *end = '\0'; md4_init(&md); - while ((fname = strsep(&sources, " ")) != NULL) { + while ((fname = strsep(&firstline, " "))) { if (!*fname) continue; if (!(is_static_library(fname)) && !parse_source_files(fname, &md)) - goto release; + goto free; } md4_final_ascii(&md, sum, sumlen); -release: - release_file(file, len); +free: + free(buf); } |