From 68faee11e868d70f5f79e58eeb1d5bfcc112c471 Mon Sep 17 00:00:00 2001 From: Ryan Stone Date: Tue, 7 Jan 2020 16:03:11 +0000 Subject: [PATCH] rtld: Fix segfault in direct exec mode When rtld is directly executed with arguments, it has to move the program arguments, environment and elf aux data up a few slots to remove its own arguments before the process being executed sees them. When copying the environment, rtld was incorrectly testing whether the location about to be written to currently contained NULL, when was supposed to check whether it had just copied the NULL terminator of the environment string. This had the result that the ELF aux data was mostly treated as environment variables, and rtld would quickly crash when it tried to access required ELF aux data that it didn't think was present. Differential Revision: https://reviews.freebsd.org/D23008 Reviewed by: kib MFC after: 1 month --- libexec/rtld-elf/rtld.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 2c7162f3d31..54fa9f609fc 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -514,12 +514,13 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) argv[i] = argv[i + rtld_argc]; *argcp -= rtld_argc; environ = env = envp = argv + main_argc + 1; + dbg("move env from %p to %p", envp + rtld_argc, envp); do { *envp = *(envp + rtld_argc); - envp++; - } while (*envp != NULL); + } while (*envp++ != NULL); aux = auxp = (Elf_Auxinfo *)envp; auxpf = (Elf_Auxinfo *)(envp + rtld_argc); + dbg("move aux from %p to %p", auxpf, aux); /* XXXKIB insert place for AT_EXECPATH if not present */ for (;; auxp++, auxpf++) { *auxp = *auxpf;