A synchronous, single-threaded interface for starting processes on Linux

Related tags

Miscellaneoussfork
Overview

Summary

sfork is a prototype for a new system call on Linux which provides a synchronous, single-threaded interface for starting processes.

sfork can be viewed as a variation on vfork which does the minimal amount of work required to make vfork actually useful and usable. In particular, sfork removes all the traditional restrictions vfork has on what you can do in the child process.

Interface

The raw interface is identical to the usual prototypes on Linux for vfork, exit, and execveat:

int sfork();
int sfork_exit(int status);
int sfork_execveat(int dirfd, const char* pathname, char *const argv[],
                   char *const envp[], int flags);

However, unlike traditional fork and vfork, sfork only ever returns once. sfork always returns 0 on success, or a negative value if forking failed for any of the usual reasons, like a cap on the number of processes.

The pid, then, is obtained from the return value of exit or execveat. Of course, those system calls don’t usually return, hence the need to wrap them with sfork-supporting equivalents.

In other words, the control flow for sfork is different from the control flow for fork and vfork.

Control flow for fork and vfork proceeds as below. Each line is numbered according to the order in which it is reached. (Error checking is omitted for simplicity)

int ret; // 1
printf("I'm in the parent"); // 2
ret = vfork();  // 3 and 7
if (ret == 0) { // 4 and 8
  printf("I'm in the child"); // 5
  exec(); // 6
} else {
  printf("I'm in the parent once again"); // 9
  printf("Pid of child is %d", ret); // 10
}

Control flow for sfork proceeds like this (again, with error checking omitted):

int ret; // 1
printf("I'm in the parent"); // 2
sfork();  // 3
printf("I'm in the child"); // 4
ret = exec(); // 5
printf("I'm in the parent once again"); // 6
printf("Pid of child is %d", ret); // 7

Control flow works like that naturally in any language that calls sfork, like any other normal function call.

For example, with the Python wrapper, exceptions thrown in the child automatically propagate up. The subprocess() contextmanager in the Python wrapper catches exceptions, automatically calls exit(1) to exit the child process context and re-enter the parent process context, and rethrows the exception. So if a user application encounters an error while setting up the child, the error is naturally and easily propagated up.

A clean way to understand sfork, is to view it as moving a single existing thread of control from an existing process context, the parent, to a new, fresh process context, the child, which starts off sharing its address space with the parent.

In this view, after a call to sfork, exec is an overloaded operation which does three things: Creates a new address space inside the current process context and loads the executable into it, creates a new thread starting at the executable entry point in the current process context and the new address space, and returns the current thread to the parent process context.

And exit, after a call to sfork, just destroys the current process context (setting the exit code), and returns the current thread to the parent process context.

In this view, sfork actually is much more like unshare than fork or vfork. Like unshare, sfork creates a new execution context and moves the current thread into that execution context. Unfortunately, sfork cannot currently be implemented with unshare; see the discussion in appropriate section below.

Userspace implementation

Recall that vfork shares the memory space between the parent process and child process, and blocks the thread in the parent process that executes vfork. The thread in the parent process is unblocked when the child process calls either exec or exit.

The kernel, when implementing vfork, saves the parent process’s registers and restores them after the parent is resumed. To achieve the behavior of sfork, we would rather the kernel just not save and restore the registers at all, but rather, just continue control flow from the point of the child process’s exec.

If you view vfork as just moving a single thread of control between processes, then the fact that the kernel saves the registers of this thread at the point of calling vfork, and then restores them when calling exec or exit, becomes obviously unnecessary: Merely not doing that save and restore gives us sfork. Without that save and restore, we get a single continuous control flow without any jumps.

So all that the sfork wrapper does is perform the exact opposite jump of the kernel: It saves the child process’s registers at the point of exec or exit, and restore those child registers immediately after the parent process is resumed with the parent’s saved registers. This register save/restore exactly counteracts the kernel’s register save/restore.

Possible implementation using unshare

Instead of calling vfork to create a new process context, sfork could call unshare(CLONE_SIGHAND|CLONE_FILES|CLONE_FS) to create a new process context and move the current thread into it.

Then, instead of calling exec, we would call clone(new_stack, CLONE_VM) while inside the new process context, with an appropriately set up new_stack to immediately call exec.

Then to return to the parent process context, we would call setns(procfd, CLONE_SIGHAND|CLONE_FILES|CLONE_FS), where procfd is a file descriptor pointing to the parent process context.

The main missing piece here is that there’s no way to get a file descriptor representing the parent process context, and setns does not support passing any of CLONE_SIGHAND|CLONE_FILES|CLONE_FS, so there’s no way for the thread to return to the parent process.

Also, unshare doesn’t allow calling CLONE_SIGHAND in multi-threaded applications, for good reason. Properly dealing with signals will be tricky.

Also, unshare doesn’t allow calling CLONE_VM in multi-threaded applications, for reasons which are unclear to me. I think that could be changed to be allowed.

Also, calling clone(new_stack, CLONE_VM) will copy the address space, negating one of the main advantages of a vfork style approach. We may need some other specialized system call that runs an executable in a new address space on a new thread, inheriting all the parts of the execution context.

Owner
Spencer Baugh
Spencer Baugh
Async-first dependency injection library based on python type hints

Dependency Depression Async-first dependency injection library based on python type hints Quickstart First let's create a class we would be injecting:

Doctor 8 Oct 10, 2022
Model synchronization from dbt to Metabase.

dbt-metabase Model synchronization from dbt to Metabase. If dbt is your source of truth for database schemas and you use Metabase as your analytics to

Mike Gouline 270 Jan 08, 2023
Find all social media accounts with a username!

Aliens_eye FIND ALL SOCIAL MEDIA ACCOUNTS WITH A USERNAME! OSINT To install: Open terminal and type: git clone https://github.com/BLINKING-IDIOT/Alien

Aaron Thomas 84 Dec 28, 2022
Demo scripts for the Kubernetes Security Webinar

Kubernetes Security Webinar [in Russian] YouTube video (October 13, 2021) Authors: Artem Yushkovsky (LinkedIn, GitHub) Maxim Mosharov @ Whitespots.io

Slurm 34 Dec 06, 2022
Wordle Solver

Wordle Solver Installation Install the following onto your computer: Python 3.10.x Download Page Run pip install -r requirements.txt Instructions To r

John Bucknam 1 Feb 15, 2022
A domonic-like wrapper around selectolax

A domonic-like wrapper around selectolax

byteface 3 Jun 23, 2022
Flames Calculater App used to calculate flames status between two names created using python's Flask web framework.

Flames Finder Web App Flames Calculater App used to calculate flames status between two names created using python's Flask web framework. First, App g

Siva Prakash 4 Jan 02, 2022
Add your recently blog and douban states in your GitHub Profile

Add your recently blog and douban states in your GitHub Profile

Bingjie Yan 4 Dec 12, 2022
An audnexus client, providing rich author and audiobook data to Plex via it's legacy plugin agent system.

Audnexus.bundle An audnex.us client, providing rich author and audiobook data to Plex via it's legacy plugin agent system. 📝 Table of Contents About

David Dembeck 248 Jan 02, 2023
Your Google Recon is Now Automated

GRecon : GRecon (Greei-Conn) is a simple python tool that automates the process of Google Based Recon AKA Google Dorking The current Version 1.0 Run 7

adnane-tebbaa 189 Dec 21, 2022
A Bot Which Can generate Random Account Based On Your Hits.

AccountGenBot This Bot Can Generate Account With Hits You Save (Randomly) Keyfeatures Join To Use Support Limit Account Generation Using Sql Customiza

DevsExpo 30 Oct 21, 2022
Машинное обучение на ФКН ВШЭ

Курс "Машинное обучение" на ФКН ВШЭ Конспекты лекций, материалы семинаров и домашние задания (теоретические, практические, соревнования) по курсу "Маш

Evgeny Sokolov 2.2k Jan 04, 2023
A Snakemake workflow for standardised sc/snRNAseq analysis

single_snake_sequencing - sc/snRNAseq Snakemake Workflow A Snakemake workflow for standardised sc/snRNAseq analysis. Every single cell analysis is sli

IMS Bio2Core Facility 1 Nov 02, 2021
PyMedPhys is an open-source Medical Physics python library

PyMedPhys is an open-source Medical Physics python library built by an open community that values and prioritises code sharing, review, improvement, and learning from each other. I

PyMedPhys 238 Dec 27, 2022
Find Transposon Element insertions using long reads (nanopore), by alignment directly. (minimap2)

find_te_ins find_te_ins is designed to find Transposon Element (TE) insertions using long reads (nanopore), by alignment directly. (minimap2) Install

Ming Wang 1 Feb 09, 2022
A Red Team tool for exfiltrating sensitive data from Jira tickets.

Jir-thief This Module will connect to Jira's API using an access token, export to a word .doc, and download the Jira issues that the target has access

Antonio Piazza 82 Dec 12, 2022
The repository for my video "Playing MINECRAFT with a WEBCAM"

This is the official repo for my video "Playing MINECRAFT with a WEBCAM" on YouTube Original video can be found here: https://youtu.be/701TPxL0Skg Red

Rishabh 27 Jun 07, 2022
Fuzz introspector for python

Fuzz introspector High-level goals: Show fuzzing-relevant data about each function in a given project Show reachability of fuzzer(s) Integrate seamles

14 Mar 25, 2022
Svg-turtle - Use the Python turtle to write SVG files

SaVaGe Turtle Use the Python turtle to write SVG files If you're using the Pytho

Don Kirkby 7 Dec 21, 2022
It is a Blender Tool which can convert the Object Data Attributes in face corner to the UVs or Vertex Color.

Blender_ObjectDataAttributesConvertTool It is a Blender Tool which can convert the Object Data Attributes in face corner to the UVs or Vertex Color. D

Takeshi Chō 2 Jan 08, 2022