| 5605 | |
| 5606 | #ifdef ARCH_MM_MMU |
| 5607 | static int copy_msghdr_from_user(struct msghdr *kmsg, struct msghdr *umsg, |
| 5608 | struct iovec **out_iov, void **out_msg_control) |
| 5609 | { |
| 5610 | size_t iovs_size; |
| 5611 | struct iovec *uiov, *kiov; |
| 5612 | size_t iovs_buffer_size = 0; |
| 5613 | void *iovs_buffer; |
| 5614 | |
| 5615 | if (!lwp_user_accessable(umsg, sizeof(*umsg))) |
| 5616 | { |
| 5617 | return -EFAULT; |
| 5618 | } |
| 5619 | |
| 5620 | lwp_get_from_user(kmsg, umsg, sizeof(*kmsg)); |
| 5621 | |
| 5622 | iovs_size = sizeof(*kmsg->msg_iov) * kmsg->msg_iovlen; |
| 5623 | if (!lwp_user_accessable(kmsg->msg_iov, iovs_size)) |
| 5624 | { |
| 5625 | return -EFAULT; |
| 5626 | } |
| 5627 | |
| 5628 | /* user and kernel */ |
| 5629 | kiov = kmem_get(iovs_size * 2); |
| 5630 | if (!kiov) |
| 5631 | { |
| 5632 | return -ENOMEM; |
| 5633 | } |
| 5634 | |
| 5635 | uiov = (void *)kiov + iovs_size; |
| 5636 | lwp_get_from_user(uiov, kmsg->msg_iov, iovs_size); |
| 5637 | |
| 5638 | if (out_iov) |
| 5639 | { |
| 5640 | *out_iov = uiov; |
| 5641 | } |
| 5642 | kmsg->msg_iov = kiov; |
| 5643 | |
| 5644 | for (int i = 0; i < kmsg->msg_iovlen; ++i) |
| 5645 | { |
| 5646 | /* |
| 5647 | * We MUST check we can copy data to user after socket done in uiov |
| 5648 | * otherwise we will be lost the messages from the network! |
| 5649 | */ |
| 5650 | if (!lwp_user_accessable(uiov->iov_base, uiov->iov_len)) |
| 5651 | { |
| 5652 | kmem_put(kmsg->msg_iov); |
| 5653 | |
| 5654 | return -EPERM; |
| 5655 | } |
| 5656 | |
| 5657 | iovs_buffer_size += uiov->iov_len; |
| 5658 | kiov->iov_len = uiov->iov_len; |
| 5659 | |
| 5660 | ++kiov; |
| 5661 | ++uiov; |
| 5662 | } |
| 5663 | |
| 5664 | /* msg_iov and msg_control */ |
no test coverage detected