mirror of
https://github.com/tmux/tmux.git
synced 2026-10-15 16:04:34 +00:00
Give the server its own session keyring on Linux
The server otherwise keeps the session keyring of the login session that started it, which pam_keyinit(8) may revoke when that session ends, leaving the server and its panes unable to use the kernel keyring. Join a new session keyring with the user keyring linked in once the configuration file has been loaded, and revoke it when the server exits. This is controlled by a new session-keyring server option, on by default.
This commit is contained in:
@@ -239,6 +239,11 @@ if NEED_FORKPTY
|
||||
nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
|
||||
endif
|
||||
|
||||
# Add compat file for Linux session keyrings.
|
||||
if HAVE_KEYCTL
|
||||
nodist_tmux_SOURCES += compat/keyring-linux.c
|
||||
endif
|
||||
|
||||
# Add compat file for systemd.
|
||||
if HAVE_SYSTEMD
|
||||
nodist_tmux_SOURCES += compat/systemd.c
|
||||
|
||||
4
cfg.c
4
cfg.c
@@ -62,6 +62,10 @@ 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);
|
||||
}
|
||||
|
||||
6
compat.h
6
compat.h
@@ -441,6 +441,12 @@ void *reallocarray(void *, size_t, size_t);
|
||||
void *recallocarray(void *, size_t, size_t, size_t);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KEYCTL
|
||||
/* keyring-linux.c */
|
||||
void keyring_join(void);
|
||||
void keyring_revoke(void);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
/* systemd.c */
|
||||
int systemd_activated(void);
|
||||
|
||||
42
compat/keyring-linux.c
Normal file
42
compat/keyring-linux.c
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <linux/keyctl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/* Serial of the session keyring we joined, or 0 if none. */
|
||||
static long keyring_serial;
|
||||
|
||||
/*
|
||||
* Create a new session keyring since the current one belongs to the login
|
||||
* session which we're meant to outlive (and pam_keyinit(8) is likely to revoke
|
||||
* the login session's keyring when it ends).
|
||||
*/
|
||||
void
|
||||
keyring_join(void)
|
||||
{
|
||||
long serial;
|
||||
|
||||
serial = syscall(SYS_keyctl, KEYCTL_JOIN_SESSION_KEYRING, NULL);
|
||||
if (serial == -1) {
|
||||
log_debug("%s: join failed: %s", __func__, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (syscall(SYS_keyctl, KEYCTL_LINK, KEY_SPEC_USER_KEYRING,
|
||||
KEY_SPEC_SESSION_KEYRING) == -1)
|
||||
log_debug("%s: link failed: %s", __func__, strerror(errno));
|
||||
keyring_serial = serial;
|
||||
}
|
||||
|
||||
void
|
||||
keyring_revoke(void)
|
||||
{
|
||||
if (keyring_serial == 0)
|
||||
return;
|
||||
if (syscall(SYS_keyctl, KEYCTL_REVOKE, keyring_serial) == -1)
|
||||
log_debug("%s: revoke failed: %s", __func__, strerror(errno));
|
||||
}
|
||||
@@ -795,6 +795,13 @@ 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)
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_KEYCTL, [test "x$found_keyctl" = xyes])
|
||||
|
||||
# Look for stravis, compat/{vis,unvis}.c used if missing.
|
||||
AC_CHECK_FUNC(stravis, found_stravis=yes, found_stravis=no)
|
||||
if test "x$found_stravis" = xyes; then
|
||||
|
||||
@@ -532,6 +532,14 @@ 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,
|
||||
|
||||
3
server.c
3
server.c
@@ -259,6 +259,9 @@ server_start(struct tmuxproc *client, uint64_t flags, struct event_base *base,
|
||||
|
||||
job_kill_all();
|
||||
prompt_save_history();
|
||||
#ifdef HAVE_KEYCTL
|
||||
keyring_revoke();
|
||||
#endif
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
8
tmux.1
8
tmux.1
@@ -5096,6 +5096,14 @@ 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
|
||||
|
||||
Reference in New Issue
Block a user