diff options
| author | Jack Pearson <jack@pearson.onl> | 2023-02-28 15:42:46 -0800 |
|---|---|---|
| committer | Alejandro Colomar <alx@kernel.org> | 2023-03-01 22:28:32 +0100 |
| commit | 184ecd225079567aa3dede2b63c7ddf962cfdbdf (patch) | |
| tree | 8f9bc2202956e5eb3d53123d6e5096354903bed5 | |
| parent | b2a916b48219db3ce744b991425fbae1fb7a3baf (diff) | |
| download | man-pages-184ecd225079567aa3dede2b63c7ddf962cfdbdf.tar.gz | |
clone.2: Note EINVAL when exit_signal + bad flags
Document that Linux will report EINVAL when exit_signal is specified and
either CLONE_THREAD or CLONE_PARENT is specified.
From clone3_args_valid in Linux:
```
if ((kargs->flags & (CLONE_THREAD | CLONE_PARENT)) &&
kargs->exit_signal)
return false;
```
I have verified that this happens on my kernel with a small program:
```
#include <stdio.h>
#include <linux/sched.h>
#include <signal.h>
#include <sys/syscall.h>
#include <unistd.h>
int main(void)
{
struct clone_args ca = {
.flags = CLONE_THREAD | CLONE_SIGHAND | CLONE_VM,
.exit_signal = SIGCHLD, // comment me out to fix error
.set_tid_size = 0,
};
syscall(SYS_clone3, &ca, sizeof(struct clone_args));
perror("");
}
```
And I have verified that this doesn't happen with normal `clone` through
the glibc helper:
```
#define _GNU_SOURCE
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <sys/mman.h>
int do_nothing(void *_) { return 0; }
int main(void)
{
void *map = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
void *stack_top = map + 0x10000 - 1;
clone(do_nothing, stack_top,
CLONE_THREAD | CLONE_VM | CLONE_SIGHAND | SIGCHLD, NULL);
perror("");
}
```
Signed-off-by: Jack Pearson <jack@pearson.onl>
Cc: "Carlos O'Donell" <carlos@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
| -rw-r--r-- | man2/clone.2 | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/man2/clone.2 b/man2/clone.2 index d63895189e..be802a2800 100644 --- a/man2/clone.2 +++ b/man2/clone.2 @@ -1436,6 +1436,16 @@ One of the PIDs specified in .I set_tid was an invalid. .TP +.BR EINVAL " (" clone3 "() only)" +.\" commit 7f192e3cd316ba58c88dfa26796cf77789dd9872 +.B CLONE_THREAD +or +.B CLONE_PARENT +was specified in the +.I flags +mask, but a signal was specified in +.I exit_signal. +.TP .BR EINVAL " (AArch64 only, Linux 4.6 and earlier)" .I stack was not aligned to a 128-bit boundary. |
