diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/capsicum.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 3b0708cb..568b5542 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -32,12 +32,14 @@ #include "settings.h" #include "signals.h" -#include <sys/types.h> +#include <sys/param.h> #include <sys/capsicum.h> +#include <sys/filio.h> #include <sys/nv.h> #include <sys/procdesc.h> #include <sys/socket.h> #include <string.h> +#include <termios.h> #define OPCODE_CONNECT 1 #define OPCODE_GETHOSTBYNAME 2 @@ -181,6 +183,10 @@ void capsicum_mkdir_with_parents(const char *path, int mode) char *component, *copy, *tofree; int error, fd, newfd; + /* The directory already exists, nothing to do. */ + if (strcmp(path, irclogs_path) == 0) + return; + /* +1 is for the slash separating irclogs_path and the rest. */ if (strlen(path) <= irclogs_path_len + 1 || path[irclogs_path_len] != '/' || @@ -359,6 +365,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; @@ -410,6 +448,13 @@ static void cmd_capsicum_enter(void) */ signal(SIGCHLD, SIG_IGN); + 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; + } + error = cap_enter(); if (error != 0) { signal_emit("capability mode failed", 1, strerror(errno)); @@ -444,7 +489,7 @@ void capsicum_init(void) settings_add_bool("misc", "capsicum", FALSE); settings_add_str("misc", "capsicum_irclogs_path", "~/irclogs"); settings_add_int("misc", "capsicum_port_min", 6667); - settings_add_int("misc", "capsicum_port_max", 6697); + settings_add_int("misc", "capsicum_port_max", 9999); signal_add("irssi init finished", (SIGNAL_FUNC) sig_init_finished); |