mirror of
https://github.com/torvalds/linux.git
synced 2024-12-23 11:21:33 +00:00
rndis_wlan: copy only useful data from rndis_command respond
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> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
eae44756d6
commit
80f8c5b434
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user