[PATCH 3/5] unshare: replace signal blocking with signal handlers

Kiran Rangoon <[email protected]> Thu, 8 Jan 2026 13:31:32 -0500
Newsgroups org.kernel.vger.util-linux
Message-ID <[email protected]>
Replace sigprocmask(SIG_BLOCK) with sigaction() to install signal
handlers for SIGTERM and SIGINT. This allows the parent to catch
signals and forward them to the child, instead of just blocking them.

The forward_signal() handler installed in the previous commit will
now be called when SIGTERM/SIGINT is received.

Signed-off-by: Kiran Rangoon <[email protected]>
---
 sys-utils/unshare.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c
index 3850e5f4a..9255ff4f8 100644
--- a/sys-utils/unshare.c
+++ b/sys-utils/unshare.c
@@ -1116,11 +1116,23 @@ int main(int argc, char *argv[])
 		settime(monotonic, CLOCK_MONOTONIC);
 
 	if (forkit) {
+		struct sigaction sa;
+
+		/* Set up signal handler to forward signals to child */
+		memset(&sa, 0, sizeof(sa));
+		sa.sa_handler = forward_signal;
+		sigemptyset(&sa.sa_mask);
+		sa.sa_flags = SA_RESTART;
+
+		if (sigaction(SIGTERM, &sa, NULL) == -1)
+			err(EXIT_FAILURE, _("sigaction SIGTERM failed"));
+		if (sigaction(SIGINT, &sa, NULL) == -1)
+			err(EXIT_FAILURE, _("sigaction SIGINT failed"));
+
+		/* Save old mask for child to restore */
 		if (sigemptyset(&sigset) != 0 ||
-			sigaddset(&sigset, SIGINT) != 0 ||
-			sigaddset(&sigset, SIGTERM) != 0 ||
-			sigprocmask(SIG_BLOCK, &sigset, &oldsigset) != 0)
-			err(EXIT_FAILURE, _("sigprocmask block failed"));
+			sigprocmask(SIG_SETMASK, NULL, &oldsigset) != 0)
+			err(EXIT_FAILURE, _("sigprocmask failed"));
 #ifdef HAVE_PIDFD_OPEN
 		if (kill_child_signo != 0) {
 			/* make a connection to the original process (parent) */
-- 
2.47.3