klp-build's elf_create_file() fails with EINVAL when the build directory path is long enough to truncate the "XXXXXX" suffix in the 256-byte tmp_name buffer. Increase the buffer to PATH_MAX and add a truncation check to ensure a valid template string for mkstemp().
Signed-off-by: Joe Lawrence <[email protected]> --- tools/objtool/elf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) Repro notes: # Consider a looooong path like: $ LONG_DIR=tests/gitlab.com/joe.lawrence/kernel-tests/-/archive/klp-build/kernel-tests-klp-build.tar.gz/general/kpatch/patch-upgrade/kpatch/kernel/BUILD/kernel-6.12.0-178.1964_2250006255.el10/linux-6.12.0-178.1964_2250006255.el10.x86_64 # Place the source repo within the long path $ mkdir -p /tmp/"$LONG_DIR" $ cd /tmp/"$LONG_DIR" $ git clone --depth=1 --branch=v6.19-rc4 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git $ cd linux # Grab a sample patch $ wget https://raw.githubusercontent.com/dynup/kpatch/refs/heads/master/examples/cmdline-string.patch # Basic config for livepatching ... $ make -j$(nproc) defconfig $ ./scripts/config --file .config \ --set-val CONFIG_FTRACE y \ --set-val CONFIG_KALLSYMS_ALL y \ --set-val CONFIG_FUNCTION_TRACER y \ --set-val CONFIG_DYNAMIC_FTRACE y \ --set-val CONFIG_DYNAMIC_DEBUG y \ --set-val CONFIG_LIVEPATCH y $ make olddefconfig # BAD BUILD, mkstemp() unhappy: $ ./scripts/livepatch/klp-build -T cmdline-string.patch Validating patch(es) Building original kernel Copying original object files Fixing patch(es) Building patched kernel Copying patched object files Diffing objects vmlinux.o: changed function: cmdline_proc_show vmlinux.o: error: objtool [elf.c:1233]: elf_create_file: can't create tmp file failed: Invalid argument error: klp-build: objtool klp diff failed error: klp-build: line 657: '( cd "$ORIG_DIR"; "${cmd[@]}" > >(tee -a "$log") 2> >(tee -a "$log" | "${filter[@]}" 1>&2) || die "objtool klp diff failed" )' # GOOD BUILD, with PATH_MAX buffer for mkstemp(): $ ./scripts/livepatch/klp-build -S 3 -T cmdline-string.patch Diffing objects vmlinux.o: changed function: cmdline_proc_show Building patch module: livepatch-cmdline-string.ko SUCCESS diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index 2c02c7b49265..836575876741 100644 --- a/tools/objtool/elf.c +++ b/tools/objtool/elf.c @@ -15,6 +15,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <limits.h> #include <errno.h> #include <libgen.h> #include <ctype.h> @@ -1192,6 +1193,7 @@ struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name) char *dir, *base, *tmp_name; struct symbol *sym; struct elf *elf; + int path_len; elf_version(EV_CURRENT); @@ -1219,13 +1221,17 @@ struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name) base = basename(base); - tmp_name = malloc(256); + tmp_name = malloc(PATH_MAX); if (!tmp_name) { ERROR_GLIBC("malloc"); return NULL; } - snprintf(tmp_name, 256, "%s/%s.XXXXXX", dir, base); + path_len = snprintf(tmp_name, PATH_MAX, "%s/%s.XXXXXX", dir, base); + if (path_len >= PATH_MAX) { + ERROR_GLIBC("snprintf"); + return NULL; + } elf->fd = mkstemp(tmp_name); if (elf->fd == -1) { -- 2.52.0
