aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv
diff options
context:
space:
mode:
authorHaiyang Zhang <haiyangz@microsoft.com>2012-03-12 06:20:49 -0400
committerDavid S. Miller <davem@davemloft.net>2012-03-12 20:06:48 -0400
commitef31bef6216db76950c38f1993b45953402f4c63 (patch)
tree044be8b3a0a0f4cd365dbf107576a176bdeb0e0b /drivers/net/hyperv
parentafd465030acb4098abcb6b965a5aebc7ea2209e0 (diff)
net/hyperv: Fix data corruption in rndis_filter_receive()
Limiting the memcpy to be the sizeof(struct rndis_message) can truncate the message if there are Per-Packet-Info or Out-of-Band data. In my earlier patch (commit 45326342), the unnecessary kmap_atomic and kunmap_atomic surrounding this memcpy have been removed because the memory in the receive buffer is always mapped. This memcpy is not necessary either. To fix the bug, I removed the memcpy. Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> Reviewed-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/hyperv')
-rw-r--r--drivers/net/hyperv/rndis_filter.c33
1 files changed, 9 insertions, 24 deletions
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 136efd84373f..0c3d7d9f51d3 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -352,8 +352,7 @@ int rndis_filter_receive(struct hv_device *dev,
352{ 352{
353 struct netvsc_device *net_dev = hv_get_drvdata(dev); 353 struct netvsc_device *net_dev = hv_get_drvdata(dev);
354 struct rndis_device *rndis_dev; 354 struct rndis_device *rndis_dev;
355 struct rndis_message rndis_msg; 355 struct rndis_message *rndis_msg;
356 struct rndis_message *rndis_hdr;
357 struct net_device *ndev; 356 struct net_device *ndev;
358 357
359 if (!net_dev) 358 if (!net_dev)
@@ -375,46 +374,32 @@ int rndis_filter_receive(struct hv_device *dev,
375 return -ENODEV; 374 return -ENODEV;
376 } 375 }
377 376
378 rndis_hdr = pkt->data; 377 rndis_msg = pkt->data;
379
380 /* Make sure we got a valid rndis message */
381 if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) &&
382 (rndis_hdr->msg_len > sizeof(struct rndis_message))) {
383 netdev_err(ndev, "incoming rndis message buffer overflow "
384 "detected (got %u, max %zu)..marking it an error!\n",
385 rndis_hdr->msg_len,
386 sizeof(struct rndis_message));
387 }
388 378
389 memcpy(&rndis_msg, rndis_hdr, 379 dump_rndis_message(dev, rndis_msg);
390 (rndis_hdr->msg_len > sizeof(struct rndis_message)) ?
391 sizeof(struct rndis_message) :
392 rndis_hdr->msg_len);
393 380
394 dump_rndis_message(dev, &rndis_msg); 381 switch (rndis_msg->ndis_msg_type) {
395
396 switch (rndis_msg.ndis_msg_type) {
397 case REMOTE_NDIS_PACKET_MSG: 382 case REMOTE_NDIS_PACKET_MSG:
398 /* data msg */ 383 /* data msg */
399 rndis_filter_receive_data(rndis_dev, &rndis_msg, pkt); 384 rndis_filter_receive_data(rndis_dev, rndis_msg, pkt);
400 break; 385 break;
401 386
402 case REMOTE_NDIS_INITIALIZE_CMPLT: 387 case REMOTE_NDIS_INITIALIZE_CMPLT:
403 case REMOTE_NDIS_QUERY_CMPLT: 388 case REMOTE_NDIS_QUERY_CMPLT:
404 case REMOTE_NDIS_SET_CMPLT: 389 case REMOTE_NDIS_SET_CMPLT:
405 /* completion msgs */ 390 /* completion msgs */
406 rndis_filter_receive_response(rndis_dev, &rndis_msg); 391 rndis_filter_receive_response(rndis_dev, rndis_msg);
407 break; 392 break;
408 393
409 case REMOTE_NDIS_INDICATE_STATUS_MSG: 394 case REMOTE_NDIS_INDICATE_STATUS_MSG:
410 /* notification msgs */ 395 /* notification msgs */
411 rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg); 396 rndis_filter_receive_indicate_status(rndis_dev, rndis_msg);
412 break; 397 break;
413 default: 398 default:
414 netdev_err(ndev, 399 netdev_err(ndev,
415 "unhandled rndis message (type %u len %u)\n", 400 "unhandled rndis message (type %u len %u)\n",
416 rndis_msg.ndis_msg_type, 401 rndis_msg->ndis_msg_type,
417 rndis_msg.msg_len); 402 rndis_msg->msg_len);
418 break; 403 break;
419 } 404 }
420 405