Skip to content

Commit 1d3891c

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 13a3d89 commit 1d3891c

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
@@ -4540,16 +4540,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
45404540
{
45414541
struct qeth_ipa_cmd *cmd;
45424542
struct qeth_arp_query_info *qinfo;
4543-
struct qeth_snmp_cmd *snmp;
45444543
unsigned char *data;
4544+
void *snmp_data;
45454545
__u16 data_len;
45464546

45474547
QETH_CARD_TEXT(card, 3, "snpcmdcb");
45484548

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

45544553
if (cmd->hdr.return_code) {
45554554
QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code);
@@ -4562,10 +4561,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
45624561
return 0;
45634562
}
45644563
data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data));
4565-
if (cmd->data.setadapterparms.hdr.seq_no == 1)
4566-
data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
4567-
else
4568-
data_len -= (__u16)((char *)&snmp->request - (char *)cmd);
4564+
if (cmd->data.setadapterparms.hdr.seq_no == 1) {
4565+
snmp_data = &cmd->data.setadapterparms.data.snmp;
4566+
data_len -= offsetof(struct qeth_ipa_cmd,
4567+
data.setadapterparms.data.snmp);
4568+
} else {
4569+
snmp_data = &cmd->data.setadapterparms.data.snmp.request;
4570+
data_len -= offsetof(struct qeth_ipa_cmd,
4571+
data.setadapterparms.data.snmp.request);
4572+
}
45694573

45704574
/* check if there is enough room in userspace */
45714575
if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
@@ -4578,16 +4582,9 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
45784582
QETH_CARD_TEXT_(card, 4, "sseqn%i",
45794583
cmd->data.setadapterparms.hdr.seq_no);
45804584
/*copy entries to user buffer*/
4581-
if (cmd->data.setadapterparms.hdr.seq_no == 1) {
4582-
memcpy(qinfo->udata + qinfo->udata_offset,
4583-
(char *)snmp,
4584-
data_len + offsetof(struct qeth_snmp_cmd, data));
4585-
qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
4586-
} else {
4587-
memcpy(qinfo->udata + qinfo->udata_offset,
4588-
(char *)&snmp->request, data_len);
4589-
}
4585+
memcpy(qinfo->udata + qinfo->udata_offset, snmp_data, data_len);
45904586
qinfo->udata_offset += data_len;
4587+
45914588
/* check if all replies received ... */
45924589
QETH_CARD_TEXT_(card, 4, "srtot%i",
45934590
cmd->data.setadapterparms.hdr.used_total);

0 commit comments

Comments
 (0)