[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2018-03-08 Thread git repository hosting
Module: xenomai-3
Branch: stable-3.0.x
Commit: 3e3eea9623f5e172972a9f09b172323d42a6d2dd
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=3e3eea9623f5e172972a9f09b172323d42a6d2dd

Author: Philippe Gerum 
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 |  222 +++
 1 file changed, 138 insertions(+), 84 deletions(-)

diff --git a/kernel/drivers/net/stack/ipv4/udp/udp.c 
b/kernel/drivers/net/stack/ipv4/udp/udp.c
index 6d624e0..903e897 100644
--- a/kernel/drivers/net/stack/ipv4/udp/udp.c
+++ b/kernel/drivers/net/stack/ipv4/udp/udp.c
@@ -154,18 +154,24 @@ static inline struct rtsocket *rt_udp_v4_lookup(u32 
daddr, u16 dport)
  *  @s: socket
  *  @addr:  local address
  */
-int rt_udp_bind(struct rtsocket *sock, const struct sockaddr *addr,
-socklen_t addrlen)
+int rt_udp_bind(struct rtdm_fd *fd, struct rtsocket *sock,
+   const struct sockaddr __user *addr, socklen_t addrlen)
 {
-struct sockaddr_in  *usin = (struct sockaddr_in *)addr;
+struct sockaddr_in  _sin, *sin;
 rtdm_lockctx_t  context;
 int index;
 int err = 0;
 
 
-if ((addrlen < (int)sizeof(struct sockaddr_in)) ||
-((usin->sin_port & auto_port_mask) == auto_port_start))
-return -EINVAL;
+if (addrlen < sizeof(struct sockaddr_in))
+   return -EINVAL;
+
+sin = rtnet_get_arg(fd, &_sin, addr, sizeof(_sin));
+if (IS_ERR(sin))
+   return PTR_ERR(sin);
+
+if ((sin->sin_port & auto_port_mask) == auto_port_start)
+   return -EINVAL;
 
 rtdm_lock_get_irqsave(_socket_base_lock, context);
 
@@ -181,8 +187,8 @@ int rt_udp_bind(struct rtsocket *sock, const struct 
sockaddr *addr,
 
 port_hash_del(_registry[index]);
 if (port_hash_insert(_registry[index],
- usin->sin_addr.s_addr,
- usin->sin_port ?: index + auto_port_start)) {
+ sin->sin_addr.s_addr,
+ sin->sin_port ?: index + auto_port_start)) {
 port_hash_insert(_registry[index],
  port_registry[index].saddr,
  port_registry[index].sport);
@@ -207,51 +213,64 @@ int rt_udp_bind(struct rtsocket *sock, const struct 
sockaddr *addr,
 /***
  *  rt_udp_connect
  */
-int rt_udp_connect(struct rtsocket *sock, const struct sockaddr *serv_addr,
-   socklen_t addrlen)
+int rt_udp_connect(struct rtdm_fd *fd, struct rtsocket *sock,
+  const struct sockaddr __user *serv_addr, socklen_t addrlen)
 {
-struct sockaddr_in  *usin = (struct sockaddr_in *) serv_addr;
-rtdm_lockctx_t  context;
-int index;
-
-
-if (usin->sin_family == AF_UNSPEC) {
-if ((index = sock->prot.inet.reg_index) < 0)
-/* socket is being closed */
-return -EBADF;
-
-rtdm_lock_get_irqsave(_socket_base_lock, context);
-
-sock->prot.inet.saddr = INADDR_ANY;
-/* Note: The following line differs from standard stacks, and we also
- don't remove the socket from the port list. Might get fixed in
- the future... */
-sock->prot.inet.sport = index + auto_port_start;
-sock->prot.inet.daddr = INADDR_ANY;
-sock->prot.inet.dport = 0;
-sock->prot.inet.state = TCP_CLOSE;
-
-rtdm_lock_put_irqrestore(_socket_base_lock, context);
-} else {
-if ((addrlen < (int)sizeof(struct sockaddr_in)) ||
-(usin->sin_family != AF_INET))
-return -EINVAL;
-
-rtdm_lock_get_irqsave(_socket_base_lock, context);
-
-if (sock->prot.inet.state != TCP_CLOSE) {
-rtdm_lock_put_irqrestore(_socket_base_lock, context);
-return -EINVAL;
-}
-
-sock->prot.inet.state = TCP_ESTABLISHED;
-sock->prot.inet.daddr = usin->sin_addr.s_addr;
-sock->prot.inet.dport = usin->sin_port;
-
-rtdm_lock_put_irqrestore(_socket_base_lock, context);
-}
+   struct sockaddr _sa, *sa;
+   struct sockaddr_in _sin, *sin;
+   rtdm_lockctx_t  context;
+   int index;
+
+   if (addrlen < sizeof(struct sockaddr))
+   return -EINVAL;
+   
+   sa = rtnet_get_arg(fd, &_sa, serv_addr, sizeof(_sa));
+   if (IS_ERR(sa))
+   return PTR_ERR(sa);
+
+   if (sa->sa_family == AF_UNSPEC) {
+   if ((index = sock->prot.inet.reg_index) < 0)
+   /* socket is being closed */
+   return -EBADF;
+
+   rtdm_lock_get_irqsave(_socket_base_lock, context);
+
+   sock->prot.inet.saddr = INADDR_ANY;
+   /* Note: The following line differs from standard
+  stacks, and we also don't remove the socket from
+ 

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2018-03-01 Thread git repository hosting
Module: xenomai-3
Branch: wip/rtnet-fixes
Commit: 3d5f95ed7f5f517ce1596e5d5a429c2e43319631
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=3d5f95ed7f5f517ce1596e5d5a429c2e43319631

Author: Philippe Gerum 
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 |  222 +++
 1 file changed, 138 insertions(+), 84 deletions(-)

diff --git a/kernel/drivers/net/stack/ipv4/udp/udp.c 
b/kernel/drivers/net/stack/ipv4/udp/udp.c
index 6d624e0..903e897 100644
--- a/kernel/drivers/net/stack/ipv4/udp/udp.c
+++ b/kernel/drivers/net/stack/ipv4/udp/udp.c
@@ -154,18 +154,24 @@ static inline struct rtsocket *rt_udp_v4_lookup(u32 
daddr, u16 dport)
  *  @s: socket
  *  @addr:  local address
  */
-int rt_udp_bind(struct rtsocket *sock, const struct sockaddr *addr,
-socklen_t addrlen)
+int rt_udp_bind(struct rtdm_fd *fd, struct rtsocket *sock,
+   const struct sockaddr __user *addr, socklen_t addrlen)
 {
-struct sockaddr_in  *usin = (struct sockaddr_in *)addr;
+struct sockaddr_in  _sin, *sin;
 rtdm_lockctx_t  context;
 int index;
 int err = 0;
 
 
-if ((addrlen < (int)sizeof(struct sockaddr_in)) ||
-((usin->sin_port & auto_port_mask) == auto_port_start))
-return -EINVAL;
+if (addrlen < sizeof(struct sockaddr_in))
+   return -EINVAL;
+
+sin = rtnet_get_arg(fd, &_sin, addr, sizeof(_sin));
+if (IS_ERR(sin))
+   return PTR_ERR(sin);
+
+if ((sin->sin_port & auto_port_mask) == auto_port_start)
+   return -EINVAL;
 
 rtdm_lock_get_irqsave(_socket_base_lock, context);
 
@@ -181,8 +187,8 @@ int rt_udp_bind(struct rtsocket *sock, const struct 
sockaddr *addr,
 
 port_hash_del(_registry[index]);
 if (port_hash_insert(_registry[index],
- usin->sin_addr.s_addr,
- usin->sin_port ?: index + auto_port_start)) {
+ sin->sin_addr.s_addr,
+ sin->sin_port ?: index + auto_port_start)) {
 port_hash_insert(_registry[index],
  port_registry[index].saddr,
  port_registry[index].sport);
@@ -207,51 +213,64 @@ int rt_udp_bind(struct rtsocket *sock, const struct 
sockaddr *addr,
 /***
  *  rt_udp_connect
  */
-int rt_udp_connect(struct rtsocket *sock, const struct sockaddr *serv_addr,
-   socklen_t addrlen)
+int rt_udp_connect(struct rtdm_fd *fd, struct rtsocket *sock,
+  const struct sockaddr __user *serv_addr, socklen_t addrlen)
 {
-struct sockaddr_in  *usin = (struct sockaddr_in *) serv_addr;
-rtdm_lockctx_t  context;
-int index;
-
-
-if (usin->sin_family == AF_UNSPEC) {
-if ((index = sock->prot.inet.reg_index) < 0)
-/* socket is being closed */
-return -EBADF;
-
-rtdm_lock_get_irqsave(_socket_base_lock, context);
-
-sock->prot.inet.saddr = INADDR_ANY;
-/* Note: The following line differs from standard stacks, and we also
- don't remove the socket from the port list. Might get fixed in
- the future... */
-sock->prot.inet.sport = index + auto_port_start;
-sock->prot.inet.daddr = INADDR_ANY;
-sock->prot.inet.dport = 0;
-sock->prot.inet.state = TCP_CLOSE;
-
-rtdm_lock_put_irqrestore(_socket_base_lock, context);
-} else {
-if ((addrlen < (int)sizeof(struct sockaddr_in)) ||
-(usin->sin_family != AF_INET))
-return -EINVAL;
-
-rtdm_lock_get_irqsave(_socket_base_lock, context);
-
-if (sock->prot.inet.state != TCP_CLOSE) {
-rtdm_lock_put_irqrestore(_socket_base_lock, context);
-return -EINVAL;
-}
-
-sock->prot.inet.state = TCP_ESTABLISHED;
-sock->prot.inet.daddr = usin->sin_addr.s_addr;
-sock->prot.inet.dport = usin->sin_port;
-
-rtdm_lock_put_irqrestore(_socket_base_lock, context);
-}
+   struct sockaddr _sa, *sa;
+   struct sockaddr_in _sin, *sin;
+   rtdm_lockctx_t  context;
+   int index;
+
+   if (addrlen < sizeof(struct sockaddr))
+   return -EINVAL;
+   
+   sa = rtnet_get_arg(fd, &_sa, serv_addr, sizeof(_sa));
+   if (IS_ERR(sa))
+   return PTR_ERR(sa);
+
+   if (sa->sa_family == AF_UNSPEC) {
+   if ((index = sock->prot.inet.reg_index) < 0)
+   /* socket is being closed */
+   return -EBADF;
+
+   rtdm_lock_get_irqsave(_socket_base_lock, context);
+
+   sock->prot.inet.saddr = INADDR_ANY;
+   /* Note: The following line differs from standard
+  stacks, and we also don't remove the socket from
+  

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2018-02-28 Thread git repository hosting
Module: xenomai-3
Branch: wip/rtnet-fixes
Commit: 79879ab9d67eeef2195b221378ce246309a24fab
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=79879ab9d67eeef2195b221378ce246309a24fab

Author: Philippe Gerum 
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, , 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(>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(>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_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(, 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_name, , 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_flags, , sizeof(flags));
+   if (ret)
+   goto fail;
+}
+out:
 if ((msg_flags & 

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2018-01-27 Thread git repository hosting
Module: xenomai-3
Branch: next
Commit: 8321553d5c0143eca979b99b3148ecdc67d24166
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=8321553d5c0143eca979b99b3148ecdc67d24166

Author: Philippe Gerum 
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, , 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(>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(>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_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(, 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_name, , 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_flags, , sizeof(flags));
+   if (ret)
+   goto fail;
+}
+out:
 if ((msg_flags & MSG_PEEK) 

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2018-01-27 Thread git repository hosting
Module: xenomai-3
Branch: next
Commit: 9ab984cb49fb2ad1efb44c3a295017d0c2ad52e8
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=9ab984cb49fb2ad1efb44c3a295017d0c2ad52e8

Author: Philippe Gerum 
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, , 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(>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(>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_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(, 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_name, , 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_flags, , sizeof(flags));
+   if (ret)
+   goto fail;
+}
+out:
 if ((msg_flags & MSG_PEEK) 

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2018-01-26 Thread git repository hosting
Module: xenomai-3
Branch: next
Commit: bc0ed268adf016f79559aa53204b046b03c99837
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=bc0ed268adf016f79559aa53204b046b03c99837

Author: Philippe Gerum 
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, , 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(>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(>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_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(, 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_name, , 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_flags, , sizeof(flags));
+   if (ret)
+   goto fail;
+}
+out:
 if ((msg_flags & MSG_PEEK) 

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2018-01-23 Thread git repository hosting
Module: xenomai-3
Branch: wip/rtnet-fixes
Commit: f941ede5d624adefebb233e244996d49cf5efcfa
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=f941ede5d624adefebb233e244996d49cf5efcfa

Author: Philippe Gerum 
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, , 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(>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(>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_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(, 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_name, , 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_flags, , sizeof(flags));
+   if (ret)
+   goto fail;
+}
+out:
 if ((msg_flags & 

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2018-01-23 Thread git repository hosting
Module: xenomai-3
Branch: wip/rtnet-fixes
Commit: 0773253d7f8d47b7a6e9a8d6dd8f4cd4d3240e87
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=0773253d7f8d47b7a6e9a8d6dd8f4cd4d3240e87

Author: Philippe Gerum 
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, , 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(>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(>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_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(, 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_name, , 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_flags, , sizeof(flags));
+   if (ret)
+   goto fail;
+}
+out:
 if ((msg_flags & 

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2018-01-15 Thread git repository hosting
Module: xenomai-3
Branch: wip/rtnet-fixes
Commit: 81c5c20cc57e12b371ee229cf51b2df1e7defd16
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=81c5c20cc57e12b371ee229cf51b2df1e7defd16

Author: Philippe Gerum 
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, , 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(>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(>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_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(, 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_name, , 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_flags, , sizeof(flags));
+   if (ret)
+   goto fail;
+}
+out:
 if ((msg_flags & 

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2018-01-15 Thread git repository hosting
Module: xenomai-3
Branch: wip/rtnet-fixes
Commit: 1db36f2b2db10717312da68cb75702c388bd5f90
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=1db36f2b2db10717312da68cb75702c388bd5f90

Author: Philippe Gerum 
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, , 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(>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(>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_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(, 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_name, , 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_flags, , sizeof(flags));
+   if (ret)
+   goto fail;
+}
+out:
 if ((msg_flags & 

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2017-12-20 Thread git repository hosting
Module: xenomai-3
Branch: wip/rtnet-fixes
Commit: b6dc4754f8fa09ce178fd2aec8f0eb5715a2e900
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=b6dc4754f8fa09ce178fd2aec8f0eb5715a2e900

Author: Philippe Gerum 
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, , 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(>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(>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_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(, 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_name, , 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_flags, , sizeof(flags));
+   if (ret)
+   goto fail;
+}
+out:
 if ((msg_flags & 

[Xenomai-git] Philippe Gerum : net/udp: recvmsg: remove direct references to user memory

2017-12-06 Thread git repository hosting
Module: xenomai-3
Branch: wip/rtnet-fixes
Commit: 6670cf25851d474b3ac1b876d7369e15c6468c75
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=6670cf25851d474b3ac1b876d7369e15c6468c75

Author: Philippe Gerum 
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, , 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(>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(>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_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(, 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_name, , 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_flags, , sizeof(flags));
+   if (ret)
+   goto fail;
+}
+out:
 if ((msg_flags &