aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r--drivers/net/wireless/rndis_wlan.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 9f6d6bf06b8e..a4f70de99cdd 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -704,6 +704,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
704 struct rndis_query_c *get_c; 704 struct rndis_query_c *get_c;
705 } u; 705 } u;
706 int ret, buflen; 706 int ret, buflen;
707 int resplen, respoffs, copylen;
707 708
708 buflen = *len + sizeof(*u.get); 709 buflen = *len + sizeof(*u.get);
709 if (buflen < CONTROL_BUFFER_SIZE) 710 if (buflen < CONTROL_BUFFER_SIZE)
@@ -733,11 +734,34 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
733 le32_to_cpu(u.get_c->status)); 734 le32_to_cpu(u.get_c->status));
734 735
735 if (ret == 0) { 736 if (ret == 0) {
736 memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); 737 resplen = le32_to_cpu(u.get_c->len);
738 respoffs = le32_to_cpu(u.get_c->offset) + 8;
737 739
738 ret = le32_to_cpu(u.get_c->len); 740 if (respoffs > buflen) {
739 if (ret > *len) 741 /* Device returned data offset outside buffer, error. */
740 *len = ret; 742 netdev_dbg(dev->net, "%s(%s): received invalid "
743 "data offset: %d > %d\n", __func__,
744 oid_to_string(oid), respoffs, buflen);
745
746 ret = -EINVAL;
747 goto exit_unlock;
748 }
749
750 if ((resplen + respoffs) > buflen) {
751 /* Device would have returned more data if buffer would
752 * have been big enough. Copy just the bits that we got.
753 */
754 copylen = buflen - respoffs;
755 } else {
756 copylen = resplen;
757 }
758
759 if (copylen > *len)
760 copylen = *len;
761
762 memcpy(data, u.buf + respoffs, copylen);
763
764 *len = resplen;
741 765
742 ret = rndis_error_status(u.get_c->status); 766 ret = rndis_error_status(u.get_c->status);
743 if (ret < 0) 767 if (ret < 0)
@@ -746,6 +770,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
746 le32_to_cpu(u.get_c->status), ret); 770 le32_to_cpu(u.get_c->status), ret);
747 } 771 }
748 772
773exit_unlock:
749 mutex_unlock(&priv->command_lock); 774 mutex_unlock(&priv->command_lock);
750 775
751 if (u.buf != priv->command_buffer) 776 if (u.buf != priv->command_buffer)