Module: xenomai-3 Branch: wip/rtnet-fixes Commit: dc5068a27cdd649e0bed4e5fc2ea5bee4f050957 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=dc5068a27cdd649e0bed4e5fc2ea5bee4f050957
Author: Philippe Gerum <r...@xenomai.org> Date: Tue Dec 5 10:31:32 2017 +0100 net/packet: recvmsg: remove direct references to user memory --- kernel/drivers/net/stack/packet/af_packet.c | 84 +++++++++++++++++++-------- 1 file changed, 59 insertions(+), 25 deletions(-) diff --git a/kernel/drivers/net/stack/packet/af_packet.c b/kernel/drivers/net/stack/packet/af_packet.c index f6638a7..ff3ef33 100644 --- a/kernel/drivers/net/stack/packet/af_packet.c +++ b/kernel/drivers/net/stack/packet/af_packet.c @@ -292,14 +292,29 @@ static ssize_t rt_packet_recvmsg(struct rtdm_fd *fd, struct user_msghdr *msg, int msg_flags) { struct rtsocket *sock = rtdm_fd_to_private(fd); - size_t len = rt_iovec_len(msg->msg_iov, msg->msg_iovlen); + ssize_t len; size_t copy_len; - size_t real_len; struct rtskb *rtskb; - struct sockaddr_ll *sll; - int ret; + struct sockaddr_ll sll; + int ret, flags; nanosecs_rel_t timeout = sock->timeout; + struct user_msghdr _msg; + socklen_t namelen; + struct iovec iov_fast[RTDM_IOV_FASTMAX], *iov; + + msg = rtnet_get_arg(fd, &_msg, msg, sizeof(*msg)); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + if (msg->msg_iovlen < 0) + return -EINVAL; + if (msg->msg_iovlen == 0) + return 0; + + ret = rtdm_get_iovec(fd, &iov, msg, iov_fast); + if (ret) + return ret; /* non-blocking receive? */ if (msg_flags & MSG_DONTWAIT) @@ -308,50 +323,64 @@ rt_packet_recvmsg(struct rtdm_fd *fd, struct user_msghdr *msg, int msg_flags) ret = rtdm_sem_timeddown(&sock->pending_sem, timeout, NULL); if (unlikely(ret < 0)) switch (ret) { + default: + ret = -EBADF; /* socket has been closed */ case -EWOULDBLOCK: case -ETIMEDOUT: case -EINTR: + rtdm_drop_iovec(iov, iov_fast); return ret; - - default: - return -EBADF; /* socket has been closed */ } rtskb = rtskb_dequeue_chain(&sock->incoming); RTNET_ASSERT(rtskb != NULL, return -EFAULT;); - sll = msg->msg_name; - /* copy the address */ - msg->msg_namelen = sizeof(*sll); - if (sll != NULL) { - struct rtnet_device *rtdev = rtskb->rtdev; + namelen = sizeof(sll); + ret = rtnet_put_arg(fd, &msg->msg_namelen, &namelen, sizeof(namelen)); + if (ret) + goto fail; - sll->sll_family = AF_PACKET; - sll->sll_hatype = rtdev->type; - sll->sll_protocol = rtskb->protocol; - sll->sll_pkttype = rtskb->pkt_type; - sll->sll_ifindex = rtdev->ifindex; + /* copy the address if required. */ + if (msg->msg_name) { + struct rtnet_device *rtdev = rtskb->rtdev; + memset(&sll, 0, sizeof(sll)); + sll.sll_family = AF_PACKET; + sll.sll_hatype = rtdev->type; + sll.sll_protocol = rtskb->protocol; + sll.sll_pkttype = rtskb->pkt_type; + sll.sll_ifindex = rtdev->ifindex; /* Ethernet specific - we rather need some parse handler here */ - memcpy(sll->sll_addr, rtskb->mac.ethernet->h_source, ETH_ALEN); - sll->sll_halen = ETH_ALEN; + memcpy(sll.sll_addr, rtskb->mac.ethernet->h_source, ETH_ALEN); + sll.sll_halen = ETH_ALEN; + ret = rtnet_put_arg(fd, &msg->msg_name, &sll, sizeof(sll)); + if (ret) + goto fail; } /* Include the header in raw delivery */ if (rtdm_fd_to_context(fd)->device->driver->socket_type != SOCK_DGRAM) rtskb_push(rtskb, rtskb->data - rtskb->mac.raw); - copy_len = real_len = rtskb->len; - /* The data must not be longer than the available buffer size */ + copy_len = rtskb->len; + len = rt_iovec_len(iov, msg->msg_iovlen); + if (len < 0) { + copy_len = len; + goto out; + } + if (copy_len > len) { copy_len = len; - msg->msg_flags |= MSG_TRUNC; + flags = msg->msg_flags | MSG_TRUNC; + ret = rtnet_put_arg(fd, &msg->msg_flags, &flags, sizeof(flags)); + if (ret) + goto fail; } - rt_memcpy_tokerneliovec(msg->msg_iov, rtskb->data, copy_len); - + copy_len = rtnet_write_to_iov(fd, iov, msg->msg_iovlen, rtskb->data, copy_len); +out: if ((msg_flags & MSG_PEEK) == 0) { kfree_rtskb(rtskb); } else { @@ -359,7 +388,12 @@ rt_packet_recvmsg(struct rtdm_fd *fd, struct user_msghdr *msg, int msg_flags) rtdm_sem_up(&sock->pending_sem); } - return real_len; + rtdm_drop_iovec(iov, iov_fast); + + return copy_len; +fail: + copy_len = ret; + goto out; } _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org https://xenomai.org/mailman/listinfo/xenomai-git