Message ID | Y4XoJCpvUA1JD7Sj@p100 (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | linux-user: Emulate CLONE_PIDFD flag in clone() | expand |
Le 29/11/2022 à 12:08, Helge Deller a écrit : > 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> > > diff --git a/linux-user/strace.c b/linux-user/strace.c > index 9ae5a812cd..8fa5c1ec3d 100644 > --- a/linux-user/strace.c > +++ b/linux-user/strace.c > @@ -1097,6 +1097,7 @@ UNUSED static struct flags clone_flags[] = { > FLAG_GENERIC(CLONE_FS), > FLAG_GENERIC(CLONE_FILES), > FLAG_GENERIC(CLONE_SIGHAND), > + FLAG_GENERIC(CLONE_PIDFD), > FLAG_GENERIC(CLONE_PTRACE), > FLAG_GENERIC(CLONE_VFORK), > FLAG_GENERIC(CLONE_PARENT), > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index 24b25759be..0468a1bad7 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -213,7 +213,7 @@ struct file_clone_range { > > /* Flags for fork which we can implement within QEMU itself */ > #define CLONE_OPTIONAL_FORK_FLAGS \ > - (CLONE_SETTLS | CLONE_PARENT_SETTID | \ > + (CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_PIDFD | \ > CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID) > > /* Flags for thread creation which we can implement within QEMU itself */ > @@ -6747,6 +6747,17 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, > 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()) { > return -QEMU_ERESTARTSYS; > } > @@ -6774,6 +6785,20 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, > ts->child_tidptr = child_tidptr; > } else { > 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); > } > } > Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Le 29/11/2022 à 12:08, Helge Deller a écrit : > 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> > > diff --git a/linux-user/strace.c b/linux-user/strace.c > index 9ae5a812cd..8fa5c1ec3d 100644 > --- a/linux-user/strace.c > +++ b/linux-user/strace.c > @@ -1097,6 +1097,7 @@ UNUSED static struct flags clone_flags[] = { > FLAG_GENERIC(CLONE_FS), > FLAG_GENERIC(CLONE_FILES), > FLAG_GENERIC(CLONE_SIGHAND), > + FLAG_GENERIC(CLONE_PIDFD), > FLAG_GENERIC(CLONE_PTRACE), > FLAG_GENERIC(CLONE_VFORK), > FLAG_GENERIC(CLONE_PARENT), > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index 24b25759be..0468a1bad7 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -213,7 +213,7 @@ struct file_clone_range { > > /* Flags for fork which we can implement within QEMU itself */ > #define CLONE_OPTIONAL_FORK_FLAGS \ > - (CLONE_SETTLS | CLONE_PARENT_SETTID | \ > + (CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_PIDFD | \ > CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID) > > /* Flags for thread creation which we can implement within QEMU itself */ > @@ -6747,6 +6747,17 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, > 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()) { > return -QEMU_ERESTARTSYS; > } > @@ -6774,6 +6785,20 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, > ts->child_tidptr = child_tidptr; > } else { > 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); > } > } > Applied to my linux-user-for-8.0 branch. Thanks, Laurent
diff --git a/linux-user/strace.c b/linux-user/strace.c index 9ae5a812cd..8fa5c1ec3d 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1097,6 +1097,7 @@ UNUSED static struct flags clone_flags[] = { FLAG_GENERIC(CLONE_FS), FLAG_GENERIC(CLONE_FILES), FLAG_GENERIC(CLONE_SIGHAND), + FLAG_GENERIC(CLONE_PIDFD), FLAG_GENERIC(CLONE_PTRACE), FLAG_GENERIC(CLONE_VFORK), FLAG_GENERIC(CLONE_PARENT), diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 24b25759be..0468a1bad7 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -213,7 +213,7 @@ struct file_clone_range { /* Flags for fork which we can implement within QEMU itself */ #define CLONE_OPTIONAL_FORK_FLAGS \ - (CLONE_SETTLS | CLONE_PARENT_SETTID | \ + (CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_PIDFD | \ CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID) /* Flags for thread creation which we can implement within QEMU itself */ @@ -6747,6 +6747,17 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, 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()) { return -QEMU_ERESTARTSYS; } @@ -6774,6 +6785,20 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, ts->child_tidptr = child_tidptr; } else { 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); } }
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>