diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-07-12 10:04:52 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-07-12 10:04:52 +0000 |
commit | 535eb11fec1a0c5e06a96f69cb2fc284f482e932 (patch) | |
tree | bb6e66ddc8e7e6b6bac6effe303c4720e735d8f2 /usr.bin/tmux/window.c | |
parent | 4c10bb1e952802978efff50d3814cde68a5e5780 (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.c | 20 |
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, |