Module: xenomai-3
Branch: next
Commit: 8321553d5c0143eca979b99b3148ecdc67d24166
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=8321553d5c0143eca979b99b3148ecdc67d24166

Author: Philippe Gerum <r...@xenomai.org>
Date:   Wed Dec  6 12:45:31 2017 +0100

net/udp: recvmsg: remove direct references to user memory

---

 kernel/drivers/net/stack/ipv4/udp/udp.c |   95 +++++++++++++++++++++----------
 1 file changed, 65 insertions(+), 30 deletions(-)

diff --git a/kernel/drivers/net/stack/ipv4/udp/udp.c 
b/kernel/drivers/net/stack/ipv4/udp/udp.c
index f8eeadd..8284ff7 100644
--- a/kernel/drivers/net/stack/ipv4/udp/udp.c
+++ b/kernel/drivers/net/stack/ipv4/udp/udp.c
@@ -377,20 +377,39 @@ int rt_udp_ioctl(struct rtdm_fd *fd, unsigned int 
request, void __user *arg)
 /***
  *  rt_udp_recvmsg
  */
+/***
+ *  rt_udp_recvmsg
+ */
 ssize_t rt_udp_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);
+    size_t              len;
     struct rtskb        *skb;
     struct rtskb        *first_skb;
     size_t              copied = 0;
     size_t              block_size;
     size_t              data_len;
     struct udphdr       *uh;
-    struct sockaddr_in  *sin;
+    struct sockaddr_in  sin;
     nanosecs_rel_t      timeout = sock->timeout;
-    int                 ret;
+    int                 ret, flags;
+    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)
@@ -398,35 +417,44 @@ ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct 
user_msghdr *msg, int msg_flag
 
     ret = rtdm_sem_timeddown(&sock->pending_sem, timeout, NULL);
     if (unlikely(ret < 0))
-        switch (ret) {
-            case -EWOULDBLOCK:
-            case -ETIMEDOUT:
-            case -EINTR:
-                return ret;
-
-            default:
-                return -EBADF;   /* socket has been closed */
-        }
+       switch (ret) {
+           default:
+               ret = -EBADF;   /* socket has been closed */
+           case -EWOULDBLOCK:
+           case -ETIMEDOUT:
+           case -EINTR:
+               rtdm_drop_iovec(iov, iov_fast);
+               return ret;
+       }
 
     skb = rtskb_dequeue_chain(&sock->incoming);
     RTNET_ASSERT(skb != NULL, return -EFAULT;);
-
     uh = skb->h.uh;
-    data_len = ntohs(uh->len) - sizeof(struct udphdr);
-    sin = msg->msg_name;
+    first_skb = skb;
 
+    namelen = sizeof(sin);
+    ret = rtnet_put_arg(fd, &msg->msg_namelen, &namelen, sizeof(namelen));
+    if (ret)
+           goto fail;
+   
     /* copy the address */
-    msg->msg_namelen = sizeof(*sin);
-    if (sin) {
-        sin->sin_family      = AF_INET;
-        sin->sin_port        = uh->source;
-        sin->sin_addr.s_addr = skb->nh.iph->saddr;
+    if (msg->msg_name) {
+           memset(&sin, 0, sizeof(sin));
+           sin.sin_family      = AF_INET;
+           sin.sin_port        = uh->source;
+           sin.sin_addr.s_addr = skb->nh.iph->saddr;
+           ret = rtnet_put_arg(fd, &msg->msg_name, &sin, sizeof(sin));
+           if (ret)
+                   goto fail;
     }
 
+    data_len = ntohs(uh->len) - sizeof(struct udphdr);
+
     /* remove the UDP header */
     __rtskb_pull(skb, sizeof(struct udphdr));
 
-    first_skb = skb;
+    flags = msg->msg_flags & ~MSG_TRUNC;
+    len = rt_iovec_len(iov, msg->msg_iovlen);
 
     /* iterate over all IP fragments */
     do {
@@ -440,25 +468,28 @@ ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct 
user_msghdr *msg, int msg_flag
         if (copied > len) {
             block_size -= copied - len;
             copied = len;
-            msg->msg_flags |= MSG_TRUNC;
-
-            /* copy the data */
-            rt_memcpy_tokerneliovec(msg->msg_iov, skb->data, block_size);
-
-            break;
+           flags |= MSG_TRUNC;
         }
 
         /* copy the data */
-        rt_memcpy_tokerneliovec(msg->msg_iov, skb->data, block_size);
+       ret = rtnet_write_to_iov(fd, iov, msg->msg_iovlen, skb->data, 
block_size);
+       if (ret)
+               goto fail;
 
         /* next fragment */
         skb = skb->next;
-    } while (skb != NULL);
+    } while (skb && !(flags & MSG_TRUNC));
 
     /* did we copied all bytes? */
     if (data_len > 0)
-        msg->msg_flags |= MSG_TRUNC;
+           flags |= MSG_TRUNC;
 
+    if (flags != msg->msg_flags) {
+           ret = rtnet_put_arg(fd, &msg->msg_flags, &flags, sizeof(flags));
+           if (ret)
+                   goto fail;
+    }
+out:
     if ((msg_flags & MSG_PEEK) == 0)
         kfree_rtskb(first_skb);
     else {
@@ -466,8 +497,12 @@ ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct 
user_msghdr *msg, int msg_flag
         rtskb_queue_head(&sock->incoming, first_skb);
         rtdm_sem_up(&sock->pending_sem);
     }
+    rtdm_drop_iovec(iov, iov_fast);
 
     return copied;
+fail:
+    copied = ret;
+    goto out;
 }
 
 


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
https://xenomai.org/mailman/listinfo/xenomai-git

Reply via email to