Commit 9a764c1e authored by Julian Wiedmann's avatar Julian Wiedmann Committed by David S. Miller

s390/qeth: fix length check in SNMP processing

The response for a SNMP request can consist of multiple parts, which
the cmd callback stages into a kernel buffer until all parts have been
received. If the callback detects that the staging buffer provides
insufficient space, it bails out with error.
This processing is buggy for the first part of the response - while it
initially checks for a length of 'data_len', it later copies an
additional amount of 'offsetof(struct qeth_snmp_cmd, data)' bytes.

Fix the calculation of 'data_len' for the first part of the response.
This also nicely cleans up the memcpy code.

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e9d8faf9
...@@ -4518,8 +4518,8 @@ static int qeth_snmp_command_cb(struct qeth_card *card, ...@@ -4518,8 +4518,8 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
{ {
struct qeth_ipa_cmd *cmd; struct qeth_ipa_cmd *cmd;
struct qeth_arp_query_info *qinfo; struct qeth_arp_query_info *qinfo;
struct qeth_snmp_cmd *snmp;
unsigned char *data; unsigned char *data;
void *snmp_data;
__u16 data_len; __u16 data_len;
QETH_CARD_TEXT(card, 3, "snpcmdcb"); QETH_CARD_TEXT(card, 3, "snpcmdcb");
...@@ -4527,7 +4527,6 @@ static int qeth_snmp_command_cb(struct qeth_card *card, ...@@ -4527,7 +4527,6 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
cmd = (struct qeth_ipa_cmd *) sdata; cmd = (struct qeth_ipa_cmd *) sdata;
data = (unsigned char *)((char *)cmd - reply->offset); data = (unsigned char *)((char *)cmd - reply->offset);
qinfo = (struct qeth_arp_query_info *) reply->param; qinfo = (struct qeth_arp_query_info *) reply->param;
snmp = &cmd->data.setadapterparms.data.snmp;
if (cmd->hdr.return_code) { if (cmd->hdr.return_code) {
QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code); QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code);
...@@ -4540,10 +4539,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card, ...@@ -4540,10 +4539,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
return 0; return 0;
} }
data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data)); data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data));
if (cmd->data.setadapterparms.hdr.seq_no == 1) if (cmd->data.setadapterparms.hdr.seq_no == 1) {
data_len -= (__u16)((char *)&snmp->data - (char *)cmd); snmp_data = &cmd->data.setadapterparms.data.snmp;
else data_len -= offsetof(struct qeth_ipa_cmd,
data_len -= (__u16)((char *)&snmp->request - (char *)cmd); data.setadapterparms.data.snmp);
} else {
snmp_data = &cmd->data.setadapterparms.data.snmp.request;
data_len -= offsetof(struct qeth_ipa_cmd,
data.setadapterparms.data.snmp.request);
}
/* check if there is enough room in userspace */ /* check if there is enough room in userspace */
if ((qinfo->udata_len - qinfo->udata_offset) < data_len) { if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
...@@ -4556,16 +4560,9 @@ static int qeth_snmp_command_cb(struct qeth_card *card, ...@@ -4556,16 +4560,9 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
QETH_CARD_TEXT_(card, 4, "sseqn%i", QETH_CARD_TEXT_(card, 4, "sseqn%i",
cmd->data.setadapterparms.hdr.seq_no); cmd->data.setadapterparms.hdr.seq_no);
/*copy entries to user buffer*/ /*copy entries to user buffer*/
if (cmd->data.setadapterparms.hdr.seq_no == 1) { memcpy(qinfo->udata + qinfo->udata_offset, snmp_data, data_len);
memcpy(qinfo->udata + qinfo->udata_offset,
(char *)snmp,
data_len + offsetof(struct qeth_snmp_cmd, data));
qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
} else {
memcpy(qinfo->udata + qinfo->udata_offset,
(char *)&snmp->request, data_len);
}
qinfo->udata_offset += data_len; qinfo->udata_offset += data_len;
/* check if all replies received ... */ /* check if all replies received ... */
QETH_CARD_TEXT_(card, 4, "srtot%i", QETH_CARD_TEXT_(card, 4, "srtot%i",
cmd->data.setadapterparms.hdr.used_total); cmd->data.setadapterparms.hdr.used_total);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment