Skip to content

Commit bf7f827

Browse files
committed
std.process.Child: block signals during clone()
1 parent 6a3e64b commit bf7f827

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

lib/std/process/Child.zig

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ const ChildArg = struct {
534534
dev_null_fd: posix.fd_t,
535535
argv_buf: [:null]?[*:0]const u8,
536536
envp: [*:null]const ?[*:0]const u8,
537+
sigmask: ?*posix.sigset_t,
537538
ret_err: RetErr,
538539
};
539540

@@ -567,6 +568,28 @@ fn spawnPosixChildHelper(arg: usize) callconv(.c) u8 {
567568
posix.setpgid(0, pid) catch |err| return forkChildErrReport(&child_arg.ret_err, err);
568569
}
569570

571+
if (native_os == .linux and child_arg.sigmask != null) {
572+
std.debug.assert(linux.SIG.DFL == null);
573+
for (1..linux.NSIG) |sig| {
574+
if (sig == posix.SIG.KILL or sig == posix.SIG.STOP) {
575+
continue;
576+
}
577+
if (sig > std.math.maxInt(u6)) {
578+
// XXX: We cannot disable all signals.
579+
// sigaction accepts u6, which is too narrow.
580+
break;
581+
}
582+
var old_act: posix.Sigaction = undefined;
583+
const new_act = mem.zeroes(posix.Sigaction);
584+
// Do not use posix.sigaction. It reaches unreachable.
585+
_ = linux.sigaction(@intCast(sig), &new_act, &old_act);
586+
if (old_act.handler.handler == linux.SIG.IGN) {
587+
_ = linux.sigaction(@intCast(sig), &old_act, null);
588+
}
589+
}
590+
posix.sigprocmask(posix.SIG.SETMASK, child_arg.sigmask, null);
591+
}
592+
570593
const err = switch (child_arg.self.expand_arg0) {
571594
.expand => posix.execvpeZ_expandArg0(.expand, child_arg.argv_buf.ptr[0].?, child_arg.argv_buf.ptr, child_arg.envp),
572595
.no_expand => posix.execvpeZ_expandArg0(.no_expand, child_arg.argv_buf.ptr[0].?, child_arg.argv_buf.ptr, child_arg.envp),
@@ -692,6 +715,7 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void {
692715
.dev_null_fd = dev_null_fd,
693716
.argv_buf = argv_buf,
694717
.envp = envp,
718+
.sigmask = null,
695719
.ret_err = undefined,
696720
};
697721

@@ -703,6 +727,10 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void {
703727
immediateExit(spawnPosixChildHelper(@intFromPtr(&child_arg)));
704728
}
705729
} else {
730+
var old_mask: posix.sigset_t = undefined;
731+
posix.sigprocmask(posix.SIG.SETMASK, &linux.all_mask, &old_mask);
732+
defer posix.sigprocmask(posix.SIG.SETMASK, &old_mask, null);
733+
child_arg.sigmask = &old_mask;
706734
child_arg.ret_err = null;
707735
// Although the stack is fixed sized, we alloc it here,
708736
// because stack-smashing protection may have higher overhead than allocation.

0 commit comments

Comments
 (0)