mirror of https://github.com/xemu-project/xemu.git
linux-user: Emulate CLONE_PIDFD flag in clone()
Add emulation for the CLONE_PIDFD flag of the clone() syscall. This flag was added in Linux kernel 5.2. Successfully tested on a x86-64 Linux host with hppa-linux target. Can be verified by running the testsuite of the qcoro debian package, which breaks hard and kills the currently logged-in user without this patch. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <Y4XoJCpvUA1JD7Sj@p100> [lv: define CLONE_PIDFD if it is not] Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
parent
fe080593dd
commit
895ce8bb53
|
@ -1111,11 +1111,16 @@ UNUSED static const struct flags mmap_flags[] = {
|
||||||
FLAG_END,
|
FLAG_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef CLONE_PIDFD
|
||||||
|
# define CLONE_PIDFD 0x00001000
|
||||||
|
#endif
|
||||||
|
|
||||||
UNUSED static const struct flags clone_flags[] = {
|
UNUSED static const struct flags clone_flags[] = {
|
||||||
FLAG_GENERIC(CLONE_VM),
|
FLAG_GENERIC(CLONE_VM),
|
||||||
FLAG_GENERIC(CLONE_FS),
|
FLAG_GENERIC(CLONE_FS),
|
||||||
FLAG_GENERIC(CLONE_FILES),
|
FLAG_GENERIC(CLONE_FILES),
|
||||||
FLAG_GENERIC(CLONE_SIGHAND),
|
FLAG_GENERIC(CLONE_SIGHAND),
|
||||||
|
FLAG_GENERIC(CLONE_PIDFD),
|
||||||
FLAG_GENERIC(CLONE_PTRACE),
|
FLAG_GENERIC(CLONE_PTRACE),
|
||||||
FLAG_GENERIC(CLONE_VFORK),
|
FLAG_GENERIC(CLONE_VFORK),
|
||||||
FLAG_GENERIC(CLONE_PARENT),
|
FLAG_GENERIC(CLONE_PARENT),
|
||||||
|
|
|
@ -169,9 +169,13 @@
|
||||||
#define CLONE_IGNORED_FLAGS \
|
#define CLONE_IGNORED_FLAGS \
|
||||||
(CLONE_DETACHED | CLONE_IO)
|
(CLONE_DETACHED | CLONE_IO)
|
||||||
|
|
||||||
|
#ifndef CLONE_PIDFD
|
||||||
|
# define CLONE_PIDFD 0x00001000
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Flags for fork which we can implement within QEMU itself */
|
/* Flags for fork which we can implement within QEMU itself */
|
||||||
#define CLONE_OPTIONAL_FORK_FLAGS \
|
#define CLONE_OPTIONAL_FORK_FLAGS \
|
||||||
(CLONE_SETTLS | CLONE_PARENT_SETTID | \
|
(CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_PIDFD | \
|
||||||
CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
|
CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
|
||||||
|
|
||||||
/* Flags for thread creation which we can implement within QEMU itself */
|
/* Flags for thread creation which we can implement within QEMU itself */
|
||||||
|
@ -6730,6 +6734,17 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(__NR_pidfd_open) || !defined(TARGET_NR_pidfd_open)
|
||||||
|
if (flags & CLONE_PIDFD) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Can not allow CLONE_PIDFD with CLONE_PARENT_SETTID */
|
||||||
|
if ((flags & CLONE_PIDFD) && (flags & CLONE_PARENT_SETTID)) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (block_signals()) {
|
if (block_signals()) {
|
||||||
return -QEMU_ERESTARTSYS;
|
return -QEMU_ERESTARTSYS;
|
||||||
}
|
}
|
||||||
|
@ -6757,6 +6772,20 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
|
||||||
ts->child_tidptr = child_tidptr;
|
ts->child_tidptr = child_tidptr;
|
||||||
} else {
|
} else {
|
||||||
cpu_clone_regs_parent(env, flags);
|
cpu_clone_regs_parent(env, flags);
|
||||||
|
if (flags & CLONE_PIDFD) {
|
||||||
|
int pid_fd = 0;
|
||||||
|
#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
|
||||||
|
int pid_child = ret;
|
||||||
|
pid_fd = pidfd_open(pid_child, 0);
|
||||||
|
if (pid_fd >= 0) {
|
||||||
|
fcntl(pid_fd, F_SETFD, fcntl(pid_fd, F_GETFL)
|
||||||
|
| FD_CLOEXEC);
|
||||||
|
} else {
|
||||||
|
pid_fd = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
put_user_u32(pid_fd, parent_tidptr);
|
||||||
|
}
|
||||||
fork_end(0);
|
fork_end(0);
|
||||||
}
|
}
|
||||||
g_assert(!cpu_in_exclusive_context(cpu));
|
g_assert(!cpu_in_exclusive_context(cpu));
|
||||||
|
|
Loading…
Reference in New Issue