X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=execute.c;h=a82d016cbcaed28a05d7d804b0e077a87219d360;hb=10a94420172b33a7472a16b2e829689dbc570cad;hp=5264b5009e73c919162d06c6e614e637f17f0337;hpb=b8d3418f7bc209427e27d76d3442987b6738cd1b;p=elogind.git diff --git a/execute.c b/execute.c index 5264b5009..a82d016cb 100644 --- a/execute.c +++ b/execute.c @@ -44,6 +44,9 @@ #include "securebits.h" #include "cgroup.h" +/* This assumes there is a 'tty' group */ +#define TTY_MODE 0620 + static int shift_fds(int fds[], unsigned n_fds) { int start, restart_from; @@ -70,7 +73,7 @@ static int shift_fds(int fds[], unsigned n_fds) { if ((nfd = fcntl(fds[i], F_DUPFD, i+3)) < 0) return -errno; - assert_se(close_nointr(fds[i]) == 0); + close_nointr_nofail(fds[i]); fds[i] = nfd; /* Hmm, the fd we wanted isn't free? Then @@ -88,7 +91,7 @@ static int shift_fds(int fds[], unsigned n_fds) { return 0; } -static int flags_fds(int fds[], unsigned n_fds, bool nonblock) { +static int flags_fds(const int fds[], unsigned n_fds, bool nonblock) { unsigned i; int r; @@ -134,7 +137,7 @@ static int open_null_as(int flags, int nfd) { if (fd != nfd) { r = dup2(fd, nfd) < 0 ? -errno : nfd; - close_nointr(fd); + close_nointr_nofail(fd); } else r = nfd; @@ -188,7 +191,7 @@ static int connect_logger_as(const ExecContext *context, ExecOutput output, cons if (fd != nfd) { r = dup2(fd, nfd) < 0 ? -errno : nfd; - close_nointr(fd); + close_nointr_nofail(fd); } else r = nfd; @@ -290,6 +293,7 @@ static int setup_output(const ExecContext *context, const char *ident) { static int setup_error(const ExecContext *context, const char *ident) { assert(context); + assert(ident); /* This expects the input and output are already set up */ @@ -326,6 +330,25 @@ static int setup_error(const ExecContext *context, const char *ident) { } } +static int chown_terminal(int fd, uid_t uid) { + struct stat st; + + assert(fd >= 0); + + /* This might fail. What matters are the results. */ + fchown(fd, uid, -1); + fchmod(fd, TTY_MODE); + + if (fstat(fd, &st) < 0) + return -errno; + + if (st.st_uid != uid || + st.st_mode != TTY_MODE) + return -EPERM; + + return 0; +} + static int setup_confirm_stdio(const ExecContext *context, int *_saved_stdin, int *_saved_stdout) { @@ -354,6 +377,11 @@ static int setup_confirm_stdio(const ExecContext *context, goto fail; } + if (chown_terminal(fd, getuid()) < 0) { + r = EXIT_STDIN; + goto fail; + } + if (dup2(fd, STDIN_FILENO) < 0) { r = EXIT_STDIN; goto fail; @@ -639,7 +667,7 @@ static int enforce_user(const ExecContext *context, uid_t uid) { int exec_spawn(ExecCommand *command, const ExecContext *context, - int *fds, unsigned n_fds, + int fds[], unsigned n_fds, bool apply_permissions, bool apply_chroot, bool confirm_spawn, @@ -814,6 +842,12 @@ int exec_spawn(ExecCommand *command, goto fail; } + if (is_terminal_input(context->std_input)) + if (chown_terminal(STDIN_FILENO, uid) < 0) { + r = EXIT_STDIN; + goto fail; + } + if (apply_chroot) { if (context->root_directory) if (chroot(context->root_directory) < 0) {