summaryrefslogtreecommitdiff
path: root/lib/libc/stdlib
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2022-05-21 00:53:54 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2022-05-21 00:53:54 +0000
commit91e9c5ecae1b5322785238ca8043f248742993bf (patch)
tree4532407fa65233dcc500193247983ccfc41e7423 /lib/libc/stdlib
parent5d07f899709a13368c473f22de6dbbdca0c5cb43 (diff)
system(3) should ignore SIGINT and SIGQUIT until the shell exits.
This got broken when system.c was converted from signal(3) to sigaction(2). Also add SIGINT and SIGQUIT to the set of blocked signals and unblock them in the parent after the signal handlers are installed. Based on a diff from Leon Fischer. OK deraadt@
Diffstat (limited to 'lib/libc/stdlib')
-rw-r--r--lib/libc/stdlib/system.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/lib/libc/stdlib/system.c b/lib/libc/stdlib/system.c
index fe718276b92..28f01a9c5dd 100644
--- a/lib/libc/stdlib/system.c
+++ b/lib/libc/stdlib/system.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: system.c,v 1.12 2016/03/13 18:34:21 guenther Exp $ */
+/* $OpenBSD: system.c,v 1.13 2022/05/21 00:53:53 millert Exp $ */
/*
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
@@ -33,6 +33,7 @@
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <paths.h>
@@ -40,7 +41,7 @@ int
system(const char *command)
{
pid_t pid, cpid;
- struct sigaction intsave, quitsave;
+ struct sigaction intsave, quitsave, sa;
sigset_t mask, omask;
int pstat;
char *argp[] = {"sh", "-c", NULL, NULL};
@@ -52,6 +53,8 @@ system(const char *command)
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
sigprocmask(SIG_BLOCK, &mask, &omask);
switch (cpid = vfork()) {
case -1: /* error */
@@ -63,11 +66,21 @@ system(const char *command)
_exit(127);
}
- sigaction(SIGINT, NULL, &intsave);
- sigaction(SIGQUIT, NULL, &quitsave);
+ /* Ignore SIGINT and SIGQUIT while waiting for command to complete. */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGINT, &sa, &intsave);
+ sigaction(SIGQUIT, &sa, &quitsave);
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ sigprocmask(SIG_UNBLOCK, &mask, NULL);
+
do {
pid = waitpid(cpid, &pstat, 0);
} while (pid == -1 && errno == EINTR);
+
sigprocmask(SIG_SETMASK, &omask, NULL);
sigaction(SIGINT, &intsave, NULL);
sigaction(SIGQUIT, &quitsave, NULL);