summaryrefslogtreecommitdiff
path: root/usr.bin/tmux/window.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2017-07-12 10:04:52 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2017-07-12 10:04:52 +0000
commit535eb11fec1a0c5e06a96f69cb2fc284f482e932 (patch)
treebb6e66ddc8e7e6b6bac6effe303c4720e735d8f2 /usr.bin/tmux/window.c
parent4c10bb1e952802978efff50d3814cde68a5e5780 (diff)
Block signals between forking and clearing signal handlers (or calling
event_reinit) - if the child gets a signal and fires the libevent signal handler during this period it could write a signal into the parent's signal pipe. GitHub issue 1001 from Aaron van Geffen.
Diffstat (limited to 'usr.bin/tmux/window.c')
-rw-r--r--usr.bin/tmux/window.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/usr.bin/tmux/window.c b/usr.bin/tmux/window.c
index 083aaca03bb..c45a710c399 100644
--- a/usr.bin/tmux/window.c
+++ b/usr.bin/tmux/window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: window.c,v 1.202 2017/07/12 09:24:17 nicm Exp $ */
+/* $OpenBSD: window.c,v 1.203 2017/07/12 10:04:51 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -22,6 +22,7 @@
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
+#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -886,6 +887,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
const char *ptr, *first, *home;
struct termios tio2;
int i;
+ sigset_t set, oldset;
if (wp->fd != -1) {
bufferevent_free(wp->event);
@@ -915,14 +917,21 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
ws.ws_col = screen_size_x(&wp->base);
ws.ws_row = screen_size_y(&wp->base);
- wp->pid = fdforkpty(ptm_fd, &wp->fd, wp->tty, NULL, &ws);
- switch (wp->pid) {
+ sigfillset(&set);
+ sigprocmask(SIG_BLOCK, &set, &oldset);
+ switch (wp->pid = fdforkpty(ptm_fd, &wp->fd, wp->tty, NULL, &ws)) {
case -1:
wp->fd = -1;
+
xasprintf(cause, "%s: %s", cmd, strerror(errno));
free(cmd);
+
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
return (-1);
case 0:
+ proc_clear_signals(server_proc);
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+
if (chdir(wp->cwd) != 0) {
if ((home = find_home()) == NULL || chdir(home) != 0)
chdir("/");
@@ -936,6 +945,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0)
fatal("tcgetattr failed");
+ log_close();
closefrom(STDERR_FILENO + 1);
if (path != NULL)
@@ -943,9 +953,6 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
environ_set(env, "TMUX_PANE", "%%%u", wp->id);
environ_push(env);
- proc_clear_signals(server_proc);
- log_close();
-
setenv("SHELL", wp->shell, 1);
ptr = strrchr(wp->shell, '/');
@@ -978,6 +985,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
fatal("execl failed");
}
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
setblocking(wp->fd, 0);
wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,