Skip to content

Commit eb09c6d

Browse files
julianwiedmanngregkh
authored andcommitted
s390/qeth: fix length check in SNMP processing
[ 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: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Julian Wiedmann <[email protected]> Reviewed-by: Ursula Braun <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4789768 commit eb09c6d

File tree

1 file changed

+12
-15
lines changed

1 file changed

+12
-15
lines changed

drivers/s390/net/qeth_core_main.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4545,16 +4545,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
45454545
{
45464546
struct qeth_ipa_cmd *cmd;
45474547
struct qeth_arp_query_info *qinfo;
4548-
struct qeth_snmp_cmd *snmp;
45494548
unsigned char *data;
4549+
void *snmp_data;
45504550
__u16 data_len;
45514551

45524552
QETH_CARD_TEXT(card, 3, "snpcmdcb");
45534553

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

45594558
if (cmd->hdr.return_code) {
45604559
QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code);
@@ -4567,10 +4566,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
45674566
return 0;
45684567
}
45694568
data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data));
4570-
if (cmd->data.setadapterparms.hdr.seq_no == 1)
4571-
data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
4572-
else
4573-
data_len -= (__u16)((char *)&snmp->request - (char *)cmd);
4569+
if (cmd->data.setadapterparms.hdr.seq_no == 1) {
4570+
snmp_data = &cmd->data.setadapterparms.data.snmp;
4571+
data_len -= offsetof(struct qeth_ipa_cmd,
4572+
data.setadapterparms.data.snmp);
4573+
} else {
4574+
snmp_data = &cmd->data.setadapterparms.data.snmp.request;
4575+
data_len -= offsetof(struct qeth_ipa_cmd,
4576+
data.setadapterparms.data.snmp.request);
4577+
}
45744578

45754579
/* check if there is enough room in userspace */
45764580
if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
@@ -4583,16 +4587,9 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
45834587
QETH_CARD_TEXT_(card, 4, "sseqn%i",
45844588
cmd->data.setadapterparms.hdr.seq_no);
45854589
/*copy entries to user buffer*/
4586-
if (cmd->data.setadapterparms.hdr.seq_no == 1) {
4587-
memcpy(qinfo->udata + qinfo->udata_offset,
4588-
(char *)snmp,
4589-
data_len + offsetof(struct qeth_snmp_cmd, data));
4590-
qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
4591-
} else {
4592-
memcpy(qinfo->udata + qinfo->udata_offset,
4593-
(char *)&snmp->request, data_len);
4594-
}
4590+
memcpy(qinfo->udata + qinfo->udata_offset, snmp_data, data_len);
45954591
qinfo->udata_offset += data_len;
4592+
45964593
/* check if all replies received ... */
45974594
QETH_CARD_TEXT_(card, 4, "srtot%i",
45984595
cmd->data.setadapterparms.hdr.used_total);

0 commit comments

Comments
 (0)