This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch tymux
in repository terminology.
View the commit online.
commit 7412320f42071f90e04732981126843011683f37
Author: [email protected] <[email protected]>
AuthorDate: Wed Mar 18 22:53:27 2026 -0600
fix: add cmsg_len validation for SCM_RIGHTS and improve tymux attach robustness
Critical security fix: validate cmsg_len before dereferencing SCM_RIGHTS
control message to prevent reading garbage fd from truncated messages.
Additional improvements to the tymux attach inline terminal proxy:
- Safe multiplication: cast before multiplying to prevent integer overflow
- Handle Terminology-internal colour codes (COL_INVIS, COL_INVERSE,
COL_INVERSEBG) by falling back to default ANSI colours
- Respect invisible cell attribute when rendering glyphs
- Validate session name length to prevent buffer overflows
- Improve SIGINT handler documentation and user feedback
Applies validation fix symmetrically in both tymux.c and termsrv.c.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
src/bin/termsrv.c | 3 ++-
src/bin/tymux.c | 32 ++++++++++++++++++++++++--------
2 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/src/bin/termsrv.c b/src/bin/termsrv.c
index 6e113d05..6e85599b 100644
--- a/src/bin/termsrv.c
+++ b/src/bin/termsrv.c
@@ -225,7 +225,8 @@ termsrv_recv_attached(int sock_fd, int *shm_fd_out,
if (hdr.type != TSRV_MSG_ATTACHED) return -1;
struct cmsghdr *cm = CMSG_FIRSTHDR(&msg);
- if (!cm || cm->cmsg_type != SCM_RIGHTS) return -1;
+ if (!cm || cm->cmsg_type != SCM_RIGHTS ||
+ cm->cmsg_len < CMSG_LEN(sizeof(int))) return -1;
memcpy(shm_fd_out, CMSG_DATA(cm), sizeof(int));
*cols_out = pl.cols;
diff --git a/src/bin/tymux.c b/src/bin/tymux.c
index 1242db9c..ead76108 100644
--- a/src/bin/tymux.c
+++ b/src/bin/tymux.c
@@ -316,7 +316,8 @@ _proto_recv_attached(int sock_fd, int *shm_fd_out,
if (hdr.type != _TSRV_MSG_ATTACHED) return -1;
struct cmsghdr *cm = CMSG_FIRSTHDR(&msg);
- if (!cm || cm->cmsg_type != SCM_RIGHTS) return -1;
+ if (!cm || cm->cmsg_type != SCM_RIGHTS ||
+ cm->cmsg_len < CMSG_LEN(sizeof(int))) return -1;
memcpy(shm_fd_out, CMSG_DATA(cm), sizeof(int));
*cols_out = pl.cols;
@@ -461,7 +462,7 @@ _render_screen(const void *shm, uint32_t cols, uint32_t rows)
/* Output buffer — worst case ~6 bytes/cell (UTF-8) + ~40 bytes ANSI/cell.
* We heap-alloc to avoid large stack frames. */
- size_t bufsz = (size_t)(scols * srows) * 50 + 256;
+ size_t bufsz = (size_t)scols * (size_t)srows * 50 + 256;
char *out = malloc(bufsz);
if (!out) return;
@@ -541,8 +542,11 @@ _render_screen(const void *shm, uint32_t cols, uint32_t rows)
else
{
/* Standard ANSI: 0=default fg, 1..8=colours 30..37,
- * fgintense shifts to 90..97 range. */
- if (c->att.fg == 0)
+ * fgintense shifts to 90..97 range.
+ * Values >8 (COL_INVIS=9, COL_INVERSE=10,
+ * COL_INVERSEBG=11) are Terminology-internal and
+ * have no ANSI mapping — fall back to default fg. */
+ if (c->att.fg == 0 || c->att.fg > 8)
EMIT("\033[39m"); /* default fg */
else
{
@@ -565,7 +569,9 @@ _render_screen(const void *shm, uint32_t cols, uint32_t rows)
}
else
{
- if (c->att.bg == 0)
+ /* Values >8 are Terminology-internal (COL_INVIS etc.)
+ * with no ANSI mapping — fall back to default bg. */
+ if (c->att.bg == 0 || c->att.bg > 8)
EMIT("\033[49m"); /* default bg */
else
{
@@ -577,9 +583,9 @@ _render_screen(const void *shm, uint32_t cols, uint32_t rows)
cur_bg256 = (int)c->att.bg256;
}
- /* Output the glyph (or space for empty / control cells) */
+ /* Output the glyph (or space for empty / control / invisible cells) */
uint32_t cp = c->codepoint;
- if (cp == 0 || cp < 0x20)
+ if (c->att.invisible || cp == 0 || cp < 0x20)
{
if (pos < bufsz - 1) out[pos++] = ' ';
}
@@ -810,6 +816,13 @@ cmd_attach(int argc, char **argv)
const char *name = argv[2];
+ if (strlen(name) > TYMUX_MAX_SESSION_NAME)
+ {
+ fprintf(stderr, "tymux: session name too long (max %d chars)\n",
+ TYMUX_MAX_SESSION_NAME);
+ return 1;
+ }
+
/* Warn if we are already inside a tymux session. */
if (getenv("TYMUX_SESSION"))
fprintf(stderr,
@@ -943,8 +956,11 @@ cmd_attach(int argc, char **argv)
if (_got_int)
{
- /* User pressed Ctrl+C — detach cleanly. */
+ /* Received SIGINT (external kill) — detach cleanly.
+ * In raw mode, Ctrl+C sends 0x03 as data, not a signal;
+ * this handler fires only for signals from external processes. */
_got_int = 0;
+ write(STDERR_FILENO, "\r\ntymux: received SIGINT, detaching\r\n", 37);
_proto_send(sock, _TSRV_MSG_DETACH, NULL, 0);
running = 0;
break;
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.