From 29db9032b3ea9997ad65d76b04c74c011e0bf892 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Mon, 6 Jul 2026 13:27:31 +0200 Subject: [PATCH] iucvterm: Improve received message type and length checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The iucvtty_read_msg() now receives the entire message header. Perform message header checks for specific message types where the payload length is clearly defined. Also this needs to be done prior starting the message chunk processing because the message datalen field will be adjusted based on the read chunks. Reviewed-by: Jan Höppner Signed-off-by: Hendrik Brueckner Signed-off-by: Jan Höppner --- iucvterm/include/iucvterm/functions.h | 3 ++ iucvterm/src/functions.c | 54 ++++++++++++++++++++++++++- iucvterm/src/iucvtty.c | 5 +-- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/iucvterm/include/iucvterm/functions.h b/iucvterm/include/iucvterm/functions.h index b1165de2..e33299ac 100644 --- a/iucvterm/include/iucvterm/functions.h +++ b/iucvterm/include/iucvterm/functions.h @@ -21,6 +21,9 @@ /* Message buffer: message header + 4096 bytes of data */ #define MSG_BUFFER_SIZE (MSG_DATA_OFFSET + (4096)) +/* Message data sizes */ +#define MAX_TERM_SIZE 256 + /* Error macros */ #define print_error(s) program_error(PRG_COMPONENT, (s)) #define iucvtty_error(m) \ diff --git a/iucvterm/src/functions.c b/iucvterm/src/functions.c index 1a298543..dff832d2 100644 --- a/iucvterm/src/functions.c +++ b/iucvterm/src/functions.c @@ -145,14 +145,16 @@ int iucvtty_tx_termenv(int dest, char *dflt) len = 0; if (term != NULL) - len = 1 + strlen(term); + len = MIN(1 + strlen(term), (size_t)MAX_TERM_SIZE); /* Note: The server console tool waits for terminal environment * information: the message is sent even if it is empty */ msg = msg_alloc(MSG_TYPE_TERMENV, len); if (msg == NULL) return -1; - msg_cpy_from(msg, term, len); + msg->datalen = len; + if (msg->datalen) + snprintf((char *)msg->data, msg->datalen, "%s", term); rc = iucvtty_write_msg(dest, msg); msg_free(msg); @@ -353,6 +355,44 @@ static int iucvtty_read_msg_chunk(int fd, struct iucvtty_msg *msg, return 0; } +/** + * validate_msg() - Perform sanity checks on a received message + * @msg: IUCV message buffer + * + * Returns zero if the message is valid; otherwise non-zero + */ +static int validate_msg(struct iucvtty_msg *msg) +{ + switch (msg->type) { + case MSG_TYPE_DATA: + /* The datalen ranges from 0 to its maximum of 0xffff + * which is the maximum of the type definition of uint16_t. + * + * Consider the datalen value as valid. + */ + break; + case MSG_TYPE_ERROR: + if (msg->datalen != sizeof(uint32_t)) + return 1; + break; + case MSG_TYPE_TERMENV: + if (msg->datalen > MAX_TERM_SIZE) + return 1; + break; + case MSG_TYPE_TERMIOS: /* ignored */ + break; + case MSG_TYPE_WINSIZE: + if (msg->datalen != sizeof(struct winsize)) + return 1; + break; + default: + /* Invalid message type */ + return 1; + } + + return 0; +} + /** * iucvtty_read_msg() - Read/Receive an IUCV message * @fd: File descriptor to read from @@ -409,6 +449,16 @@ int iucvtty_read_msg(int fd, struct iucvtty_msg *msg, if (!msg->datalen) return 0; + /* Check message type and data length */ + if (validate_msg(msg)) { + fprintf(stderr, _("%s: %s\n"), + PRG_COMPONENT, _("The received message is invalid")); + fprintf(stderr, "MSG: msg->version=%u msg->type=%u msg->datalen=%u\n", + msg->version, msg->type, msg->datalen); + rc = -3; + goto out_read_error; + } + /* Process the new message as a one chunk */ *chunk = msg->datalen; msg->datalen = 0; diff --git a/iucvterm/src/iucvtty.c b/iucvterm/src/iucvtty.c index 5296132e..ae1be578 100644 --- a/iucvterm/src/iucvtty.c +++ b/iucvterm/src/iucvtty.c @@ -32,7 +32,6 @@ #define SYSLOG_IDENT "iucvtty" #define PRG_COMPONENT SYSLOG_IDENT -#define TERM_BUFSIZE 256 #define TERM_DEFAULT "linux" @@ -82,7 +81,7 @@ static int iucvtty_worker(int client, int master, int slave, pid_t child; fd_set set; size_t chunk; - char term_env[TERM_BUFSIZE]; + char term_env[MAX_TERM_SIZE]; /* flush pending terminal data */ @@ -90,7 +89,7 @@ static int iucvtty_worker(int client, int master, int slave, /* read and validate terminal parameters from client */ memset(term_env, 0, sizeof(term_env)); - if (iucvtty_rx_termenv(client, term_env, TERM_BUFSIZE)) + if (iucvtty_rx_termenv(client, term_env, MAX_TERM_SIZE)) snprintf(term_env, sizeof(term_env), "%s", TERM_DEFAULT); if (!is_term_valid(term_env, sizeof(term_env))) {