From: Haiyang Zhang Date: Mon, 12 Mar 2012 10:20:49 +0000 (+0000) Subject: net/hyperv: Fix data corruption in rndis_filter_receive() X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=ef31bef6216db76950c38f1993b45953402f4c63;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git 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 Reviewed-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- 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, { struct netvsc_device *net_dev = hv_get_drvdata(dev); struct rndis_device *rndis_dev; - struct rndis_message rndis_msg; - struct rndis_message *rndis_hdr; + struct rndis_message *rndis_msg; struct net_device *ndev; if (!net_dev) @@ -375,46 +374,32 @@ int rndis_filter_receive(struct hv_device *dev, return -ENODEV; } - rndis_hdr = pkt->data; - - /* Make sure we got a valid rndis message */ - if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) && - (rndis_hdr->msg_len > sizeof(struct rndis_message))) { - netdev_err(ndev, "incoming rndis message buffer overflow " - "detected (got %u, max %zu)..marking it an error!\n", - rndis_hdr->msg_len, - sizeof(struct rndis_message)); - } + rndis_msg = pkt->data; - memcpy(&rndis_msg, rndis_hdr, - (rndis_hdr->msg_len > sizeof(struct rndis_message)) ? - sizeof(struct rndis_message) : - rndis_hdr->msg_len); + dump_rndis_message(dev, rndis_msg); - dump_rndis_message(dev, &rndis_msg); - - switch (rndis_msg.ndis_msg_type) { + switch (rndis_msg->ndis_msg_type) { case REMOTE_NDIS_PACKET_MSG: /* data msg */ - rndis_filter_receive_data(rndis_dev, &rndis_msg, pkt); + rndis_filter_receive_data(rndis_dev, rndis_msg, pkt); break; case REMOTE_NDIS_INITIALIZE_CMPLT: case REMOTE_NDIS_QUERY_CMPLT: case REMOTE_NDIS_SET_CMPLT: /* completion msgs */ - rndis_filter_receive_response(rndis_dev, &rndis_msg); + rndis_filter_receive_response(rndis_dev, rndis_msg); break; case REMOTE_NDIS_INDICATE_STATUS_MSG: /* notification msgs */ - rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg); + rndis_filter_receive_indicate_status(rndis_dev, rndis_msg); break; default: netdev_err(ndev, "unhandled rndis message (type %u len %u)\n", - rndis_msg.ndis_msg_type, - rndis_msg.msg_len); + rndis_msg->ndis_msg_type, + rndis_msg->msg_len); break; }