Skip to content

Commit

Permalink
s390/qeth: fix length check in SNMP processing
Browse files Browse the repository at this point in the history
[ Upstream commit 9a764c1 ]

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: 1da177e ("Linux-2.6.12-rc2")
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
julianwiedmann authored and gregkh committed Dec 5, 2018
1 parent 13a3d89 commit 1d3891c
Showing 1 changed file with 12 additions and 15 deletions.
27 changes: 12 additions & 15 deletions drivers/s390/net/qeth_core_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4540,16 +4540,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
{
struct qeth_ipa_cmd *cmd;
struct qeth_arp_query_info *qinfo;
struct qeth_snmp_cmd *snmp;
unsigned char *data;
void *snmp_data;
__u16 data_len;

QETH_CARD_TEXT(card, 3, "snpcmdcb");

cmd = (struct qeth_ipa_cmd *) sdata;
data = (unsigned char *)((char *)cmd - reply->offset);
qinfo = (struct qeth_arp_query_info *) reply->param;
snmp = &cmd->data.setadapterparms.data.snmp;

if (cmd->hdr.return_code) {
QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code);
Expand All @@ -4562,10 +4561,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
return 0;
}
data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data));
if (cmd->data.setadapterparms.hdr.seq_no == 1)
data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
else
data_len -= (__u16)((char *)&snmp->request - (char *)cmd);
if (cmd->data.setadapterparms.hdr.seq_no == 1) {
snmp_data = &cmd->data.setadapterparms.data.snmp;
data_len -= offsetof(struct qeth_ipa_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 */
if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
Expand All @@ -4578,16 +4582,9 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
QETH_CARD_TEXT_(card, 4, "sseqn%i",
cmd->data.setadapterparms.hdr.seq_no);
/*copy entries to user buffer*/
if (cmd->data.setadapterparms.hdr.seq_no == 1) {
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);
}
memcpy(qinfo->udata + qinfo->udata_offset, snmp_data, data_len);
qinfo->udata_offset += data_len;

/* check if all replies received ... */
QETH_CARD_TEXT_(card, 4, "srtot%i",
cmd->data.setadapterparms.hdr.used_total);
Expand Down

0 comments on commit 1d3891c

Please sign in to comment.