Description of problem: When execve cannot map LOAD segments in the main executable, it creates a new process that immediately dies with SIGSEGV, without running any code. This is very confusing to users, as can be seen from bug 1817106. Version-Release number of selected component (if applicable): kernel-4.18.0-193.el8.x86_64 How reproducible: Compile this program and run it (this may need adjustments for very large systems which can successfully allocate 512 GiB of memory): char large_data[1LL << 39]; int main (void) { } Steps to Reproduce: 1. gcc reproducer.c 2. ./a.out Actual results: The shell reports: Segmentation fault Expected results: The execve system call should fail with ENOMEM, resulting in a more understandable error message from the shell.
(In reply to Florian Weimer from comment #0) > > char large_data[1LL << 39]; > > int > main (void) > { > } > > Steps to Reproduce: > 1. gcc reproducer.c > 2. ./a.out > > Actual results: > > The shell reports: Segmentation fault Yes, > Expected results: > > The execve system call should fail with ENOMEM, resulting in a more > understandable error message from the shell. but this is impossible :/ The old VM was already destroyed, the process simply cannot return to userspace.
Yuck, I didn't consider this. Thanks. Would it be possible to communicate somehow the cause of the SIGSEGV in the siginfo_t value provided by waitid?
(In reply to Florian Weimer from comment #2) > > Would it be possible to communicate somehow the cause of the SIGSEGV in the > siginfo_t value provided by waitid? Unfortunately no. The only additional info you can get from this siginfo_t (compared to wait(&status)) is pid/uid.
The ENOMEM from execve is visible in strace output immediately before strace reports the SIGSEGV, so while the shell can't easily report it, it can be seen with suitable tool usage. The SIGSEGV comes from search_binary_handler (the force_sigsegv(SIGSEGV, current) line), called by exec_binprm, called by __do_execve_file, in fs/exec.c; I have not yet found documentation for this behavior, unless https://lkml.org/lkml/2013/2/15/572 qualifies as such. It appears there was already precedent for killing processes in response to execve failures, but the patch in that message (or something very similar like https://github.com/torvalds/linux/commit/19d860a140beac48a1377f179e693abe86a9dac9) seems mostly responsible for the present behavior.
(In reply to Eirik Fuller from comment #4) > > The ENOMEM from execve is visible in strace output immediately before strace > reports the SIGSEGV, so while the shell can't easily report it, it can be > seen with suitable tool usage. Yes, > It appears there was already precedent for killing processes in response to > execve failures, but the patch in that message (or something very similar > like > https://github.com/torvalds/linux/commit/ > 19d860a140beac48a1377f179e693abe86a9dac9) seems mostly responsible for the > present behavior. No really, this patch cleanups the "suicide" logic we always had. Once again, the execing task simply can't return to usermode after de_thread/ exec_mmap, sys_execve() does return the error code, strace can report it, but this task can't. IOW, consider sys_execve(...); printf("exec failed"); if execve fails after original VM is already destroyed, the code above no longer exist, its page is already freed.