Message ID | 61b6c5ad26d52b583c535705f04b1bd3953e0de2.1543855384.git.joseph.salisbury@canonical.com |
---|---|
State | New |
Headers | show |
Series | s390/qeth: fix length check in SNMP processing | expand |
On 12/14/18 5:48 PM, Joseph Salisbury wrote: > From: Julian Wiedmann <jwi@linux.ibm.com> > > BugLink: https://bugs.launchpad.net/bugs/1805802 > > 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 <jwi@linux.ibm.com> > Reviewed-by: Ursula Braun <ubraun@linux.ibm.com> > Signed-off-by: David S. Miller <davem@davemloft.net> > (cherry picked from commit 9a764c1e59684c0358e16ccaafd870629f2cfe67) > Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com> Clean cherry-pick, limited to s390x: Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > --- > drivers/s390/net/qeth_core_main.c | 27 ++++++++++++--------------- > 1 file changed, 12 insertions(+), 15 deletions(-) > > diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c > index b828345..b043620 100644 > --- a/drivers/s390/net/qeth_core_main.c > +++ b/drivers/s390/net/qeth_core_main.c > @@ -4513,8 +4513,8 @@ 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"); > @@ -4522,7 +4522,6 @@ static int qeth_snmp_command_cb(struct qeth_card *card, > 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); > @@ -4535,10 +4534,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) { > @@ -4551,16 +4555,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);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index b828345..b043620 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -4513,8 +4513,8 @@ 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"); @@ -4522,7 +4522,6 @@ static int qeth_snmp_command_cb(struct qeth_card *card, 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); @@ -4535,10 +4534,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) { @@ -4551,16 +4555,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);