From 461bf4de012d1e3257394cc63315863c46e0c287 Mon Sep 17 00:00:00 2001 From: "Christian S.J. Peron" Date: Wed, 11 Nov 2026 02:31:38 -0500 Subject: [PATCH] cblockd: fix heap overflow when replaying console history tty_trim_buffer() strips trailing whitespace and NULs from the console history before it is replayed to a newly attached client. If the scan never found a non-whitespace byte above input[0] (for example a history of just "\r\n"), the "new" pointer was left at 0 and the returned length was computed as len - (pointer - 0), which wraps to a huge size_t. dispatch_connect_console() then sent 64K frames past the end of the termbuf_to_contig() allocation, which crashed cblockd under ASAN and could send heap contents to the console client otherwise. Rewrite the function to count the length down instead of doing pointer arithmetic. This also checks input[0], which the old loop skipped, and casts to unsigned char before calling isspace(), because passing a negative char is undefined behaviour for bytes >= 0x80. Writing the terminating NUL at input[len] is safe because termbuf_to_contig() allocates t_tot_len + 1 bytes. --- src/cblockd/tty.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/cblockd/tty.c b/src/cblockd/tty.c index ebfb52b..290ea41 100644 --- a/src/cblockd/tty.c +++ b/src/cblockd/tty.c @@ -168,26 +168,12 @@ tty_console_session(const char *instance, int sock, int ttyfd) { char * tty_trim_buffer(char *input, size_t len, size_t *newlen) { - uintptr_t old, new; - char *ep; - if (len == 0) { - *newlen = 0; - return (input); + while (len > 0 && (isspace((unsigned char)input[len - 1]) || + input[len - 1] == '\0')) { + len--; } - new = 0; - ep = input + len - 1; - old = (uintptr_t) ep; - while (ep > input) { - if (isspace(*ep) || *ep == '\0') { - ep--; - continue; - } - new = (uintptr_t) ep; - ep++; - *ep = '\0'; - break; - } - *newlen = len - (old - new); + input[len] = '\0'; + *newlen = len; return (input); }