]> xenbits.xensource.com Git - unikraft/unikraft.git/commit
lib/posix-process: Define `libc` wrappers for `vfork`
authorSergiu Moga <sergiu@unikraft.io>
Mon, 24 Mar 2025 17:00:35 +0000 (19:00 +0200)
committerUnikraft Bot <monkey@unikraft.io>
Thu, 17 Apr 2025 12:33:46 +0000 (12:33 +0000)
commit846d4ecbdf5f0bc3811f3a7a8f52922414311787
treee93701adfccd085b0979def0620e887569c89068
parentae4cef9a9a3ae16a470fd0bc800f0ad2b3f7d0d3
lib/posix-process: Define `libc` wrappers for `vfork`

It is impossible to write the libc wrapper of the `vfork` system call
in C since the child might end up reusing and overwriting the parent's
return address when it pops it and then calls `execve`, leaving the
parent to return to an invalid state - typically would overwrite it
with the return address from execve, making it look as if the parent
returned from execve.

Userspace libc's solve this by writing the libc wrapper as something
among the lines of:
popq %<register that the syscall guarantees to preserve>
movq $SYS_vfork, %rax
syscall
pushq %<register we popped return address into 3 lines above>
ret

On ARM64 as well as others, clone() with the flags
`SIGCHLD | CLONE_VM | CLONE_VFORK` is called instead but let's just
still use our `vfork` implementation since it essentially also does
the same exact thing.

However, as a Unikernel with function calls for system calls we do
not need to care about any of that, as our execenv prologue can store
and restore everything without touching the stack. Thus, we can write
our native libc wrappers as a basic jump/branch to said prologue.

Signed-off-by: Sergiu Moga <sergiu@unikraft.io>
Approved-by: Michalis Pappas <michalis@unikraft.io>
Reviewed-by: Michalis Pappas <michalis@unikraft.io>
Reviewed-by: Andrei Tatar <andrei@unikraft.io>
GitHub-Closes: #1618
lib/posix-process/Makefile.uk
lib/posix-process/arch/arm64/vfork.S [new file with mode: 0644]
lib/posix-process/arch/x86_64/vfork.S [new file with mode: 0644]