From 90cc41de320e8930950bf53dc6a7de228920a97a Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Mon, 12 Oct 2026 11:26:28 +0000 Subject: [PATCH] Replace the session-keyring option with a configure option Join the new session keyring when the server starts rather than once the configuration file has been loaded, and control it at build time with --enable-keyring, on by default if linux/keyctl.h is found. Rename keyring_join and keyring_revoke to new_session_keyring and revoke_session_keyring. --- cfg.c | 4 ---- compat.h | 4 ++-- compat/keyring-linux.c | 4 ++-- configure.ac | 16 ++++++++++---- options-table.c | 8 ------- regress/session-keyring.sh | 44 +++++++++++--------------------------- server.c | 6 +++++- tmux.1 | 8 ------- 8 files changed, 34 insertions(+), 60 deletions(-) diff --git a/cfg.c b/cfg.c index 17c01ad64..31294f92a 100644 --- a/cfg.c +++ b/cfg.c @@ -62,10 +62,6 @@ cfg_done(__unused struct cmdq_item *item, __unused void *data) } prompt_load_history(); -#ifdef HAVE_KEYCTL - if (options_get_number(global_options, "session-keyring")) - keyring_join(); -#endif return (CMD_RETURN_NORMAL); } diff --git a/compat.h b/compat.h index 0631b7252..4c74b7168 100644 --- a/compat.h +++ b/compat.h @@ -443,8 +443,8 @@ void *recallocarray(void *, size_t, size_t, size_t); #ifdef HAVE_KEYCTL /* keyring-linux.c */ -void keyring_join(void); -void keyring_revoke(void); +void new_session_keyring(void); +void revoke_session_keyring(void); #endif #ifdef HAVE_SYSTEMD diff --git a/compat/keyring-linux.c b/compat/keyring-linux.c index e777bbbbb..fb8e7126a 100644 --- a/compat/keyring-linux.c +++ b/compat/keyring-linux.c @@ -17,7 +17,7 @@ static long keyring_serial; * the login session's keyring when it ends). */ void -keyring_join(void) +new_session_keyring(void) { long serial; @@ -33,7 +33,7 @@ keyring_join(void) } void -keyring_revoke(void) +revoke_session_keyring(void) { if (keyring_serial == 0) return; diff --git a/configure.ac b/configure.ac index 139d93b88..8ce5ef9da 100644 --- a/configure.ac +++ b/configure.ac @@ -795,10 +795,18 @@ else AC_LIBOBJ(daemon) fi -# Look for linux/keyctl.h, compat/keyring-linux.c used if found. -AC_CHECK_HEADER(linux/keyctl.h, found_keyctl=yes, found_keyctl=no) -if test "x$found_keyctl" = xyes; then - AC_DEFINE(HAVE_KEYCTL) +# Look for linux/keyctl.h, compat/keyring-linux.c used if found and enabled. +AC_ARG_ENABLE( + keyring, + AS_HELP_STRING(--disable-keyring, disable giving the server its own Linux session keyring) +) +if test "x$enable_keyring" != xno; then + AC_CHECK_HEADER(linux/keyctl.h, found_keyctl=yes, found_keyctl=no) + if test "x$found_keyctl" = xyes; then + AC_DEFINE(HAVE_KEYCTL) + elif test "x$enable_keyring" = xyes; then + AC_MSG_ERROR("linux/keyctl.h not found") + fi fi AM_CONDITIONAL(HAVE_KEYCTL, [test "x$found_keyctl" = xyes]) diff --git a/options-table.c b/options-table.c index 813fc7b26..a65694973 100644 --- a/options-table.c +++ b/options-table.c @@ -532,14 +532,6 @@ const struct options_table_entry options_table[] = { .text = "Maximum number of commands to keep in history." }, - { .name = "session-keyring", - .type = OPTIONS_TABLE_FLAG, - .scope = OPTIONS_TABLE_SERVER, - .default_num = 1, - .text = "Whether the server should join a new session keyring " - "(Linux only)." - }, - { .name = "set-clipboard", .type = OPTIONS_TABLE_CHOICE, .scope = OPTIONS_TABLE_SERVER, diff --git a/regress/session-keyring.sh b/regress/session-keyring.sh index 8c854bdf6..07cc29acf 100644 --- a/regress/session-keyring.sh +++ b/regress/session-keyring.sh @@ -1,8 +1,8 @@ #!/bin/sh -# On Linux the server should join a session keyring of its own unless the -# session-keyring option is off, so it keeps working after the login session's -# keyring is revoked, and revoke it when it exits. +# On Linux the server should join a session keyring of its own, so it keeps +# working after the login session's keyring is revoked, and revoke it when it +# exits. PATH=/bin:/usr/bin TERM=screen @@ -12,10 +12,8 @@ keyctl session - true >/dev/null 2>&1 || exit 0 [ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) OUT=$(mktemp -d) -TMUX="$TEST_TMUX -LtestA$$ -f/dev/null" -TMUX2="$TEST_TMUX -LtestB$$ -f$OUT/conf" +TMUX="$TEST_TMUX -Ltest$$ -f/dev/null" $TMUX kill-server 2>/dev/null -$TMUX2 kill-server 2>/dev/null fail() { @@ -26,35 +24,11 @@ fail() cleanup() { $TMUX kill-server 2>/dev/null - $TMUX2 kill-server 2>/dev/null [ -s $OUT/holder ] && kill $(cat $OUT/holder) 2>/dev/null rm -rf "$OUT" } trap cleanup 0 1 15 -# Set KEYRING to the session keyring of a new pane on server $1. -pane_keyring() -{ - $1 new-window -d "keyctl id @s >$OUT/pane 2>&1; $1 wait-for -S pane" || - fail "could not create pane" - $1 wait-for pane - KEYRING=$(cat $OUT/pane) - case "$KEYRING" in - ''|*[!0-9]*) - fail "pane keyring not usable: $KEYRING" - ;; - esac -} - -# With the option off, the server should keep the keyring it was started with. -echo 'set -g session-keyring off' >$OUT/conf -OFF=$(keyctl session - sh -c " - $TMUX2 new -d 'sleep 1000' && keyctl id @s -" 2>/dev/null) || fail "could not start server" -pane_keyring "$TMUX2" -[ "$KEYRING" = "$OFF" ] || fail "pane has a new keyring with option off" -$TMUX2 kill-server - # Start the server from a login session with its own keyring, then revoke that # keyring as pam_keyinit(8) does when the login session ends. LOGIN=$(keyctl session - sh -c " @@ -62,7 +36,15 @@ LOGIN=$(keyctl session - sh -c " " 2>/dev/null) || fail "could not start server" # A new pane should still have a usable keyring, with the user keyring linked. -pane_keyring "$TMUX" +$TMUX new-window -d "keyctl id @s >$OUT/pane 2>&1; $TMUX wait-for -S pane" || + fail "could not create pane" +$TMUX wait-for pane +KEYRING=$(cat $OUT/pane) +case "$KEYRING" in +''|*[!0-9]*) + fail "pane keyring not usable: $KEYRING" + ;; +esac [ "$KEYRING" != "$LOGIN" ] || fail "pane has the login keyring" keyctl rlist $KEYRING | grep -qw "$(keyctl id @u)" || fail "user keyring not linked" diff --git a/server.c b/server.c index bad77f5b8..a70a1502c 100644 --- a/server.c +++ b/server.c @@ -220,6 +220,10 @@ server_start(struct tmuxproc *client, uint64_t flags, struct event_base *base, TAILQ_INIT(&message_log); gettimeofday(&start_time, NULL); +#ifdef HAVE_KEYCTL + new_session_keyring(); +#endif + #ifdef HAVE_SYSTEMD server_fd = systemd_create_socket(flags, &cause); #else @@ -260,7 +264,7 @@ server_start(struct tmuxproc *client, uint64_t flags, struct event_base *base, job_kill_all(); prompt_save_history(); #ifdef HAVE_KEYCTL - keyring_revoke(); + revoke_session_keyring(); #endif exit(0); diff --git a/tmux.1 b/tmux.1 index b843d7e65..cf82a209f 100644 --- a/tmux.1 +++ b/tmux.1 @@ -5096,14 +5096,6 @@ each client. .It Ic prompt\-history\-limit Ar number Set the number of history items to save in the history file for each type of command prompt. -.It Xo Ic session\-keyring -.Op Cm on | off -.Xc -On Linux, if enabled (the default), the server joins a new session keyring with -the user keyring linked into it, rather than keeping the session keyring of the -login session it was started from, which may be revoked when that session ends. -The new keyring is revoked when the server exits. -This option is checked once the configuration file has been loaded. .It Xo Ic set\-clipboard .Op Cm on | external | off .Xc