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))) {