diff options
Diffstat (limited to 'drivers/net/hyperv')
-rw-r--r-- | drivers/net/hyperv/hyperv_net.h | 1 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc.c | 25 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 6 | ||||
-rw-r--r-- | drivers/net/hyperv/rndis_filter.c | 20 |
4 files changed, 36 insertions, 16 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 32861036c3fc..960f06141472 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -793,6 +793,7 @@ struct netvsc_device { /* Receive buffer allocated by us but manages by NetVSP */ void *recv_buf; + u32 recv_buf_size; /* allocated bytes */ u32 recv_buf_gpadl_handle; u32 recv_section_cnt; u32 recv_section_size; diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 4123d081b1c7..c9910c33e671 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -282,6 +282,8 @@ static int netvsc_init_buf(struct hv_device *device, goto cleanup; } + net_device->recv_buf_size = buf_size; + /* * Establish the gpadl handle for this buffer on this * channel. Note: This call uses the vmbus connection rather @@ -1095,15 +1097,30 @@ static int netvsc_receive(struct net_device *ndev, /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */ for (i = 0; i < count; i++) { - void *data = recv_buf - + vmxferpage_packet->ranges[i].byte_offset; + u32 offset = vmxferpage_packet->ranges[i].byte_offset; u32 buflen = vmxferpage_packet->ranges[i].byte_count; + void *data; + int ret; + + if (unlikely(offset + buflen > net_device->recv_buf_size)) { + status = NVSP_STAT_FAIL; + netif_err(net_device_ctx, rx_err, ndev, + "Packet offset:%u + len:%u too big\n", + offset, buflen); + + continue; + } + + data = recv_buf + offset; trace_rndis_recv(ndev, q_idx, data); /* Pass it to the upper layer */ - status = rndis_filter_receive(ndev, net_device, - channel, data, buflen); + ret = rndis_filter_receive(ndev, net_device, + channel, data, buflen); + + if (unlikely(ret != NVSP_STAT_SUCCESS)) + status = NVSP_STAT_FAIL; } enq_receive_complete(ndev, net_device, q_idx, diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index f28c85d212ce..ecc84954c511 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -55,7 +55,7 @@ #define VF_TAKEOVER_INT (HZ / 10) static unsigned int ring_size __ro_after_init = 128; -module_param(ring_size, uint, S_IRUGO); +module_param(ring_size, uint, 0444); MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); unsigned int netvsc_ring_bytes __ro_after_init; struct reciprocal_value netvsc_ring_reciprocal __ro_after_init; @@ -66,7 +66,7 @@ static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_TX_ERR; static int debug = -1; -module_param(debug, int, S_IRUGO); +module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); static void netvsc_change_rx_flags(struct net_device *net, int change) @@ -831,7 +831,7 @@ int netvsc_recv_callback(struct net_device *net, u64_stats_update_end(&rx_stats->syncp); napi_gro_receive(&nvchan->napi, skb); - return 0; + return NVSP_STAT_SUCCESS; } static void netvsc_get_drvinfo(struct net_device *net, diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 020f8bc54386..e2b68d9328a7 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -365,14 +365,15 @@ static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type) static int rndis_filter_receive_data(struct net_device *ndev, struct netvsc_device *nvdev, - struct rndis_message *msg, struct vmbus_channel *channel, - void *data, u32 data_buflen) + struct rndis_message *msg, + u32 data_buflen) { struct rndis_packet *rndis_pkt = &msg->msg.pkt; const struct ndis_tcp_ip_checksum_info *csum_info; const struct ndis_pkt_8021q_info *vlan; u32 data_offset; + void *data; /* Remove the rndis header and pass it back up the stack */ data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset; @@ -393,14 +394,15 @@ static int rndis_filter_receive_data(struct net_device *ndev, vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO); + csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO); + + data = (void *)msg + data_offset; + /* * Remove the rndis trailer padding from rndis packet message * rndis_pkt->data_len tell us the real data length, we only copy * the data packet to the stack, without the rndis trailer padding */ - data = (void *)((unsigned long)data + data_offset); - csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO); - return netvsc_recv_callback(ndev, nvdev, channel, data, rndis_pkt->data_len, csum_info, vlan); @@ -419,8 +421,8 @@ int rndis_filter_receive(struct net_device *ndev, switch (rndis_msg->ndis_msg_type) { case RNDIS_MSG_PACKET: - return rndis_filter_receive_data(ndev, net_dev, rndis_msg, - channel, data, buflen); + return rndis_filter_receive_data(ndev, net_dev, channel, + rndis_msg, buflen); case RNDIS_MSG_INIT_C: case RNDIS_MSG_QUERY_C: case RNDIS_MSG_SET_C: @@ -437,10 +439,10 @@ int rndis_filter_receive(struct net_device *ndev, "unhandled rndis message (type %u len %u)\n", rndis_msg->ndis_msg_type, rndis_msg->msg_len); - break; + return NVSP_STAT_FAIL; } - return 0; + return NVSP_STAT_SUCCESS; } static int rndis_filter_query_device(struct rndis_device *dev, |