On Sun, Sep 17, 2023 at 10:39 PM Karim Taha <kariem.taha...@gmail.com> wrote:
> From: Stacey Son <s...@freebsd.org> > > Signed-off-by: Stacey Son <s...@freebsd.org> > Signed-off-by: Karim Taha <kariem.taha...@gmail.com> > Reviewed-by: Richard Henderson <richard.hender...@linaro.org> > --- > bsd-user/freebsd/os-proc.h | 39 +++++++++++++++++++++++++++++++++++ > bsd-user/freebsd/os-syscall.c | 4 ++++ > 2 files changed, 43 insertions(+) > Reviewed-by: Warner Losh <i...@bsdimp.com> > diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h > index 14478d4bb5..a406ef7db8 100644 > --- a/bsd-user/freebsd/os-proc.h > +++ b/bsd-user/freebsd/os-proc.h > @@ -212,4 +212,43 @@ static inline abi_long do_freebsd_vfork(void *cpu_env) > return do_freebsd_fork(cpu_env); > } > > +/* rfork(2) */ > +static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags) > +{ > + abi_long ret; > + abi_ulong child_flag; > + > + /* > + * XXX We need to handle RFMEM here, as well. Neither are safe to > execute > + * as-is on x86 hosts because they'll split memory but not the stack, > + * wreaking havoc on host architectures that use the stack to store > the > + * return address as both threads try to pop it off. Rejecting > RFSPAWN > + * entirely for now is ok, the only consumer at the moment is > posix_spawn > + * and it will fall back to classic vfork(2) if we return EINVAL. > + */ > + if ((flags & TARGET_RFSPAWN) != 0) { > + return -TARGET_EINVAL; > + } > + fork_start(); > + ret = rfork(flags); > + if (ret == 0) { > + /* child */ > + child_flag = 1; > + target_cpu_clone_regs(cpu_env, 0); > + } else { > + /* parent */ > + child_flag = 0; > + } > + > + /* > + * The fork system call sets a child flag in the second return > + * value: 0 for parent process, 1 for child process. > + */ > + set_second_rval(cpu_env, child_flag); > + fork_end(child_flag); > + > + return ret; > + > +} > + > #endif /* BSD_USER_FREEBSD_OS_PROC_H */ > diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c > index cb9425c9ba..4c4e773d1d 100644 > --- a/bsd-user/freebsd/os-syscall.c > +++ b/bsd-user/freebsd/os-syscall.c > @@ -234,6 +234,10 @@ static abi_long freebsd_syscall(void *cpu_env, int > num, abi_long arg1, > ret = do_freebsd_vfork(cpu_env); > break; > > + case TARGET_FREEBSD_NR_rfork: /* rfork(2) */ > + ret = do_freebsd_rfork(cpu_env, arg1); > + break; > + > case TARGET_FREEBSD_NR_execve: /* execve(2) */ > ret = do_freebsd_execve(arg1, arg2, arg3); > break; > -- > 2.42.0 > >