From c85b4e54dd943cada0afca4c5ec03a75780284c5 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Mon, 6 Jul 2026 11:30:56 +0200 Subject: [PATCH] iucvterm/iucvtty: Validate TERM environment name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve handling of TERM environment processing by validating the received terminal name. If the terminal name is not valid, a message will be displayed and the default terminal will be used. Reviewed-by: Steffen Eiden Signed-off-by: Hendrik Brueckner Signed-off-by: Jan Höppner --- iucvterm/include/iucvterm/functions.h | 1 + iucvterm/include/iucvterm/proto.h | 2 +- iucvterm/src/functions.c | 32 +++++++++++++++++++++++++-- iucvterm/src/iucvtty.c | 14 ++++++++++-- 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/iucvterm/include/iucvterm/functions.h b/iucvterm/include/iucvterm/functions.h index 90fe4938..0eb7d973 100644 --- a/iucvterm/include/iucvterm/functions.h +++ b/iucvterm/include/iucvterm/functions.h @@ -62,6 +62,7 @@ extern ssize_t __write(int, const void*, size_t); extern int strmatch(const char *, const char *); extern int is_regex_valid(const char *); extern int is_client_allowed(const char *, const struct iucvterm_cfg *); +extern int is_term_valid(const char *term, size_t len); extern void userid_cpy(char [9], const char [8]); extern void iucv_msg_error(const char *, uint32_t); diff --git a/iucvterm/include/iucvterm/proto.h b/iucvterm/include/iucvterm/proto.h index 0391a236..e30e651a 100644 --- a/iucvterm/include/iucvterm/proto.h +++ b/iucvterm/include/iucvterm/proto.h @@ -86,7 +86,7 @@ static inline struct iucvtty_msg *msg_alloc(uint8_t type, uint16_t size) { struct iucvtty_msg *m; - m = malloc(size + MSG_DATA_OFFSET); + m = calloc(1, size + MSG_DATA_OFFSET); if (m != NULL) { m->version = MSG_VERSION; m->type = type; diff --git a/iucvterm/src/functions.c b/iucvterm/src/functions.c index 80b1f1a3..e832dafd 100644 --- a/iucvterm/src/functions.c +++ b/iucvterm/src/functions.c @@ -8,6 +8,7 @@ * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ +#include #include #include #include @@ -148,10 +149,12 @@ int iucvtty_rx_termenv(int fd, void *buf, size_t len) rc = iucvtty_read_msg(fd, msg, msg_size(msg), &skip); iucvtty_skip_msg_residual(fd, &skip); if (!rc) { - if (msg->datalen == 0) + if (msg->datalen == 0) { memset(buf, 0, MIN(1u, len)); - else + } else { msg_cpy_to(msg, buf, len); + memset(buf + MIN(msg->datalen, len - 1), 0, 1); + } } msg_free(msg); return rc; @@ -501,6 +504,31 @@ int is_client_allowed(const char *client, const struct iucvterm_cfg *cfg) return strmatch(client, cfg->client_re); } +/** + * is_term_valid() - Validate TERM environment value + * @term: Terminal environment name to validate + * @len: Maximum number of characters to validate + */ +int is_term_valid(const char *term, size_t len) +{ + const char *c; + + if (term == NULL || *term == '\0') + return 0; + + for (c = term; *c != '\0'; c++) { + if ((size_t)(c - term) >= len) + return 0; + if (!isalnum((unsigned char)*c) && + *c != '.' && + *c != '_' && + *c != '-') + return 0; + } + + return 1; +} + /** * userid_cpy() - Copy z/VM user ID and skip trailing spaces. * @dest: Destination buffer diff --git a/iucvterm/src/iucvtty.c b/iucvterm/src/iucvtty.c index d0a66bce..f1dbaa8d 100644 --- a/iucvterm/src/iucvtty.c +++ b/iucvterm/src/iucvtty.c @@ -69,6 +69,10 @@ static int exec_login_prog(char *cmd[]) * @master: PTY master file descriptor * @slave: PTY slave file descriptor * @cfg: IUCV TTY configuration structure. + * + * Unlike the HVC IUCV terminal device driver, iucvtty expects to + * receive the TERM environment first. This is necessary to correctly + * set up the login program. */ static int iucvtty_worker(int client, int master, int slave, const struct iucvterm_cfg *cfg) @@ -84,9 +88,15 @@ static int iucvtty_worker(int client, int master, int slave, /* flush pending terminal data */ tcflush(master, TCIOFLUSH); - /* read terminal parameters from client */ + /* read and validate terminal parameters from client */ + memset(term_env, 0, sizeof(term_env)); if (iucvtty_rx_termenv(client, term_env, TERM_BUFSIZE)) - sprintf(term_env, TERM_DEFAULT); + snprintf(term_env, sizeof(term_env), "%s", TERM_DEFAULT); + + if (!is_term_valid(term_env, sizeof(term_env))) { + print_error("Ignoring received TERM env due to invalid character(s)"); + snprintf(term_env, sizeof(term_env), "%s", TERM_DEFAULT); + } /* start login program */ child = fork();