struct sk_buff *skb;
                unsigned out, in;
                size_t nbytes;
+               u32 offset;
                int head;
 
                skb = virtio_vsock_skb_dequeue(&vsock->send_pkt_queue);
                }
 
                iov_iter_init(&iov_iter, ITER_DEST, &vq->iov[out], in, iov_len);
-               payload_len = skb->len;
+               offset = VIRTIO_VSOCK_SKB_CB(skb)->offset;
+               payload_len = skb->len - offset;
                hdr = virtio_vsock_hdr(skb);
 
                /* If the packet is greater than the space available in the
                        break;
                }
 
-               nbytes = copy_to_iter(skb->data, payload_len, &iov_iter);
-               if (nbytes != payload_len) {
+               if (skb_copy_datagram_iter(skb,
+                                          offset,
+                                          &iov_iter,
+                                          payload_len)) {
                        kfree_skb(skb);
                        vq_err(vq, "Faulted on copying pkt buf\n");
                        break;
                vhost_add_used(vq, head, sizeof(*hdr) + payload_len);
                added = true;
 
-               skb_pull(skb, payload_len);
+               VIRTIO_VSOCK_SKB_CB(skb)->offset += payload_len;
                total_len += payload_len;
 
                /* If we didn't send all the payload we can requeue the packet
                 * to send it with the next available buffer.
                 */
-               if (skb->len > 0) {
+               if (VIRTIO_VSOCK_SKB_CB(skb)->offset < skb->len) {
                        hdr->flags |= cpu_to_le32(flags_to_restore);
 
                        /* We are queueing the same skb to handle
 
                spin_unlock_bh(&vvs->rx_lock);
 
                /* sk_lock is held by caller so no one else can dequeue.
-                * Unlock rx_lock since memcpy_to_msg() may sleep.
+                * Unlock rx_lock since skb_copy_datagram_iter() may sleep.
                 */
-               err = memcpy_to_msg(msg, skb->data, bytes);
+               err = skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
+                                            &msg->msg_iter, bytes);
                if (err)
                        goto out;
 
        while (total < len && !skb_queue_empty(&vvs->rx_queue)) {
                skb = skb_peek(&vvs->rx_queue);
 
-               bytes = len - total;
-               if (bytes > skb->len)
-                       bytes = skb->len;
+               bytes = min_t(size_t, len - total,
+                             skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset);
 
                /* sk_lock is held by caller so no one else can dequeue.
-                * Unlock rx_lock since memcpy_to_msg() may sleep.
+                * Unlock rx_lock since skb_copy_datagram_iter() may sleep.
                 */
                spin_unlock_bh(&vvs->rx_lock);
 
-               err = memcpy_to_msg(msg, skb->data, bytes);
+               err = skb_copy_datagram_iter(skb,
+                                            VIRTIO_VSOCK_SKB_CB(skb)->offset,
+                                            &msg->msg_iter, bytes);
                if (err)
                        goto out;
 
                spin_lock_bh(&vvs->rx_lock);
 
                total += bytes;
-               skb_pull(skb, bytes);
 
-               if (skb->len == 0) {
+               VIRTIO_VSOCK_SKB_CB(skb)->offset += bytes;
+
+               if (skb->len == VIRTIO_VSOCK_SKB_CB(skb)->offset) {
                        u32 pkt_len = le32_to_cpu(virtio_vsock_hdr(skb)->len);
 
                        virtio_transport_dec_rx_pkt(vvs, pkt_len);
                        spin_unlock_bh(&vvs->rx_lock);
 
                        /* sk_lock is held by caller so no one else can dequeue.
-                        * Unlock rx_lock since memcpy_to_msg() may sleep.
+                        * Unlock rx_lock since skb_copy_datagram_iter() may sleep.
                         */
-                       err = memcpy_to_msg(msg, skb->data, bytes);
+                       err = skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
+                                                    &msg->msg_iter, bytes);
                        if (err)
                                return err;
 
                                int err;
 
                                /* sk_lock is held by caller so no one else can dequeue.
-                                * Unlock rx_lock since memcpy_to_msg() may sleep.
+                                * Unlock rx_lock since skb_copy_datagram_iter() may sleep.
                                 */
                                spin_unlock_bh(&vvs->rx_lock);
 
-                               err = memcpy_to_msg(msg, skb->data, bytes_to_copy);
+                               err = skb_copy_datagram_iter(skb, 0,
+                                                            &msg->msg_iter,
+                                                            bytes_to_copy);
                                if (err) {
                                        /* Copy of message failed. Rest of
                                         * fragments will be freed without copy.