V OpenBSD i tmuxu od 2. 10. 2026  Oprava chyby v tmuxu v upstreamu

tmux: pád serveru při copy-mode -S bez připojeného klienta

BudgetScan odhalil chybějící kontrolu NULL ukazatele v obsluze copy-mode -S v tmuxu, celosvětově používaném terminálovém multiplexeru. Při vyvolání v kontextu serveru bez připojeného terminálového klienta (například z hooků nebo front příkazů na pozadí) vedla chybějící kontrola k pádu serveru tmux daného uživatele na SIGSEGV, což ukončilo všechny jeho relace i programy, které v nich běžely. Nicholas Marriott, autor a hlavní správce tmuxu, přijal naši zprávu a začlenil opravu přímo do CVS OpenBSD.

Co bylo špatně

Příkaz copy-mode nabízí přepínač -S pro posouvání historie pomocí událostí posuvníku myši. Při provádění funkce cmd_copy_mode_exec() získává tmux odkaz na aktivního klienta příkazu voláním cmdq_get_client(item).

Pokud příkaz spustí interaktivní terminálový klient, ukazuje c na strukturu klienta a jeho terminál (c->tty). Příkazy v tmuxu však mohou být vyvolány také na úrovni serveru zcela bez připojeného terminálu — například z konfiguračního souboru ~/.tmux.conf, přes automatizaci na pozadí nebo ze systémových hooků jako pane-died (set-hook -g pane-died "copy-mode -S").

V těchto situacích bez klienta je c rovno NULL. Zatímco sousední větev pro myš (-M) tento stav správně ošetřila:

if (c == NULL || c->session != s)
    return (CMD_RETURN_NORMAL);

ve větvi -S tato kontrola zcela chyběla. Kód okamžitě předal &c->tty do funkce tty_window_offset(), což vedlo k okamžitému pádu na neplatnou paměť (SIGSEGV). Jeden serverový proces tmuxu obsluhuje všechny relace daného uživatele (ve výchozím nastavení má každý uživatel vlastní server a socket), takže pád ukončil všechna okna a panely tohoto serveru i programy, které v nich běžely. Spouštěčem je příkaz bez klienta, třeba z hooku ve vlastní konfiguraci uživatele, takže jde o opravu robustnosti, ne o bezpečnostní zranitelnost.

Řídicí tok v tmux copy-mode -S Serverový hook vyvolá copy-mode -S bez připojeného klienta. cmdq_get_client vrátí NULL. Před opravou způsobil neověřený ukazatel pád serveru. Po opravě funkce bezpečně vrátí návratový kód. Serverový hook či frontaspustí copy-mode -S (např. hook pane-died) cmdq_get_client(item)není připojen klient → c je NULL NOVĚ: if (c == NULL) returnošetřeno: vrátí CMD_RETURN_NORMAL tty_window_offset(&c->tty)spustí se pouze při připojeném klientovi Server pokračuje v běhuvšechny relace a procesy zůstanou živé dříve: SIGSEGV pád serveru
Průchod kódem v copy-mode -S. Před opravou vedlo spuštění bez klienta k obejití jakékoli kontroly (červená čára) a okamžitému pádu serverového démona tmux.
Ilustrace: Záznam v OpenBSD CVS revize 1.55 se jménem Martin Vlach, diff ošetřující cmd-copy-mode.c a potvrzení správce Nicholase Marriotta.
Upstreamové ověření v CVS OpenBSD. Revize 1.55 začleněná Nicholasem Marriottem (nicm): „Do not use client for copy-mode -S if NULL, reported by Martin Vlach.“

Jak to bylo opraveno

Odeslali jsme pull request s defenzivní kontrolou ukazatele a automatickým regresním testem reprodukujícím pád bez připojeného klienta:

Index: src/usr.bin/tmux/cmd-copy-mode.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd-copy-mode.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -p -r1.54 -r1.55
--- src/usr.bin/tmux/cmd-copy-mode.c	14 Jul 2026 17:17:17 -0000	1.54
+++ src/usr.bin/tmux/cmd-copy-mode.c	2 Oct 2026 12:12:51 -0000	1.55
@@ -103,6 +103,8 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
 	if (args_has(args, 'd'))
 		window_copy_pagedown(wp, 0, args_has(args, 'e'));
 	if (args_has(args, 'S')) {
+		if (c == NULL)
+			return (CMD_RETURN_NORMAL);
 		tty_window_offset(&c->tty, &tty_ox, &tty_oy, &tty_sx, &tty_sy);
 		window_copy_scroll(wp, c->tty.mouse_slider_mpos, event->m.y,
 		    tty_oy, args_has(args, 'e'));

Přiložený regresní test (regress/copy-mode-no-client-scroll.sh) vyvolá copy-mode -S z hooku pane-died bez připojeného klienta. Na původním kódu test okamžitě reprodukoval segmentation fault; s nasazenou opravou server příkaz bezpečně ignoroval a test doběhl zelený.

Správce Nicholas Marriott opravu přijal a začlenil revizi 1.55 přímo do stromu OpenBSD:

„Applied to OpenBSD now, will be in GitHub later. Thanks!“

A tak se i stalo: týž den odpoledne se změna přenesla do tmuxu na GitHubu jako commit 5932140.

Časová osa

Jak to číst

Skener poukázal na nechráněný ukazatel jako na konkrétní podnět. Inženýr prověřil řídicí tok, izoloval spuštění přes hooky, napsal reprodukovatelný test a připravil opravu. Upstreamový správce Nicholas Marriott ji zvalidoval a začlenil do OpenBSD. Přesně tak má automatizované skenování fungovat: nálezy slouží lidem k prověření, nikoli jako nezpochybnitelné ortely. Velké díky patří Nicholasi Marriottovi za okamžitou, vstřícnou reakci a bezproblémové začlenění do OpenBSD.

Zdroje

← Zpět na příběhy úspěchu