Skip to content

std.os.linux: Implement clone3 #22616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions lib/std/os/linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,80 @@ pub fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:
return syscall3(.execve, @intFromPtr(path), @intFromPtr(argv), @intFromPtr(envp));
}

pub const clone_args = extern struct {
/// Flag bit mask
flags: packed struct(u64) {
__reserverd0: u8 = 0,
VM: bool = false,
FS: bool = false,
FILES: bool = false,
SIGHAND: bool = false,
PIDFD: bool = false,
PTRACE: bool = false,
VFORK: bool = false,
PARENT: bool = false,
THREAD: bool = false,
NEWNS: bool = false,
SYSVSEM: bool = false,
SETTLS: bool = false,
PARENT_SETTID: bool = false,
CHILD_CLEARTID: bool = false,
DETACHED: bool = false,
UNTRACED: bool = false,
CHILD_SETTID: bool = false,
NEWCGROUP: bool = false,
NEWUTS: bool = false,
NEWIPC: bool = false,
NEWUSER: bool = false,
NEWPID: bool = false,
NEWNET: bool = false,
IO: bool = false,
CLEAR_SIGHAND: bool = false,
INTO_CGROUP: bool = false,
__reseved1: u30 = 0,
} = .{},

/// Where to store PID file descriptor
/// (int *)
pidfd: u64 = 0,

/// Where to store child TID in child's memory
/// (pid_t *)
child_tid: u64 = 0,

/// Where to store child TID in parent's memory
/// (pid_t *)
parent_tid: u64 = 0,

/// Signal to deliver to parent on child termination
exit_signal: u64 = SIG.CHLD,

/// Pointer to lowest byte of stack
stack: u64 = 0,

/// Size of stack
stack_size: u64 = 0,

/// Location of new TLS
tls: u64 = 0,

/// Pointer to a pid_t array
/// (since linux 5.5)
set_tid: u64 = 0,

/// Number of elements in set_tid
/// (since linux 5.5)
set_tid_size: u64 = 0,

/// File descriptor for target cgroup of child
/// (since linux 5.7)
cgroup: u64 = 0,
};

pub fn clone3(cl_args: clone_args) usize {
return syscall2(.clone3, @intFromPtr(&cl_args), @sizeOf(@TypeOf(cl_args)));
}

pub fn fork() usize {
if (comptime native_arch.isSPARC()) {
return syscall_fork();
Expand Down
29 changes: 29 additions & 0 deletions lib/std/posix.zig
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub const IOV_MAX = system.IOV_MAX;
pub const IPPROTO = system.IPPROTO;
pub const KERN = system.KERN;
pub const Kevent = system.Kevent;
pub const clone_args = system.clone_args;
pub const MADV = system.MADV;
pub const MAP = system.MAP;
pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN;
Expand Down Expand Up @@ -4691,6 +4692,34 @@ pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectErro
}
}

pub const Clone3Error = error{
AccessDenied,
SystemResources,
Invalid,
PidAlreadyExists,
OutOfMemory,
OperationNotSupported,
OutOfUserNamespaces,
} || UnexpectedError;

pub fn clone3(cl_args: system.clone_args) Clone3Error!pid_t {
const rc = system.clone3(cl_args);
return switch (errno(rc)) {
.SUCCESS => @intCast(rc),
.ACCES => error.AccessDenied,
.AGAIN => error.SystemResources,
.BUSY => error.Invalid,
.EXIST => error.PidAlreadyExists,
.INVAL => error.Invalid,
.NOMEM => error.OutOfMemory,
.NOSPC => error.SystemResources,
.OPNOTSUPP => error.OperationNotSupported,
.PERM => error.AccessDenied,
.USERS => error.OutOfUserNamespaces,
else => |err| unexpectedErrno(err),
};
}

pub const ForkError = error{SystemResources} || UnexpectedError;

pub fn fork() ForkError!pid_t {
Expand Down
Loading