As requested in https://github.com/systemd/systemd/pull/27867#pullrequestreview-
1567161854.
/dev/console, /dev/tty0, and /dev/ttyN are "different" device nodes
that may point to a single underlying device. We want to use a single
lock so that we don't get a race if different writers are using a different
device path, so let's just always lock around /dev/console.
This effectively makes the locking less granular.
Fixup for
a0043bfa51281c2374878e2a98cf2a3ee10fd92c.
Fixes https://github.com/systemd/systemd/issues/28721.
Maybe fixes https://github.com/systemd/systemd/issues/28778 and
https://github.com/systemd/systemd/issues/28634.
#include "cgroup-setup.h"
#include "constants.h"
#include "cpu-set-util.h"
+#include "dev-setup.h"
#include "env-file.h"
#include "env-util.h"
#include "errno-list.h"
}
void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) {
- _cleanup_close_ int fd = -EBADF;
+ _cleanup_close_ int _fd = -EBADF, lock_fd = -EBADF;
const char *path = exec_context_tty_path(ASSERT_PTR(context));
+ int fd;
- /* 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.
- */
-
- 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 (p && p->stdin_fd >= 0)
+ fd = p->stdin_fd;
+ else if (path) {
+ fd = _fd = open_terminal(path, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
return;
-
- if (lock_generic(fd, LOCK_BSD, LOCK_EX) < 0)
- return;
} else
return; /* nothing to do */
+ /* Take a synchronization lock 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.
+ */
+ lock_fd = lock_dev_console();
+ if (lock_fd < 0)
+ return (void) log_debug_errno(lock_fd,
+ "Failed to lock /dev/console: %m");
+
if (context->tty_vhangup)
(void) terminal_vhangup_fd(fd);
#include "alloc-util.h"
#include "dev-setup.h"
+#include "fd-util.h"
#include "label-util.h"
+#include "lock-util.h"
#include "log.h"
#include "mkdir-label.h"
#include "nulstr-util.h"
#include "path-util.h"
+#include "terminal-util.h"
#include "umask-util.h"
#include "user-util.h"
+int lock_dev_console(void) {
+ _cleanup_close_ int fd = -EBADF;
+ int r;
+
+ fd = open_terminal("/dev/console", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
+ if (fd < 0)
+ return fd;
+
+ r = lock_generic(fd, LOCK_BSD, LOCK_EX);
+ if (r < 0)
+ return log_error_errno(r, "Failed to lock /dev/console: %m");
+
+ return TAKE_FD(fd);
+}
+
int dev_setup(const char *prefix, uid_t uid, gid_t gid) {
static const char symlinks[] =
"-/proc/kcore\0" "/dev/core\0"
#include <sys/types.h>
+int lock_dev_console(void);
+
int dev_setup(const char *prefix, uid_t uid, gid_t gid);
int make_inaccessible_nodes(const char *parent_dir, uid_t uid, gid_t gid);
#include "alloc-util.h"
#include "creds-util.h"
+#include "dev-setup.h"
#include "env-file.h"
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "io-util.h"
#include "locale-util.h"
-#include "lock-util.h"
#include "log.h"
#include "main-func.h"
#include "proc-cmdline.h"
static int run(int argc, char **argv) {
_cleanup_(context_done) Context c = {};
_cleanup_free_ char *vc = NULL;
- _cleanup_close_ int fd = -EBADF;
+ _cleanup_close_ int fd = -EBADF, lock_fd = -EBADF;
bool utf8, keyboard_ok;
unsigned idx = 0;
int r;
/* 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)
- return log_error_errno(r, "Failed to lock console: %m");
+ lock_fd = lock_dev_console();
+ if (lock_fd < 0) {
+ log_full_errno(lock_fd == -ENOENT ? LOG_DEBUG : LOG_ERR,
+ lock_fd,
+ "Failed to lock /dev/console%s: %m",
+ lock_fd == -ENOENT ? ", ignoring" : "");
+ if (lock_fd != -ENOENT)
+ return lock_fd;
+ }
(void) toggle_utf8_sysfs(utf8);
(void) toggle_utf8_vc(vc, fd, utf8);