tiny.sys.process
Defined in tiny.sys.
API (92)
Actions
Public operations.
abortauxiliaryValuebecomeChildSubreaper: Ensures a descendant whose parent died still reports its exit to the supervisor by making the calling process the Linux child subreaper, so descendants orphaned below it reparent to it and stay reapable.buildId: Returns the GNU build-id descriptor of the running executable, or null when its link wrote none.childPeekPolicychildSignalPolicycreateOwnProcessGroupcurrentGroupIdcurrentProcessIdcurrentResourceUsagecurrentThreadIdcurrentUserIddetachPolicyeffectiveGroupIdeffectiveUserIdexecDescriptorexecUnderStack: Caps this process atstack_bytesof stack and then hands it over to the program atpath.executableDirPathAllocexecutablePathAllocexitexitCodeforceKillChildIdforkforkContained: Forks a child that is process id 1 inside a new PID namespace and a new user namespace, preserving the caller's real and effective user and group identity through an identity map, while on the parent side the call yields the child's process id as the host numbers it.handoffReapisolateChildDescriptorskernelReleasekillAndReapparentProcessIdpeekNoHangprocessAliveprocessGroupAliveprocessGroupIdprocessIdentityPolicyrequestTerminationrunsignalChildGroupsignalChildIdspawnspawnCapturedIsolated: Starts one Linux child whose standard output and standard error are pipes the caller reads, with standard input on/dev/null, for a caller that needs to know the child holds none of its descriptors.spawnDetachedsystemControlwaitwaitDirectwaitNoHang
Types and contracts
Public types and contracts.
ArgsAuxiliaryKeyAuxiliaryValueErrorBuildIdErrorCapturedIsolatedOptions: Specifies what to run and in what environment through the inputs for a captured launch: the argument vector and the environment map.ChildChildPeekPolicyChildSignalChildSignalErrorChildSignalPolicyDescriptorIsolationErrorDetachErrorDetachOptionsDetachPolicyEnvironExecDescriptorErrorExecUnderStackErrorExecutablePathAllocErrorForkErrorForkResultGroupIdInitKernelReleaseErrorMinimalInitProcessGroupErrorProcessIdProcessIdentityErrorProcessIdentityPolicyReapHandoffErrorResourceUsageResourceUsageSourceRunErrorRunOptionsRunResultSpawnErrorSpawnOptionsSubreaperErrorSystemControlErrorTerminationThreadIdUserIdWaitDirectErrorWaitErrorWaitNoHangOutcome
Namespaces
Public namespaces.
inspecttracing: A recorder that wants every file a program opens has to stop that program at each syscall, attached from the start as the process that receives its stops, the tracer.
Values and defaults
Public values and defaults.
Source
Source: lib/sys/src/process/control.zig:36
pub const AuxiliaryKey = enum { hardware_capabilities, hardware_capabilities_2,};Source: lib/sys/src/process/control.zig:41
pub const AuxiliaryValueError = error{UnsupportedPlatform};Source: lib/sys/src/process/control.zig:282
pub const BuildIdError = error{ UnsupportedPlatform, ProgramHeaderMissing };Source: lib/sys/src/process/control.zig:91
pub const ChildPeekPolicy = enum { unsupported, linux_waitid, darwin_waitid,};Source: lib/sys/src/process/control.zig:72
pub const ChildSignal = enum { terminate, kill, pause_child, resume_child,};Source: lib/sys/src/process/control.zig:97
pub const ChildSignalError = error{ UnsupportedPlatform, ProcessNotFound, PermissionDenied, InvalidSignal, SignalFailed,};Source: lib/sys/src/process/control.zig:79
pub const ChildSignalPolicy = enum { unsupported, linux_syscall, posix_host,};Source: lib/sys/src/process/control.zig:169
pub const DescriptorIsolationError = error{ UnsupportedPlatform, DescriptorIsolationFailed,};Source: lib/sys/src/process/control.zig:159
pub const DetachOptions = struct { argv: []const []const u8, cwd: Child.Cwd = .inherit, environ_map: ?*const Environ.Map = null,};Source: lib/sys/src/process/control.zig:154
pub const DetachPolicy = enum { unsupported, linux_cloexec_process_group,};Source: lib/sys/src/process/control.zig:131
pub const ExecDescriptorError = error{ UnsupportedPlatform, InvalidDescriptor, AccessDenied, InvalidExecutable, ExecFailed,};Source: lib/sys/src/process/control.zig:138
pub const ExecUnderStackError = error{ UnsupportedPlatform, InvalidLimit, PermissionDenied, PersonaFailed, AccessDenied, InvalidExecutable, ExecFailed,};Source: lib/sys/src/process/control.zig:120
pub const ForkError = error{ UnsupportedPlatform, SystemResources, ForkFailed,};Source: lib/sys/src/process/control.zig:126
pub const ForkResult = union(enum) { child, parent: ProcessId,};Source: lib/sys/src/process/control.zig:49
pub const KernelReleaseError = error{ UnsupportedPlatform, BufferTooSmall };Source: lib/sys/src/process/control.zig:109
pub const ProcessGroupError = error{ UnsupportedPlatform, ProcessNotFound, PermissionDenied,};Source: lib/sys/src/process/control.zig:105
pub const ProcessIdentityError = error{ UnsupportedPlatform,};Source: lib/sys/src/process/control.zig:85
pub const ProcessIdentityPolicy = enum { unsupported, linux_syscall, posix_host,};Source: lib/sys/src/process/control.zig:56
pub const ResourceUsage = struct { source: ?ResourceUsageSource = null, maxrss_kib: ?i64 = null, user_s: ?f64 = null, system_s: ?f64 = null, minor_page_faults: ?u64 = null, major_page_faults: ?u64 = null, voluntary_context_switches: ?u64 = null, involuntary_context_switches: ?u64 = null,};Source: lib/sys/src/process/control.zig:51
pub const ResourceUsageSource = enum { getrusage_self, wait4_rusage,};Source: lib/sys/src/process/control.zig:115
pub const SubreaperError = error{ UnsupportedPlatform, SubreaperFailed,};Source: lib/sys/src/process/control.zig:42
pub const SystemControlError = error{ UnsupportedPlatform, NotFound, PermissionDenied, BufferTooSmall, QueryFailed,};Source: lib/sys/src/process/control.zig:148
pub const WaitDirectError = error{ UnsupportedPlatform, ChildAlreadyReaped, ChildWaitFailed,};Source: lib/sys/src/process/control.zig:67
pub const WaitNoHangOutcome = struct { term: Termination, usage: ResourceUsage,};Source: lib/sys/src/process/isolated.zig:13
/// Specifies what to run and in what environment through the inputs for a/// captured launch: the argument vector and the environment map.pub const CapturedOptions = struct { argv: []const []const u8, environment: *const std.process.Environ.Map,};Source: lib/sys/src/process/control.zig:165
pub const DetachError = SpawnError || error{ UnsupportedPlatform, DescriptorIsolationFailed,};Source: lib/sys/src/process/control.zig:173
pub const ReapHandoffError = sys.thread.SpawnError || error{ MissingChildId,};Source: lib/sys/src/process/control.zig:752
pub fn abort() noreturn { std.process.abort();}Source: lib/sys/src/process/control.zig:255
pub fn auxiliaryValue(key: AuxiliaryKey) AuxiliaryValueError!usize { if (comptime native_os != .linux) return error.UnsupportedPlatform; return linux.getauxval(switch (key) { .hardware_capabilities => std.elf.AT_HWCAP, .hardware_capabilities_2 => std.elf.AT_HWCAP2, });}Source: lib/sys/src/process/control.zig:520
/// Ensures a descendant whose parent died still reports its exit to the/// supervisor by making the calling process the Linux child subreaper, so/// descendants orphaned below it reparent to it and stay reapable. Other/// targets refuse with `UnsupportedPlatform`.pub fn becomeChildSubreaper() SubreaperError!void { if (comptime native_os != .linux) return error.UnsupportedPlatform; return switch (linux.errno(linux.prctl( @backingInt(linux.PR.SET_CHILD_SUBREAPER), 1, 0, 0, 0, ))) { .SUCCESS => {}, else => error.SubreaperFailed, };}Source: lib/sys/src/process/control.zig:266
/// Returns the GNU build-id descriptor of the running executable, or null when its link wrote/// none. The kernel passes the program headers in auxv, so no file is read and no syscall runs./// The slice borrows the mapped image for the life of the process.pub fn buildId() BuildIdError!?[]const u8 { if (comptime native_os != .linux) return error.UnsupportedPlatform; const headers = posix.getSelfPhdrs(); const bias = for (headers) |header| { if (header.type == .PHDR) break @intFromPtr(headers.ptr) -% header.vaddr; } else return error.ProgramHeaderMissing; for (headers) |header| { if (header.type != .NOTE) continue; const start: [*]const u8 = @ptrFromInt(bias +% header.vaddr); const alignment: usize = if (header.@"align" == 8) 8 else 4; const segment = start[0..header.filesz]; if (noteDescriptor(segment, alignment, std.elf.NT_GNU_BUILD_ID)) |id| return id; } return null;}Source: lib/sys/src/process/control.zig:689
pub fn childPeekPolicy() ChildPeekPolicy { return switch (native_os) { .linux => .linux_waitid, .macos => .darwin_waitid, else => .unsupported, };}Source: lib/sys/src/process/control.zig:765
pub fn childSignalPolicy() ChildSignalPolicy { return switch (native_os) { .windows, .wasi => .unsupported, .linux => .linux_syscall, else => .posix_host, };}Source: lib/sys/src/process/control.zig:502
pub fn createOwnProcessGroup() ProcessGroupError!void { const outcome = if (comptime native_os == .linux) linux.errno(linux.setpgid(0, 0)) else if (comptime native_os == .macos) std.c.errno(std.c.setpgid(0, 0)) else return error.UnsupportedPlatform; return switch (outcome) { .SUCCESS => {}, .ACCES, .PERM => error.PermissionDenied, else => error.UnsupportedPlatform, };}Source: lib/sys/src/process/control.zig:828
pub fn currentGroupId() ProcessIdentityError!GroupId { return switch (comptime processIdentityPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall => linux.getgid(), .posix_host => currentGroupIdPosix(), };}Source: lib/sys/src/process/control.zig:796
pub fn currentProcessId() ProcessIdentityError!ProcessId { return switch (comptime processIdentityPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall => linux.getpid(), .posix_host => currentProcessIdPosix(), };}Source: lib/sys/src/process/control.zig:619
pub fn currentResourceUsage() ResourceUsage { if (comptime native_os == .windows or native_os == .wasi or native_os == .freestanding) { return .{}; } return resourceUsage( .getrusage_self, posix.getrusage(posix.rusage.SELF), );}Source: lib/sys/src/process/control.zig:812
pub fn currentThreadId() ProcessIdentityError!ThreadId { return switch (comptime processIdentityPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall => linux.gettid(), .posix_host => currentThreadIdPosix(), };}Source: lib/sys/src/process/control.zig:820
pub fn currentUserId() ProcessIdentityError!UserId { return switch (comptime processIdentityPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall => linux.getuid(), .posix_host => currentUserIdPosix(), };}Source: lib/sys/src/process/control.zig:340
pub fn detachPolicy() DetachPolicy { return switch (comptime native_os) { .linux => .linux_cloexec_process_group, else => .unsupported, };}Source: lib/sys/src/process/control.zig:844
pub fn effectiveGroupId() ProcessIdentityError!GroupId { return switch (comptime processIdentityPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall => linux.getegid(), .posix_host => effectiveGroupIdPosix(), };}Source: lib/sys/src/process/control.zig:836
pub fn effectiveUserId() ProcessIdentityError!UserId { return switch (comptime processIdentityPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall => linux.geteuid(), .posix_host => effectiveUserIdPosix(), };}Source: lib/sys/src/process/control.zig:191
pub fn execDescriptor( descriptor: posix.fd_t, argv: [*:null]const ?[*:0]const u8, environment: [*:null]const ?[*:0]const u8,) ExecDescriptorError!void { if (comptime native_os != .linux) return error.UnsupportedPlatform; const result = linux.execveat( descriptor, "", argv, environment, .{ .SYMLINK_NOFOLLOW = true, .EMPTY_PATH = true }, ); return switch (linux.errno(result)) { .BADF => error.InvalidDescriptor, .ACCES => error.AccessDenied, .NOEXEC => error.InvalidExecutable, else => error.ExecFailed, };}Source: lib/sys/src/process/control.zig:229
/// Caps this process at `stack_bytes` of stack and then hands it over to the/// program at `path`. The initial stack lands at the address the kernel picks/// when no randomization applies, so a harness that has to show a program stays/// inside a stack budget gets the same answer on every run. Linux otherwise/// shifts the initial stack pointer down by a random amount of up to eight/// kilobytes before the program executes an instruction, in `arch_align_stack`,/// which leaves a program at a fixed limit surviving one run and overflowing/// the next. The order runs persona, then the soft and hard limit in one call,/// and then the exec. A return means the exec failed, and both settings remain/// in force on the calling process, so a caller with work left to do makes this/// call inside a forked child. A zero limit fails with `InvalidLimit`, and a/// host other than Linux with `UnsupportedPlatform`.pub fn execUnderStack( path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, environment: [*:null]const ?[*:0]const u8, stack_bytes: u64,) ExecUnderStackError!void { if (comptime native_os != .linux) return error.UnsupportedPlatform; if (stack_bytes == 0) return error.InvalidLimit; if (linux.errno(linux.syscall1(.personality, persona_no_randomize)) != .SUCCESS) { return error.PersonaFailed; } const limit = linux.rlimit{ .cur = stack_bytes, .max = stack_bytes }; switch (linux.errno(linux.setrlimit(.STACK, &limit))) { .SUCCESS => {}, .INVAL => return error.InvalidLimit, .PERM => return error.PermissionDenied, else => return error.InvalidLimit, } const result = linux.execve(path, argv, environment); return switch (linux.errno(result)) { .ACCES => error.AccessDenied, .NOEXEC => error.InvalidExecutable, else => error.ExecFailed, };}Source: lib/sys/src/process/control.zig:740
pub fn executableDirPathAlloc(allocator: std.mem.Allocator) ExecutablePathAllocError![]u8 { return std.process.executableDirPathAlloc(std.Options.debug_io, allocator);}Source: lib/sys/src/process/control.zig:744
pub fn executablePathAlloc(allocator: std.mem.Allocator) ExecutablePathAllocError![:0]u8 { return std.process.executablePathAlloc(std.Options.debug_io, allocator);}Source: lib/sys/src/process/control.zig:748
pub fn exit(code: u8) noreturn { std.process.exit(code);}Source: lib/sys/src/process/control.zig:756
pub fn exitCode(term: Termination) i64 { return switch (term) { .exited => |code| @intCast(code), .signal => |sig| -@as(i64, @intCast(@backingInt(sig))), .stopped => |sig| -@as(i64, @intCast(@backingInt(sig))), .unknown => -1, };}Source: lib/sys/src/process/control.zig:862
pub fn forceKillChildId(child_id: Child.Id) void { if (builtin.os.tag == .windows or builtin.os.tag == .wasi) return; signalChildId(child_id, .kill) catch {};}Source: lib/sys/src/process/control.zig:181
pub fn fork() ForkError!ForkResult { if (comptime native_os != .linux) return error.UnsupportedPlatform; const result = linux.fork(); return switch (linux.errno(result)) { .SUCCESS => if (result == 0) .child else .{ .parent = @intCast(result) }, .AGAIN, .NOMEM => error.SystemResources, else => error.ForkFailed, };}Source: lib/sys/src/process/control.zig:362
pub fn handoffReap( child: *Child,) ReapHandoffError!void { const child_id = child.id orelse return error.MissingChildId; const reaper = try sys.thread.spawn( reapChildId, .{child_id}, ); child.id = null; reaper.detach();}Source: lib/sys/src/process/control.zig:398
pub fn isolateChildDescriptors() DescriptorIsolationError!void { return switch (comptime native_os) { .linux => isolateChildDescriptorsLinux(), .macos => isolateChildDescriptorsDarwin(), else => error.UnsupportedPlatform, };}Source: lib/sys/src/process/control.zig:329
pub fn kernelRelease(storage: []u8) KernelReleaseError![]const u8 { if (comptime native_os == .windows or native_os == .wasi or native_os == .freestanding) { return error.UnsupportedPlatform; } const identity = posix.uname(); const release = std.mem.sliceTo(&identity.release, 0); if (release.len > storage.len) return error.BufferTooSmall; @memcpy(storage[0..release.len], release); return storage[0..release.len];}Source: lib/sys/src/process/control.zig:867
pub fn killAndReap(child: *Child, io: anytype) void { if (child.id != null) child.kill(io);}Source: lib/sys/src/process/control.zig:804
pub fn parentProcessId() ProcessIdentityError!ProcessId { return switch (comptime processIdentityPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall => linux.getppid(), .posix_host => parentProcessIdPosix(), };}Source: lib/sys/src/process/control.zig:651
pub fn peekNoHang(child_id: Child.Id) !?Termination { return switch (comptime childPeekPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_waitid => peekLinux(child_id), .darwin_waitid => peekDarwin(child_id), };}Source: lib/sys/src/process/control.zig:494
pub fn processAlive(process_id: ProcessId) ProcessGroupError!bool { _ = processGroupId(process_id) catch |err| switch (err) { error.ProcessNotFound => return false, else => return err, }; return true;}Source: lib/sys/src/process/control.zig:534
pub fn processGroupAlive(group_id: ProcessId) ProcessGroupError!bool { if (group_id <= 1) return error.ProcessNotFound; return switch (comptime processIdentityPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall => switch (linux.errno(linux.kill( -group_id, @fromBackingInt(@intCast(0)), ))) { .SUCCESS => true, .SRCH => false, .PERM => true, else => error.UnsupportedPlatform, }, .posix_host => switch (posix.errno(system.kill( -group_id, @as(system.SIG, @fromBackingInt(@intCast(0))), ))) { .SUCCESS, .PERM => true, .SRCH => false, else => error.UnsupportedPlatform, }, };}Source: lib/sys/src/process/control.zig:485
pub fn processGroupId(process_id: ProcessId) ProcessGroupError!ProcessId { if (process_id <= 0) return error.ProcessNotFound; return switch (comptime processIdentityPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall => processGroupIdInspected(process_id), .posix_host => processGroupIdPosix(process_id), };}Source: lib/sys/src/process/control.zig:773
pub fn processIdentityPolicy() ProcessIdentityPolicy { return switch (native_os) { .windows, .wasi, .freestanding => .unsupported, .linux => .linux_syscall, else => .posix_host, };}Source: lib/sys/src/process/control.zig:852
pub fn requestTermination(child: *Child, io: anytype) void { if (native_os == .windows or native_os == .wasi) { killAndReap(child, io); return; } const child_id = child.id orelse return; signalChildId(child_id, .terminate) catch {};}Source: lib/sys/src/process/control.zig:14
pub const required_capabilities = sys.capabilities.host( &.{ .process, .environment, .threads },);Source: lib/sys/src/process/control.zig:736
pub fn run(allocator: std.mem.Allocator, io: anytype, options: RunOptions) RunError!RunResult { return std.process.run(allocator, io, options);}Source: lib/sys/src/process/control.zig:789
pub fn signalChildGroup(child_id: Child.Id, signal: ChildSignal) ChildSignalError!void { return switch (comptime childSignalPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall, .posix_host => signalChildId(-child_id, signal), };}Source: lib/sys/src/process/control.zig:781
pub fn signalChildId(child_id: Child.Id, signal: ChildSignal) ChildSignalError!void { return switch (comptime childSignalPolicy()) { .unsupported => error.UnsupportedPlatform, .linux_syscall => signalChildIdLinux(child_id, signal), .posix_host => signalChildIdPosix(child_id, signal), };}Source: lib/sys/src/process/control.zig:177
pub fn spawn(io: anytype, options: SpawnOptions) SpawnError!Child { return std.process.spawn(io, options);}Source: lib/sys/src/process/control.zig:347
pub fn spawnDetached(io: anytype, options: DetachOptions) DetachError!Child { if (comptime detachPolicy() == .unsupported) return error.UnsupportedPlatform; std.debug.assert(options.argv.len != 0); try isolateChildDescriptors(); return try spawn(io, .{ .argv = options.argv, .cwd = options.cwd, .environ_map = options.environ_map, .stdin = .ignore, .stdout = .ignore, .stderr = .ignore, .pgid = 0, });}Source: lib/sys/src/process/control.zig:312
pub fn systemControl( comptime name: [:0]const u8, output: anytype,) SystemControlError!usize { if (comptime !is_darwin) return error.UnsupportedPlatform; const pointer = @typeInfo(@TypeOf(output)).pointer; var byte_len: usize = @sizeOf(pointer.child); const rc = system.sysctlbyname(name, output, &byte_len, null, 0); return switch (posix.errno(rc)) { .SUCCESS => byte_len, .NOENT => error.NotFound, .ACCES, .PERM => error.PermissionDenied, .NOMEM => error.BufferTooSmall, else => error.QueryFailed, };}Source: lib/sys/src/process/control.zig:580
pub fn wait(child: *Child, io: anytype) WaitError!Termination { return child.wait(io);}Source: lib/sys/src/process/control.zig:584
pub fn waitDirect(child_id: ProcessId) WaitDirectError!Termination { if (comptime native_os == .windows or native_os == .wasi or native_os == .freestanding) { return error.UnsupportedPlatform; } var status: i32 = undefined; var child_usage: posix.rusage = undefined; while (true) { const result = system.wait4(child_id, &status, 0, &child_usage); switch (posix.errno(result)) { .SUCCESS => return statusToTerm(@bitCast(status)), .INTR => continue, .CHILD => return error.ChildAlreadyReaped, else => return error.ChildWaitFailed, } }}Source: lib/sys/src/process/control.zig:604
pub fn waitNoHang(child_id: Child.Id) !?WaitNoHangOutcome { if (comptime native_os == .windows or native_os == .wasi) return error.UnsupportedPlatform; var status: i32 = undefined; var child_usage: posix.rusage = undefined; const rc = system.wait4(child_id, &status, posix.W.NOHANG, &child_usage); return switch (posix.errno(rc)) { .SUCCESS => if (rc == 0) null else .{ .term = statusToTerm(@bitCast(status)), .usage = resourceUsage(.wait4_rusage, child_usage), }, .INTR => null, else => |err| return posix.unexpectedErrno(err), };}Source: lib/sys/src/process/isolated.zig:36
/// Starts one Linux child whose standard output and standard error are pipes/// the caller reads, with standard input on `/dev/null`, for a caller that/// needs to know the child holds none of its descriptors.////// Before it execs, the child arms the parent-death signal to `SIGKILL` and/// starts its own process group. One `close_range` call in the child closes any/// open descriptor above standard error, so that every inherited non-standard/// descriptor is closed before the program runs, while the pre-exec launcher/// keeps one private close-on-exec status descriptor at descriptor 3, whose/// end-of-file after a successful exec tells the parent the launch reached the/// program. Where a command name has no slash, the launcher finds it by/// searching a fixed `PATH` list compiled into the launcher, which the/// environment map does not change.////// A launch that fails anywhere before the program starts is killed and reaped,/// and reports `DescriptorIsolationFailed`, while an empty argument vector/// returns `EmptyArgv` and a host other than Linux returns/// `UnsupportedPlatform`.pub fn spawnCaptured( allocator: Allocator, options: CapturedOptions,) !std.process.Child { if (comptime native_os != .linux) return error.UnsupportedPlatform; if (options.argv.len == 0) return error.EmptyArgv; var arena_state = std.heap.ArenaAllocator.init(allocator); defer arena_state.deinit(); const arena = arena_state.allocator(); const argv = try prepareArgv(arena, options.argv); const environment = try options.environment.createPosixBlock(arena, .{ .zig_progress_fd = -1, }); var executable_storage: [std.posix.PATH_MAX]u8 = undefined; const executable = try executablePath( argv[0].?, options.argv[0], &executable_storage, ); var descriptors = try Descriptors.init(); defer descriptors.deinit(); const parent_id = linux.getpid(); const fork_result = linux.fork(); switch (linux.errno(fork_result)) { .SUCCESS => {}, .AGAIN, .NOMEM => return error.SystemResources, else => return error.DescriptorIsolationFailed, } if (fork_result == 0) { launchChild( parent_id, descriptors, executable, argv, environment, ); } const child_id: linux.pid_t = @intCast(fork_result); descriptors.closeSources(); if (!launchSucceeded(descriptors.status_read)) { terminateAndReap(child_id); return error.DescriptorIsolationFailed; } descriptors.closeStatus(); const stdout_descriptor = descriptors.takeStdout(); const stderr_descriptor = descriptors.takeStderr(); return .{ .id = child_id, .thread_handle = {}, .stdin = null, .stdout = .{ .handle = stdout_descriptor, .flags = .{ .nonblocking = false }, }, .stderr = .{ .handle = stderr_descriptor, .flags = .{ .nonblocking = false }, }, .request_resource_usage_statistics = false, };}Source: lib/sys/src/process/namespace.zig:31
/// Forks a child that is process id 1 inside a new PID namespace and a new user/// namespace, preserving the caller's real and effective user and group/// identity through an identity map, while on the parent side the call yields/// the child's process id as the host numbers it. Killing or exiting that child/// kills the namespace's descendants, including processes that create new/// sessions. The child arms the parent-death signal, which delivers `SIGKILL`/// to a child when its parent exits, and no-new-privileges, which stops a later/// exec from gaining privileges, such as through a setuid binary, while the/// parent waits for both over a socket pair before the call returns. The child/// keeps every mount the caller had, procfs among them, so a numeric path under/// `/proc` read inside the child resolves against the caller's process/// numbering, and only a program whose behavior under that mismatch is known/// belongs beneath this call. The child carries the same restriction any forked/// child carries: it reaches an exec or an exit while touching none of the/// runtime locks it inherited. A caller whose real and effective identity/// differ fails with `NamespaceIdentityUnavailable`, and a host outside Linux/// on x86-64 and aarch64 fails with `UnsupportedPlatform`.pub fn forkContained() !process.ForkResult { if (comptime builtin.os.tag != .linux) return error.UnsupportedPlatform; if (comptime builtin.cpu.arch != .x86_64 and builtin.cpu.arch != .aarch64) { return error.UnsupportedPlatform; } const uid = linux.getuid(); const gid = linux.getgid(); if (uid != linux.geteuid() or gid != linux.getegid()) { return error.NamespaceIdentityUnavailable; } var channel: [2]sys.fd.Descriptor = undefined; const channel_result = linux.socketpair( linux.AF.UNIX, linux.SOCK.SEQPACKET | linux.SOCK.CLOEXEC, 0, &channel, ); if (linux.errno(channel_result) != .SUCCESS) { return error.NamespaceChannelFailed; } defer closeDescriptor(&channel[0]); defer closeDescriptor(&channel[1]); const flags = linux.CLONE.NEWUSER | linux.CLONE.NEWPID | @backingInt(linux.SIG.CHLD); const result = linux.clone2(flags, 0); switch (linux.errno(result)) { .SUCCESS => {}, .PERM, .ACCES => return error.NamespacePermissionDenied, .AGAIN, .NOMEM, .NOSPC => return error.SystemResources, else => return error.NamespaceCreationFailed, } if (result == 0) { closeDescriptor(&channel[0]); childReady(channel[1]) catch process.exit(127); std.debug.assert(linux.getpid() == 1); std.debug.assert(linux.getuid() == uid); std.debug.assert(linux.getgid() == gid); return .child; } closeDescriptor(&channel[1]); const child: process.ProcessId = @intCast(result); std.debug.assert(child > 1); errdefer { process.forceKillChildId(child); _ = process.waitDirect(child) catch {}; } try receiveReady(channel[0]); try mapIdentity(child, "uid_map", uid); try writeControl(child, "setgroups", "deny"); try mapIdentity(child, "gid_map", gid); try sendReady(channel[0]); return .{ .parent = child };}Source: lib/sys/src/process/control.zig:21
pub const Args = std.process.Args;Source: lib/sys/src/process/control.zig:18
pub const Child = std.process.Child;Source: lib/sys/src/process/control.zig:22
pub const Environ = std.process.Environ;Source: lib/sys/src/process/control.zig:30
pub const ExecutablePathAllocError = std.process.ExecutablePathAllocError;Source: lib/sys/src/process/control.zig:34
pub const GroupId = linux.gid_t;Source: lib/sys/src/process/control.zig:19
pub const Init = std.process.Init;Source: lib/sys/src/process/control.zig:20
pub const MinimalInit = std.process.Init.Minimal;Source: lib/sys/src/process/control.zig:31
pub const ProcessId = linux.pid_t;Source: lib/sys/src/process/control.zig:29
pub const RunError = std.process.RunError;Source: lib/sys/src/process/control.zig:27
pub const RunOptions = std.process.RunOptions;Source: lib/sys/src/process/control.zig:28
pub const RunResult = std.process.RunResult;Source: lib/sys/src/process/control.zig:24
pub const SpawnError = std.process.SpawnError;Source: lib/sys/src/process/control.zig:23
pub const SpawnOptions = std.process.SpawnOptions;Source: lib/sys/src/process/control.zig:25
pub const Termination = Child.Term;Source: lib/sys/src/process/control.zig:32
pub const ThreadId = linux.pid_t;Source: lib/sys/src/process/control.zig:33
pub const UserId = linux.uid_t;Source: lib/sys/src/process/control.zig:26
pub const WaitError = Child.WaitError;Source: lib/sys/src/process/root.zig
const control = @import("control.zig");const namespace = @import("namespace.zig");const isolated = @import("isolated.zig");pub const inspect = @import("inspect/root.zig");pub const required_capabilities = control.required_capabilities;pub const Child = control.Child;pub const Init = control.Init;pub const MinimalInit = control.MinimalInit;pub const Args = control.Args;pub const Environ = control.Environ;pub const SpawnOptions = control.SpawnOptions;pub const SpawnError = control.SpawnError;pub const Termination = control.Termination;pub const WaitError = control.WaitError;pub const RunOptions = control.RunOptions;pub const RunResult = control.RunResult;pub const RunError = control.RunError;pub const ExecutablePathAllocError = control.ExecutablePathAllocError;pub const ProcessId = control.ProcessId;pub const ThreadId = control.ThreadId;pub const UserId = control.UserId;pub const GroupId = control.GroupId;pub const AuxiliaryKey = control.AuxiliaryKey;pub const BuildIdError = control.BuildIdError;pub const AuxiliaryValueError = control.AuxiliaryValueError;pub const SystemControlError = control.SystemControlError;pub const KernelReleaseError = control.KernelReleaseError;pub const ResourceUsageSource = control.ResourceUsageSource;pub const ResourceUsage = control.ResourceUsage;pub const WaitNoHangOutcome = control.WaitNoHangOutcome;pub const ChildSignal = control.ChildSignal;pub const ChildSignalPolicy = control.ChildSignalPolicy;pub const ProcessIdentityPolicy = control.ProcessIdentityPolicy;pub const ChildPeekPolicy = control.ChildPeekPolicy;pub const ChildSignalError = control.ChildSignalError;pub const ProcessIdentityError = control.ProcessIdentityError;pub const ProcessGroupError = control.ProcessGroupError;pub const SubreaperError = control.SubreaperError;pub const ForkError = control.ForkError;pub const ForkResult = control.ForkResult;pub const ExecDescriptorError = control.ExecDescriptorError;pub const ExecUnderStackError = control.ExecUnderStackError;pub const WaitDirectError = control.WaitDirectError;pub const DetachPolicy = control.DetachPolicy;pub const DetachOptions = control.DetachOptions;pub const DetachError = control.DetachError;pub const DescriptorIsolationError = control.DescriptorIsolationError;pub const ReapHandoffError = control.ReapHandoffError;pub const CapturedIsolatedOptions = isolated.CapturedOptions;pub const spawn = control.spawn;pub const fork = control.fork;pub const forkContained = namespace.forkContained;pub const execDescriptor = control.execDescriptor;pub const execUnderStack = control.execUnderStack;pub const spawnCapturedIsolated = isolated.spawnCaptured;pub const auxiliaryValue = control.auxiliaryValue;pub const buildId = control.buildId;pub const systemControl = control.systemControl;pub const kernelRelease = control.kernelRelease;pub const detachPolicy = control.detachPolicy;pub const spawnDetached = control.spawnDetached;pub const handoffReap = control.handoffReap;pub const isolateChildDescriptors = control.isolateChildDescriptors;pub const processGroupId = control.processGroupId;pub const processAlive = control.processAlive;pub const createOwnProcessGroup = control.createOwnProcessGroup;pub const becomeChildSubreaper = control.becomeChildSubreaper;pub const processGroupAlive = control.processGroupAlive;pub const wait = control.wait;pub const waitDirect = control.waitDirect;pub const waitNoHang = control.waitNoHang;pub const currentResourceUsage = control.currentResourceUsage;pub const peekNoHang = control.peekNoHang;pub const childPeekPolicy = control.childPeekPolicy;pub const run = control.run;pub const executableDirPathAlloc = control.executableDirPathAlloc;pub const executablePathAlloc = control.executablePathAlloc;pub const exit = control.exit;pub const abort = control.abort;pub const exitCode = control.exitCode;pub const childSignalPolicy = control.childSignalPolicy;pub const processIdentityPolicy = control.processIdentityPolicy;pub const signalChildId = control.signalChildId;pub const signalChildGroup = control.signalChildGroup;pub const currentProcessId = control.currentProcessId;pub const parentProcessId = control.parentProcessId;pub const currentThreadId = control.currentThreadId;pub const currentUserId = control.currentUserId;pub const currentGroupId = control.currentGroupId;pub const effectiveUserId = control.effectiveUserId;pub const effectiveGroupId = control.effectiveGroupId;pub const requestTermination = control.requestTermination;pub const forceKillChildId = control.forceKillChildId;pub const killAndReap = control.killAndReap;pub const tracing = @import("tracing/root.zig");Source: lib/sys/src/root.zig:43
pub const process = @import("process/root.zig");Complete caller list for process.processIdentityPolicy
12 direct callers.
tiny.sys.process.currentGroupId[function] atlib/sys/src/process/control.zig:828tiny.sys.process.currentProcessId[function] atlib/sys/src/process/control.zig:796tiny.sys.process.currentThreadId[function] atlib/sys/src/process/control.zig:812tiny.sys.process.currentUserId[function] atlib/sys/src/process/control.zig:820tiny.sys.process.effectiveGroupId[function] atlib/sys/src/process/control.zig:844tiny.sys.process.effectiveUserId[function] atlib/sys/src/process/control.zig:836tiny.sys.process.parentProcessId[function] atlib/sys/src/process/control.zig:804tiny.sys.process.processGroupAlive[function] atlib/sys/src/process/control.zig:534tiny.sys.process.processGroupId[function] atlib/sys/src/process/control.zig:485lib.sys.src.process.control.test_process_group_lookup_rejects_absent_and_invalid_identities[function] — test source atlib/sys/src/process/control.zig:1312in nearest public ownerlib.sys.src.process.controllib.sys.src.process.control.test_process_identity_policy_is_explicit[function] — test source atlib/sys/src/process/control.zig:1143in nearest public ownerlib.sys.src.process.controllib.sys.src.process.control.test_process_identity_values_are_queryable[function] — test source atlib/sys/src/process/control.zig:1161in nearest public ownerlib.sys.src.process.control
Complete call list for process.spawnCapturedIsolated
12 direct calls.
lib.sys.src.linux.errno[function] — private source atlib/sys/src/linux.zig:17in nearest public ownerlib.sys.src.linuxlib.sys.src.process.isolated.Descriptors.closeSources[method] — private source atlib/sys/src/process/isolated.zig:178in nearest public ownerlib.sys.src.process.isolatedlib.sys.src.process.isolated.Descriptors.closeStatus[method] — private source atlib/sys/src/process/isolated.zig:185in nearest public ownerlib.sys.src.process.isolatedlib.sys.src.process.isolated.Descriptors.deinit[method] — private source atlib/sys/src/process/isolated.zig:201in nearest public ownerlib.sys.src.process.isolatedlib.sys.src.process.isolated.Descriptors.init[function] — private source atlib/sys/src/process/isolated.zig:162in nearest public ownerlib.sys.src.process.isolatedlib.sys.src.process.isolated.Descriptors.takeStderr[method] — private source atlib/sys/src/process/isolated.zig:195in nearest public ownerlib.sys.src.process.isolatedlib.sys.src.process.isolated.Descriptors.takeStdout[method] — private source atlib/sys/src/process/isolated.zig:189in nearest public ownerlib.sys.src.process.isolatedlib.sys.src.process.isolated.executablePath[function] — private source atlib/sys/src/process/isolated.zig:121in nearest public ownerlib.sys.src.process.isolatedlib.sys.src.process.isolated.launchChild[function] — private source atlib/sys/src/process/isolated.zig:270in nearest public ownerlib.sys.src.process.isolatedlib.sys.src.process.isolated.launchSucceeded[function] — private source atlib/sys/src/process/isolated.zig:349in nearest public ownerlib.sys.src.process.isolatedlib.sys.src.process.isolated.prepareArgv[function] — private source atlib/sys/src/process/isolated.zig:103in nearest public ownerlib.sys.src.process.isolatedlib.sys.src.process.isolated.terminateAndReap[function] — private source atlib/sys/src/process/isolated.zig:363in nearest public ownerlib.sys.src.process.isolated
Complete call list for process.forkContained
7 direct calls.
lib.sys.src.linux.errno[function] — private source atlib/sys/src/linux.zig:17in nearest public ownerlib.sys.src.linuxlib.sys.src.process.namespace.childReady[function] — private source atlib/sys/src/process/namespace.zig:84in nearest public ownerlib.sys.src.process.namespacelib.sys.src.process.namespace.closeDescriptor[function] — private source atlib/sys/src/process/namespace.zig:149in nearest public ownerlib.sys.src.process.namespacelib.sys.src.process.namespace.mapIdentity[function] — private source atlib/sys/src/process/namespace.zig:127in nearest public ownerlib.sys.src.process.namespacelib.sys.src.process.namespace.receiveReady[function] — private source atlib/sys/src/process/namespace.zig:103in nearest public ownerlib.sys.src.process.namespacelib.sys.src.process.namespace.sendReady[function] — private source atlib/sys/src/process/namespace.zig:111in nearest public ownerlib.sys.src.process.namespacelib.sys.src.process.namespace.writeControl[function] — private source atlib/sys/src/process/namespace.zig:135in nearest public ownerlib.sys.src.process.namespace
Audit
| Definitions | 91 |
|---|---|
| Public names | 92 |
| Members | 77 |
| Version | 26.7.0 |
| Revision | daab053ee433 |