Bug 1820095 - kernel: execve synthesizes SIGSEGV when failing to load main program segments
Summary: kernel: execve synthesizes SIGSEGV when failing to load main program segments
Keywords:
Status: CLOSED CANTFIX
Alias: None
Product: Red Hat Enterprise Linux 8
Classification: Red Hat
Component: kernel
Version: 8.2
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: rc
: 8.0
Assignee: core-kernel-bot
QA Contact: Kernel General QE
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2020-04-02 09:02 UTC by Florian Weimer
Modified: 2023-08-08 03:24 UTC (History)
3 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2020-04-02 10:28:28 UTC
Type: Bug
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Bugzilla 1817106 0 low CLOSED glibc: ld.so appears to segfault when failing to load very large PT_LOAD segment. 2023-07-18 14:30:35 UTC

Internal Links: 1817106

Description Florian Weimer 2020-04-02 09:02:57 UTC
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.

Comment 1 Oleg Nesterov 2020-04-02 10:28:28 UTC
(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.

Comment 2 Florian Weimer 2020-04-02 11:28:54 UTC
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?

Comment 3 Oleg Nesterov 2020-04-02 17:18:26 UTC
(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.

Comment 4 Eirik Fuller 2020-04-02 18:39:09 UTC
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.

Comment 5 Oleg Nesterov 2020-04-03 10:36:04 UTC
(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.


Note You need to log in before you can comment on or make changes to this bug.