Module: xenomai-3
Branch: wip/rtnet-fixes
Commit: e9bedb0cdab8321457c82e91ffdff92cfc7ceb40
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=e9bedb0cdab8321457c82e91ffdff92cfc7ceb40

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sun Jan  7 18:23:57 2018 +0100

net/udp: recvmsg, ioctl: remove direct references to user memory (2)

---

 kernel/drivers/net/stack/ipv4/udp/udp.c |  137 ++++++++++++++++++-------------
 1 file changed, 78 insertions(+), 59 deletions(-)

diff --git a/kernel/drivers/net/stack/ipv4/udp/udp.c 
b/kernel/drivers/net/stack/ipv4/udp/udp.c
index 4368303..8e80d3e 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(&udp_socket_base_lock, context);
 
@@ -181,8 +187,8 @@ int rt_udp_bind(struct rtsocket *sock, const struct 
sockaddr *addr,
 
     port_hash_del(&port_registry[index]);
     if (port_hash_insert(&port_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(&port_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(&udp_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(&udp_socket_base_lock, context);
-    } else {
-        if ((addrlen < (int)sizeof(struct sockaddr_in)) ||
-            (usin->sin_family != AF_INET))
-            return -EINVAL;
-
-        rtdm_lock_get_irqsave(&udp_socket_base_lock, context);
-
-        if (sock->prot.inet.state != TCP_CLOSE) {
-            rtdm_lock_put_irqrestore(&udp_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(&udp_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(&udp_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(&udp_socket_base_lock, context);
+       } else {
+               if (addrlen < sizeof(struct sockaddr_in))
+                       return -EINVAL;
+
+               sin = rtnet_get_arg(fd, &_sin, serv_addr, sizeof(_sin));
+               if (IS_ERR(sin))
+                       return PTR_ERR(sin);
+
+               if (sin->sin_family != AF_INET)
+                       return -EINVAL;
+               
+               rtdm_lock_get_irqsave(&udp_socket_base_lock, context);
+
+               if (sock->prot.inet.state != TCP_CLOSE) {
+                       rtdm_lock_put_irqrestore(&udp_socket_base_lock, 
context);
+                       return -EINVAL;
+               }
+
+               sock->prot.inet.state = TCP_ESTABLISHED;
+               sock->prot.inet.daddr = sin->sin_addr.s_addr;
+               sock->prot.inet.dport = sin->sin_port;
+
+               rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
+       }
 
-    return 0;
+       return 0;
 }
 
 
@@ -363,9 +382,9 @@ int rt_udp_ioctl(struct rtdm_fd *fd, unsigned int request, 
void __user *arg)
                if (IS_ERR(setaddr))
                        return PTR_ERR(setaddr);
                if (request == _RTIOC_BIND)
-                       return rt_udp_bind(sock, setaddr->addr, 
setaddr->addrlen);
+                       return rt_udp_bind(fd, sock, setaddr->addr, 
setaddr->addrlen);
 
-               return rt_udp_connect(sock, setaddr->addr, setaddr->addrlen);
+               return rt_udp_connect(fd, sock, setaddr->addr, 
setaddr->addrlen);
 
         default:
                return rt_ip_ioctl(fd, request, arg);
@@ -380,7 +399,7 @@ int rt_udp_ioctl(struct rtdm_fd *fd, unsigned int request, 
void __user *arg)
 /***
  *  rt_udp_recvmsg
  */
-ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct user_msghdr *msg, int 
msg_flags)
+ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct user_msghdr *u_msg, int 
msg_flags)
 {
     struct rtsocket     *sock = rtdm_fd_to_private(fd);
     size_t              len;
@@ -393,11 +412,11 @@ ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct 
user_msghdr *msg, int msg_flag
     struct sockaddr_in  sin;
     nanosecs_rel_t      timeout = sock->timeout;
     int                 ret, flags;
-    struct user_msghdr _msg;
+    struct user_msghdr _msg, *msg;
     socklen_t namelen;
     struct iovec iov_fast[RTDM_IOV_FASTMAX], *iov;
 
-    msg = rtnet_get_arg(fd, &_msg, msg, sizeof(*msg));
+    msg = rtnet_get_arg(fd, &_msg, u_msg, sizeof(_msg));
     if (IS_ERR(msg))
            return PTR_ERR(msg);
 
@@ -438,12 +457,12 @@ ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct 
user_msghdr *msg, int msg_flag
            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));
+           ret = rtnet_put_arg(fd, msg->msg_name, &sin, sizeof(sin));
            if (ret)
                    goto fail;
 
            namelen = sizeof(sin);
-           ret = rtnet_put_arg(fd, &msg->msg_namelen, &namelen, 
sizeof(namelen));
+           ret = rtnet_put_arg(fd, &u_msg->msg_namelen, &namelen, 
sizeof(namelen));
            if (ret)
                    goto fail;
        }
@@ -485,7 +504,7 @@ ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct 
user_msghdr *msg, int msg_flag
            flags |= MSG_TRUNC;
 
     if (flags != msg->msg_flags) {
-           ret = rtnet_put_arg(fd, &msg->msg_flags, &flags, sizeof(flags));
+           ret = rtnet_put_arg(fd, &u_msg->msg_flags, &flags, sizeof(flags));
            if (ret)
                    goto fail;
     }


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

Reply via email to