linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4 v2] rndis_wlan: copy only useful data from rndis_command respond
@ 2010-03-04 16:27 Jussi Kivilinna
  2010-03-04 16:27 ` [PATCH 2/4] rndis_wlan: remove unused variables from priv structure Jussi Kivilinna
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jussi Kivilinna @ 2010-03-04 16:27 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless

rndis_query_oid() uses full output buffer size to copy response buffer
from rndis_command()/device. This doesn't cause problems as response buffer
is sized based on output buffer but does copy extra unset bytes.
So change rndis_query_oid() so that only meaningful bytes are being copied.

Also in case of malfunctioning device/cable/etc returned data offset from
device might be wrong so bound check memory access correctly, so add
checks for this.

v2: fixed to use new netdev_dbg/warn/etc instead of old devdbg/warn/etc

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |   33 +++++++++++++++++++++++++++++----
 1 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 9f6d6bf..a4f70de 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)
 		struct rndis_query_c	*get_c;
 	} u;
 	int ret, buflen;
+	int resplen, respoffs, copylen;
 
 	buflen = *len + sizeof(*u.get);
 	if (buflen < CONTROL_BUFFER_SIZE)
@@ -733,11 +734,34 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
 			   le32_to_cpu(u.get_c->status));
 
 	if (ret == 0) {
-		memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
+		resplen = le32_to_cpu(u.get_c->len);
+		respoffs = le32_to_cpu(u.get_c->offset) + 8;
 
-		ret = le32_to_cpu(u.get_c->len);
-		if (ret > *len)
-			*len = ret;
+		if (respoffs > buflen) {
+			/* Device returned data offset outside buffer, error. */
+			netdev_dbg(dev->net, "%s(%s): received invalid "
+				"data offset: %d > %d\n", __func__,
+				oid_to_string(oid), respoffs, buflen);
+
+			ret = -EINVAL;
+			goto exit_unlock;
+		}
+
+		if ((resplen + respoffs) > buflen) {
+			/* Device would have returned more data if buffer would
+			 * have been big enough. Copy just the bits that we got.
+			 */
+			copylen = buflen - respoffs;
+		} else {
+			copylen = resplen;
+		}
+
+		if (copylen > *len)
+			copylen = *len;
+
+		memcpy(data, u.buf + respoffs, copylen);
+
+		*len = resplen;
 
 		ret = rndis_error_status(u.get_c->status);
 		if (ret < 0)
@@ -746,6 +770,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
 				   le32_to_cpu(u.get_c->status), ret);
 	}
 
+exit_unlock:
 	mutex_unlock(&priv->command_lock);
 
 	if (u.buf != priv->command_buffer)


^ permalink raw reply related	[flat|nested] 5+ messages in thread
* [PATCH 1/4] rndis_wlan: copy only useful data from rndis_command respond
@ 2010-03-02 22:38 Jussi Kivilinna
  2010-03-02 22:38 ` [PATCH 2/4] rndis_wlan: remove unused variables from priv structure Jussi Kivilinna
  0 siblings, 1 reply; 5+ messages in thread
From: Jussi Kivilinna @ 2010-03-02 22:38 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless

rndis_query_oid() uses full output buffer size to copy response buffer
from rndis_command()/device. This doesn't cause problems as response buffer
is sized based on output buffer but does copy extra unset bytes.
So change rndis_query_oid() so that only meaningful bytes are being copied.

Also in case of malfunctioning device/cable/etc returned data offset from
device might be wrong so bound check memory access correctly, so add
checks for this.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 drivers/net/wireless/rndis_wlan.c |   33 +++++++++++++++++++++++++++++----
 1 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 305c106..b275713 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)
 		struct rndis_query_c	*get_c;
 	} u;
 	int ret, buflen;
+	int resplen, respoffs, copylen;
 
 	buflen = *len + sizeof(*u.get);
 	if (buflen < CONTROL_BUFFER_SIZE)
@@ -733,11 +734,34 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
 			le32_to_cpu(u.get_c->status));
 
 	if (ret == 0) {
-		memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
+		resplen = le32_to_cpu(u.get_c->len);
+		respoffs = le32_to_cpu(u.get_c->offset) + 8;
 
-		ret = le32_to_cpu(u.get_c->len);
-		if (ret > *len)
-			*len = ret;
+		if (respoffs > buflen) {
+			/* Device returned data offset outside buffer, error. */
+			devdbg(dev, "rndis_query_oid(%s): received invalid "
+				"data offset: %d > %d", oid_to_string(oid),
+				respoffs, buflen);
+
+			ret = -EINVAL;
+			goto exit_unlock;
+		}
+
+		if ((resplen + respoffs) > buflen) {
+			/* Device would have returned more data if buffer would
+			 * have been big enough. Copy just the bits that we got.
+			 */
+			copylen = buflen - respoffs;
+		} else {
+			copylen = resplen;
+		}
+
+		if (copylen > *len)
+			copylen = *len;
+
+		memcpy(data, u.buf + respoffs, copylen);
+
+		*len = resplen;
 
 		ret = rndis_error_status(u.get_c->status);
 		if (ret < 0)
@@ -746,6 +770,7 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
 				le32_to_cpu(u.get_c->status), ret);
 	}
 
+exit_unlock:
 	mutex_unlock(&priv->command_lock);
 
 	if (u.buf != priv->command_buffer)


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-03-04 16:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-04 16:27 [PATCH 1/4 v2] rndis_wlan: copy only useful data from rndis_command respond Jussi Kivilinna
2010-03-04 16:27 ` [PATCH 2/4] rndis_wlan: remove unused variables from priv structure Jussi Kivilinna
2010-03-04 16:27 ` [PATCH 3/4 v2] rndis_wlan: get max_num_pmkids from device Jussi Kivilinna
2010-03-04 16:27 ` [PATCH 4/4 v2] rndis_wlan: Implement cfg80211 PMKSA API Jussi Kivilinna
  -- strict thread matches above, loose matches on Subject: below --
2010-03-02 22:38 [PATCH 1/4] rndis_wlan: copy only useful data from rndis_command respond Jussi Kivilinna
2010-03-02 22:38 ` [PATCH 2/4] rndis_wlan: remove unused variables from priv structure Jussi Kivilinna

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).