From 610bf0135118fd53ba84e643458e0f76a1e6a5de Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 15 Oct 2026 07:25:07 +0000 Subject: [PATCH] A few additional readonly checks, GitHub issue 5736 from gmkbenjamin at hotmail dot com. --- cmd-attach-session.c | 23 ++++++++++++++++++----- cmd-queue.c | 11 ++++++++++- cmd-send-keys.c | 6 ++++-- cmd-switch-client.c | 15 +++++++++++++-- format.c | 5 ++++- 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/cmd-attach-session.c b/cmd-attach-session.c index 923229eab..7146c98f5 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-attach-session.c,v 1.93 2026/10/09 13:12:14 nicm Exp $ */ +/* $OpenBSD: cmd-attach-session.c,v 1.94 2026/10/15 07:25:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -55,7 +55,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state target; enum cmd_find_type type; - int flags; + int flags, ro = 0; struct client *c = cmdq_get_client(item), *c_loop; struct session *s; struct winlink *wl; @@ -72,6 +72,14 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, if (c == NULL) return (CMD_RETURN_NORMAL); + if (c->flags & CLIENT_READONLY) { + if (dflag || xflag || cflag != NULL) { + cmdq_error(item, "client is read-only"); + return (CMD_RETURN_ERROR); + } + ro = 1; + } + if (server_client_check_nested(c)) { cmdq_error(item, "sessions should be nested with care, " "unset $TMUX to force"); @@ -91,6 +99,11 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, wl = target.wl; wp = target.wp; + if (ro && (wl != s->curw || (wp != NULL && wp != wp->window->active))) { + cmdq_error(item, "client is read-only"); + return (CMD_RETURN_ERROR); + } + if (wl != NULL) { if (wp != NULL) { window_redraw_active_switch(wp->window, wp); @@ -111,7 +124,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, if (fflag) server_client_set_flags(c, fflag); if (rflag) { - if (c->flags & CLIENT_READONLY) { + if (ro) { uid = proc_get_peer_uid(c->peer); if (uid != getuid()) { cmdq_error(item, "client is read-only"); @@ -134,7 +147,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, server_client_detach(c_loop, msgtype); } } - if (!Eflag) + if (!Eflag && (~c->flags & CLIENT_READONLY)) environ_update(s->options, c->environ, s->environ); server_client_set_session(c, s); @@ -158,7 +171,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, server_client_detach(c_loop, msgtype); } } - if (!Eflag) + if (!Eflag && (~c->flags & CLIENT_READONLY)) environ_update(s->options, c->environ, s->environ); server_client_set_session(c, s); diff --git a/cmd-queue.c b/cmd-queue.c index f96edd2dc..76382aa00 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-queue.c,v 1.124 2026/09/22 06:46:50 nicm Exp $ */ +/* $OpenBSD: cmd-queue.c,v 1.125 2026/10/15 07:25:07 nicm Exp $ */ /* * Copyright (c) 2013 Nicholas Marriott @@ -595,6 +595,15 @@ cmdq_fire_command(struct cmdq_item *item) flags = !!(state->flags & CMDQ_STATE_CONTROL); cmdq_guard(item, "begin", flags); + if (flags && + saved != NULL && + (saved->flags & CLIENT_READONLY) && + (~entry->flags & CMD_READONLY)) { + cmdq_error(item, "client is read-only"); + retval = CMD_RETURN_ERROR; + goto out; + } + if (item->client == NULL) item->client = cmd_find_client(item, NULL, 1); diff --git a/cmd-send-keys.c b/cmd-send-keys.c index f9f0360e4..3ca963ffb 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-send-keys.c,v 1.82 2026/10/09 13:12:14 nicm Exp $ */ +/* $OpenBSD: cmd-send-keys.c,v 1.83 2026/10/15 07:25:07 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -164,6 +164,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); struct cmd_find_state *target = cmdq_get_target(item); + struct client *c = cmdq_get_client(item); struct client *tc = cmdq_get_target_client(item); struct session *s = target->s; struct winlink *wl = target->wl; @@ -177,7 +178,8 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) u_int count = args_count(args); char *cause = NULL; - if (tc != NULL && tc->flags & CLIENT_READONLY && !args_has(args, 'X')) { + if ((c != NULL && (c->flags & CLIENT_READONLY) && c != tc) || + (tc != NULL && (tc->flags & CLIENT_READONLY) && !args_has(args, 'X'))) { cmdq_error(item, "client is read-only"); return (CMD_RETURN_ERROR); } diff --git a/cmd-switch-client.c b/cmd-switch-client.c index 19a04cf39..a2d0ee630 100644 --- a/cmd-switch-client.c +++ b/cmd-switch-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-switch-client.c,v 1.76 2026/10/09 13:12:14 nicm Exp $ */ +/* $OpenBSD: cmd-switch-client.c,v 1.77 2026/10/15 07:25:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -66,6 +66,11 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item) struct sort_criteria sort_crit; uid_t uid; + if (c != NULL && (c->flags & CLIENT_READONLY) && c != tc) { + cmdq_error(item, "client is read-only"); + return (CMD_RETURN_ERROR); + } + if (tflag != NULL && (tflag[strcspn(tflag, ":.%")] != '\0' || strcmp(tflag, "=") == 0)) { type = CMD_FIND_PANE; @@ -80,6 +85,12 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item) wl = target.wl; wp = target.wp; + if (c != NULL && (c->flags & CLIENT_READONLY) && + (wl != s->curw || (wp != NULL && wp != wp->window->active))) { + cmdq_error(item, "client is read-only"); + return (CMD_RETURN_ERROR); + } + if (args_has(args, 'r')) { if (tc->flags & CLIENT_READONLY) { uid = proc_get_peer_uid(c->peer); @@ -157,7 +168,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item) } } - if (!args_has(args, 'E')) + if (!args_has(args, 'E') && (~tc->flags & CLIENT_READONLY)) environ_update(s->options, tc->environ, s->environ); server_client_set_session(tc, s); diff --git a/format.c b/format.c index e391323f4..4d6993b82 100644 --- a/format.c +++ b/format.c @@ -1,4 +1,4 @@ -/* $OpenBSD: format.c,v 1.428 2026/10/13 10:21:58 nicm Exp $ */ +/* $OpenBSD: format.c,v 1.429 2026/10/15 07:25:07 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -4271,7 +4271,10 @@ format_create_add_item(struct format_tree *ft, struct cmdq_item *item) { struct key_event *event = cmdq_get_event(item); struct mouse_event *m = &event->m; + struct client *c = cmdq_get_client(item); + if (c != NULL && (c->flags & CLIENT_READONLY)) + ft->flags |= FORMAT_NOJOBS; cmdq_merge_formats(item, ft); memcpy(&ft->m, m, sizeof ft->m); }