** Description changed:
[ Impact ]
The tmux server in resolute (3.6a-2ubuntu0.1) crashes with SIGSEGV when a
control-mode notification is broadcast while another control-mode client
(`tmux -C` / `tmux -CC`) is still connecting. The crash takes down the whole
server, i.e. every session, window and process running inside tmux.
The broadcast loops in control-notify.c select clients with
- #define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
- ((c) != NULL && ((c)->flags & CLIENT_CONTROL))
+ #define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
+ ((c) != NULL && ((c)->flags & CLIENT_CONTROL))
CLIENT_CONTROL is set from the client's identify flags before control_start()
has allocated c->control_state, so a client in that window is selected and
control_write() dereferences the NULL control_state:
- #0 control_write (c=..., fmt="%%client-detached %s") control.c:414
(cs = 0x0)
- #1 control_notify_client_detached (cc=...)
control-notify.c:181
- #2 notify_callback (...) notify.c:144
- #3 cmdq_fire_callback / cmdq_next
cmd-queue.c:725/784
- #4 server_loop () server.c:272
+ #0 control_write (c=..., fmt="%%client-detached %s") control.c:414
(cs = 0x0)
+ #1 control_notify_client_detached (cc=...)
control-notify.c:181
+ #2 notify_callback (...) notify.c:144
+ #3 cmdq_fire_callback / cmdq_next
cmd-queue.c:725/784
+ #4 server_loop () server.c:272
(kernel: "tmux: server[...]: segfault at 20 ... error 4"). The same NULL
dereference is reachable through other control notifications too; we have
cores via control_notify_session_created ("%%sessions-changed") as well.
Anything that opens control-mode clients concurrently hits it: iTerm2's tmux
integration, editors/IDE integrations, and tools that run one `tmux -C` client
per session. On one workstation we have 16 tmux server crashes recorded by
systemd-coredump over five weeks. The most recent one killed 16 sessions
running ~100 long-lived processes.
Upstream fixed this in tmux commit e5a2a25faf ("Do not notify clients if not
fully initialized, from Ben Maurer in GitHub issue 4980", 2026-04-13). It adds
a NULL check on control_state. The fix is in tmux 3.7 and later, so stonking
(3.7b-1) and Debian sid (3.7c-1) already have it. 3.6b does not.
[ Test Plan ]
On an isolated socket (does not touch the user's default tmux server):
- #!/bin/sh
- SOCK=lp-ctl-race-$$
- tmux -L "$SOCK" -f /dev/null new-session -d -s s0 'sleep 600' || exit 1
- SPID=$(tmux -L "$SOCK" display-message -p '#{pid}')
- i=0
- while [ $i -lt 2000 ] && kill -0 "$SPID" 2>/dev/null; do
- for j in 1 2 3 4 5 6 7 8; do
- tmux -L "$SOCK" -C attach-session -t s0 </dev/null >/dev/null 2>&1 &
- done
- wait
- i=$((i+1))
- done
- if kill -0 "$SPID" 2>/dev/null; then
- echo "server survived $i rounds"; tmux -L "$SOCK" kill-server
- else
- echo "server CRASHED after $i rounds"
- fi
+ #!/bin/sh
+ SOCK=lp-ctl-race-$$
+ tmux -L "$SOCK" -f /dev/null new-session -d -s s0 'sleep 600' || exit 1
+ SPID=$(tmux -L "$SOCK" display-message -p '#{pid}')
+ i=0
+ while [ $i -lt 2000 ] && kill -0 "$SPID" 2>/dev/null; do
+ for j in 1 2 3 4 5 6 7 8; do
+ tmux -L "$SOCK" -C attach-session -t s0 </dev/null >/dev/null 2>&1 &
+ done
+ wait
+ i=$((i+1))
+ done
+ if kill -0 "$SPID" 2>/dev/null; then
+ echo "server survived $i rounds"; tmux -L "$SOCK" kill-server
+ else
+ echo "server CRASHED after $i rounds"
+ fi
With 3.6a-2ubuntu0.1 on amd64 this prints "server CRASHED after 7 rounds", and
the backtrace above is from that run. Expected with the fix: "server survived
2000 rounds".
[ Where problems could occur ]
The change only adds `(c)->control_state != NULL` to the
CONTROL_SHOULD_NOTIFY_CLIENT macro. The only behaviour change is that a
control client which has not finished connecting no longer receives
notifications that were emitted before it was ready. Such a client could not
have received them correctly anyway, because it had no output buffer yet. A
regression would show up as a control-mode client missing a notification
emitted during its own attach. Clients that are already attached are
unaffected.
[ Other Info ]
Upstream commit:
https://github.com/tmux/tmux/commit/e5a2a25fafb8ee107c230d8acad694f6b635f8bb
Upstream PR: https://github.com/tmux/tmux/pull/4980
- --- a/control-notify.c
- +++ b/control-notify.c
- @@ -24,7 +24,8 @@
- #define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
- - ((c) != NULL && ((c)->flags & CLIENT_CONTROL))
- + ((c) != NULL && ((c)->flags & CLIENT_CONTROL) && \
- + (c)->control_state != NULL)
+ --- a/control-notify.c
+ +++ b/control-notify.c
+ @@ -24,7 +24,8 @@
+ #define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
+ - ((c) != NULL && ((c)->flags & CLIENT_CONTROL))
+ + ((c) != NULL && ((c)->flags & CLIENT_CONTROL) && \
+ + (c)->control_state != NULL)
Release: Ubuntu 26.04 LTS (resolute), tmux 3.6a-2ubuntu0.1, amd64.
+
+ There are two other later commits that fix related issues (but are not
+ needed to fix this bug):
+
+ https://github.com/tmux/tmux/commit/31c93c483afa4f94ef2091c8d9f25db4731d0e7f
+ https://github.com/tmux/tmux/commit/881bec958e2fd9093ed2c8fd8f934196f6afa7da
+
+ They are omitted from the proposed patches, but can be added if the SRU
+ team deems it worthwhile.
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2169164
Title:
tmux server SIGSEGV in control_write() when a control-mode client is
still connecting (fixed upstream in 3.7)
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/tmux/+bug/2169164/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs