diff options
author | Edward Tomasz Napierala <trasz@FreeBSD.org> | 2017-10-11 23:13:06 +0100 |
---|---|---|
committer | Edward Tomasz Napierala <trasz@FreeBSD.org> | 2017-10-11 23:13:06 +0100 |
commit | 1e66cbd62e231f8ae47589cf4f1c0c6c62bb7ca8 (patch) | |
tree | e946b9ba349089ab4d04ac9d1f4e3ff8c96d0d9f /src/core | |
parent | 17b195021dc35b95b24c1cce6f2e891e0e6b85ec (diff) | |
download | irssi-1e66cbd62e231f8ae47589cf4f1c0c6c62bb7ca8.zip |
Improve Capsicum stdio limits to fix terminal state on exit.
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/capsicum.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 945d3197..5f2556ab 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -360,6 +360,38 @@ static void cmd_capsicum(const char *data, SERVER_REC *server, void *item) command_runsub("capsicum", data, server, item); } +/* + * The main difference between this and caph_limit_stdio(3) is that this + * one permits TIOCSETAW, which is requred for restoring the terminal state + * on exit. + */ +static int +limit_stdio_fd(int fd) +{ + cap_rights_t rights; + unsigned long cmds[] = { TIOCGETA, TIOCGWINSZ, TIOCSETAW, FIODTYPE }; + + cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_EVENT, CAP_FCNTL, + CAP_FSTAT, CAP_IOCTL, CAP_SEEK); + + if (cap_rights_limit(fd, &rights) < 0) { + g_warning("cap_rights_limit(3) failed: %s", strerror(errno)); + return (-1); + } + + if (cap_ioctls_limit(fd, cmds, nitems(cmds)) < 0) { + g_warning("cap_ioctls_limit(3) failed: %s", strerror(errno)); + return (-1); + } + + if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0) { + g_warning("cap_fcntls_limit(3) failed: %s", strerror(errno)); + return (-1); + } + + return (0); +} + static void cmd_capsicum_enter(void) { u_int mode; @@ -411,9 +443,9 @@ static void cmd_capsicum_enter(void) */ signal(SIGCHLD, SIG_IGN); - error = caph_limit_stdio(); - if (error != 0) { - g_warning("caph_limit_stdio(3) failed: %s", strerror(errno)); + if (limit_stdio_fd(STDIN_FILENO) != 0 || + limit_stdio_fd(STDOUT_FILENO) != 0 || + limit_stdio_fd(STDERR_FILENO) != 0) { signal_emit("capability mode failed", 1, strerror(errno)); return; } |