diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 94c0dfd3de..804440ef2a 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -1172,7 +1172,6 @@ int xopenat_lock( int r; assert(dir_fd >= 0 || dir_fd == AT_FDCWD); - assert(path); assert(IN_SET(operation & ~LOCK_NB, LOCK_EX, LOCK_SH)); /* POSIX/UNPOSIX locks don't work on directories (errno is set to -EBADF so let's return early with diff --git a/src/core/execute.c b/src/core/execute.c index 3a0d289fa5..246c151ebc 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -268,25 +268,34 @@ static int exec_context_tty_size(const ExecContext *context, unsigned *ret_rows, } static void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) { - const char *path; + _cleanup_close_ int fd = -EBADF; + const char *path = exec_context_tty_path(ASSERT_PTR(context)); - assert(context); + /* Take a lock around the device for the duration of the setup that we do here. + * systemd-vconsole-setup.service also takes the lock to avoid being interrupted. + * We open a new fd that will be closed automatically, and operate on it for convenience. + */ - path = exec_context_tty_path(context); + if (p && p->stdin_fd >= 0) { + fd = xopenat_lock(p->stdin_fd, NULL, + O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY, 0, 0, LOCK_BSD, LOCK_EX); + if (fd < 0) + return; + } else if (path) { + fd = open_terminal(path, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) + return; - if (context->tty_vhangup) { - if (p && p->stdin_fd >= 0) - (void) terminal_vhangup_fd(p->stdin_fd); - else if (path) - (void) terminal_vhangup(path); - } + if (lock_generic(fd, LOCK_BSD, LOCK_EX) < 0) + return; + } else + return; /* nothing to do */ - if (context->tty_reset) { - if (p && p->stdin_fd >= 0) - (void) reset_terminal_fd(p->stdin_fd, true); - else if (path) - (void) reset_terminal(path); - } + if (context->tty_vhangup) + (void) terminal_vhangup_fd(fd); + + if (context->tty_reset) + (void) reset_terminal_fd(fd, true); if (p && p->stdin_fd >= 0) { unsigned rows = context->tty_rows, cols = context->tty_cols; diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 4d9915cbba..f2987412b9 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -26,6 +26,7 @@ #include "fileio.h" #include "io-util.h" #include "locale-util.h" +#include "lock-util.h" #include "log.h" #include "proc-cmdline.h" #include "process-util.h" @@ -589,6 +590,14 @@ int main(int argc, char **argv) { context_load_config(&c); + /* Take lock around the remaining operation to avoid being interrupted by a tty reset operation + * performed for services with TTYVHangup=yes. */ + r = lock_generic(fd, LOCK_BSD, LOCK_EX); + if (r < 0) { + log_error_errno(r, "Failed to lock console: %m"); + return EXIT_FAILURE; + } + (void) toggle_utf8_sysfs(utf8); (void) toggle_utf8_vc(vc, fd, utf8);