diff options
author | Haiyang Zhang <haiyangz@microsoft.com> | 2012-03-12 06:20:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-03-12 20:06:48 -0400 |
commit | ef31bef6216db76950c38f1993b45953402f4c63 (patch) | |
tree | 044be8b3a0a0f4cd365dbf107576a176bdeb0e0b /drivers | |
parent | afd465030acb4098abcb6b965a5aebc7ea2209e0 (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')
-rw-r--r-- | drivers/net/hyperv/rndis_filter.c | 33 |
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 | ||