mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
iucvterm: Improve received message type and length checking
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 <hoeppner@linux.ibm.com> Signed-off-by: Hendrik Brueckner <brueckner@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
56a55901c1
commit
29db9032b3
@@ -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) \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))) {
|
||||
|
||||
Reference in New Issue
Block a user