On Wed, Jan 26, 2022 at 06:02:25PM +0300, Alexey Dobriyan wrote: > > execve("...", NULL, NULL); > > I personally wrote a program which relies on execve(NULL) to succeed. > It wasn't an exploit, it was test program against IMA-like kernel > "only whitelisted executables can run" feature. > > Test copies and "corrupts" itself by appending \0 to the end, then tries > to reexec itself with execve("/proc/self/exe", NULL, NULL); > main() if run with argc==0 exits with specific error code. > > Appending \0 breaks checksum so working kernel protection scheme must > not allow it, therefore if execve(NULL) succeeded, than the parent > process doing test hard fails. > > Also appending \0 doesn't break ELF structure. In other words, > if executable A is working (and it is working because it is running) > then A||\0 is valid executable as well and will run too. > > This is independent from filesystem layout, libc, kernel, dynamic > libraries, compile options and what not. > > Now QNX doesn't allow execve(NULL) and I don't remember if I changed it > to the next simplest variant and I don't work anymore at that company, > so I can't check :^) > > execve("/proc/self/exe", (char*[]){"Alexey", NULL}, NULL); One of the various suggestions was to inject { path, NULL } when argc=0. Given that execve(path, NULL, ...) is being used at least a little, hopefully there is nothing that depends on argc==0... :P -- Kees Cook