On 03.06.19 14:10, Sebastian Smolorz wrote:
Signed-off-by: Sebastian Smolorz <sebastian.smol...@gmx.de>
---
  kernel/drivers/net/stack/ipv4/tcp/tcp.c | 90 ++++++++++++++++---------
  1 file changed, 59 insertions(+), 31 deletions(-)

diff --git a/kernel/drivers/net/stack/ipv4/tcp/tcp.c 
b/kernel/drivers/net/stack/ipv4/tcp/tcp.c
index 828f7d115..f4ea6ffcc 100644
--- a/kernel/drivers/net/stack/ipv4/tcp/tcp.c
+++ b/kernel/drivers/net/stack/ipv4/tcp/tcp.c
@@ -1418,15 +1418,18 @@ static void rt_tcp_close(struct rtdm_fd *fd)
   *  @s:     socket
   *  @addr:  local address
   */
-static int rt_tcp_bind(struct tcp_socket *ts, const struct sockaddr *addr,
-                      socklen_t addrlen)
+static int rt_tcp_bind(struct rtdm_fd *fd, struct tcp_socket *ts,
+                      const struct sockaddr __user *addr, socklen_t addrlen)
  {
-    struct sockaddr_in  *usin = (struct sockaddr_in *)addr;
+    struct sockaddr_in  *usin, _usin;
      rtdm_lockctx_t      context;
      int                 index;
      int                 bound = 0;
      int                 ret = 0;

+    usin = rtnet_get_arg(fd, &_usin, addr, sizeof(_usin));
+    if (IS_ERR(usin))
+       return PTR_ERR(usin);

      if ((addrlen < (int)sizeof(struct sockaddr_in)) ||
        ((usin->sin_port & tcp_auto_port_mask) == tcp_auto_port_start))
@@ -1475,10 +1478,11 @@ static int rt_tcp_bind(struct tcp_socket *ts, const 
struct sockaddr *addr,
  /***
   *  rt_tcp_connect
   */
-static int rt_tcp_connect(struct tcp_socket *ts, const struct sockaddr 
*serv_addr,
+static int rt_tcp_connect(struct rtdm_fd *fd, struct tcp_socket *ts,
+                         const struct sockaddr __user *serv_addr,
                          socklen_t addrlen)
  {
-    struct sockaddr_in  *usin = (struct sockaddr_in *) serv_addr;
+    struct sockaddr_in  *usin, _usin;
      struct dest_route   rt;
      rtdm_lockctx_t      context;
      int ret;
@@ -1486,6 +1490,10 @@ static int rt_tcp_connect(struct tcp_socket *ts, const 
struct sockaddr *serv_add
      if (addrlen < (int)sizeof(struct sockaddr_in))
        return -EINVAL;

+    usin = rtnet_get_arg(fd, &_usin, serv_addr, sizeof(_usin));
+    if (IS_ERR(usin))
+       return PTR_ERR(usin);
+
      if (usin->sin_family != AF_INET)
        return -EAFNOSUPPORT;

@@ -1594,18 +1602,23 @@ static int rt_tcp_listen(struct tcp_socket *ts, 
unsigned long backlog)
  /***
   *  rt_tcp_accept
   */
-static int rt_tcp_accept(struct tcp_socket *ts, struct sockaddr *addr,
-                        socklen_t *addrlen)
+static int rt_tcp_accept(struct rtdm_fd *fd, struct tcp_socket *ts,
+                        struct sockaddr *addr, socklen_t __user *addrlen)
  {
      /* Return sockaddr, but bind it with rt_socket_init, so it would be
         possible to read/write from it in future, return valid file descriptor 
*/

      int ret;
-    struct sockaddr_in  *sin = (struct sockaddr_in*)addr;
+    socklen_t           *uaddrlen, _uaddrlen;
+    struct sockaddr_in  sin;
      nanosecs_rel_t      timeout = ts->sock.timeout;
      rtdm_lockctx_t      context;
      struct dest_route   rt;

+    uaddrlen = rtnet_get_arg(fd, &_uaddrlen, addrlen, sizeof(_uaddrlen));
+    if (IS_ERR(uaddrlen))
+       return PTR_ERR(uaddrlen);
+
      rtdm_lock_get_irqsave(&ts->socket_lock, context);
      if (ts->is_accepting || ts->is_accepted) {
        /* socket is already accepted or is accepting a connection right now */
@@ -1613,7 +1626,7 @@ static int rt_tcp_accept(struct tcp_socket *ts, struct 
sockaddr *addr,
        return -EALREADY;
      }

-    if (ts->tcp_state != TCP_LISTEN || *addrlen < sizeof(struct sockaddr_in)) {
+    if (ts->tcp_state != TCP_LISTEN || *uaddrlen < sizeof(struct sockaddr_in)) 
{
        rtdm_lock_put_irqrestore(&ts->socket_lock, context);
        return -EINVAL;
      }
@@ -1642,6 +1655,18 @@ static int rt_tcp_accept(struct tcp_socket *ts, struct 
sockaddr *addr,
        goto err;
      }

+    if (addr) {
+       sin.sin_family      = AF_INET;
+       sin.sin_port        = ts->dport;
+       sin.sin_addr.s_addr = ts->daddr;
+       ret = rtnet_put_arg(fd, addr, &sin, sizeof(sin));
+       if (ret) {
+           rtdev_dereference(rt.rtdev);
+           ret = -EFAULT;
+           goto err;
+       }
+    }
+
      rtdm_lock_get_irqsave(&ts->socket_lock, context);

      if (ts->tcp_state != TCP_ESTABLISHED) {
@@ -1657,10 +1682,6 @@ static int rt_tcp_accept(struct tcp_socket *ts, struct 
sockaddr *addr,
      else
        rtdev_dereference(rt.rtdev);

-    sin->sin_family      = AF_INET;
-    sin->sin_port        = ts->dport;
-    sin->sin_addr.s_addr = ts->daddr;
-
      ts->is_accepted = 1;
      rtdm_lock_put_irqrestore(&ts->socket_lock, context);

@@ -1799,14 +1820,14 @@ static int rt_tcp_ioctl(struct rtdm_fd *fd,
                setaddr = rtnet_get_arg(fd, &_setaddr, arg, sizeof(_setaddr));
                if (IS_ERR(setaddr))
                        return PTR_ERR(setaddr);
-               return rt_tcp_bind(ts, setaddr->addr, setaddr->addrlen);
+               return rt_tcp_bind(fd, ts, setaddr->addr, setaddr->addrlen);
        case _RTIOC_CONNECT:
                if (!in_rt)
                        return -ENOSYS;
                setaddr = rtnet_get_arg(fd, &_setaddr, arg, sizeof(_setaddr));
                if (IS_ERR(setaddr))
                        return PTR_ERR(setaddr);
-               return rt_tcp_connect(ts, setaddr->addr, setaddr->addrlen);
+               return rt_tcp_connect(fd, ts, setaddr->addr, setaddr->addrlen);

        case _RTIOC_LISTEN:
                return rt_tcp_listen(ts, (unsigned long)arg);
@@ -1817,7 +1838,7 @@ static int rt_tcp_ioctl(struct rtdm_fd *fd,
                getaddr = rtnet_get_arg(fd, &_getaddr, arg, sizeof(_getaddr));
                if (IS_ERR(getaddr))
                        return PTR_ERR(getaddr);
-               return rt_tcp_accept(ts, getaddr->addr, getaddr->addrlen);
+               return rt_tcp_accept(fd, ts, getaddr->addr, getaddr->addrlen);

        case _RTIOC_SHUTDOWN:
                return rt_tcp_shutdown(ts, (unsigned long)arg);
@@ -1994,13 +2015,15 @@ static ssize_t rt_tcp_read(struct rtdm_fd *fd, void 
*buf, size_t nbyte)
  /***
   *  rt_tcp_write
   */
-static ssize_t rt_tcp_write(struct rtdm_fd *fd, const void *buf, size_t nbyte)
+static ssize_t rt_tcp_write(struct rtdm_fd *fd, const void __user *user_buf,
+                           size_t nbyte)
  {
      struct tcp_socket *ts = rtdm_fd_to_private(fd);
      uint32_t sent_len = 0;
      rtdm_lockctx_t      context;
      int ret = 0;
      nanosecs_rel_t sk_sndtimeo;
+    void *buf;

      if (!rtdm_fd_is_user(fd)) {
        return -EFAULT;
@@ -2022,6 +2045,16 @@ static ssize_t rt_tcp_write(struct rtdm_fd *fd, const 
void *buf, size_t nbyte)

      rtdm_lock_put_irqrestore(&ts->socket_lock, context);

+    buf = xnmalloc(nbyte);
+    if (buf == NULL)
+       return -ENOMEM;
+
+    ret = rtdm_copy_from_user(fd, buf, user_buf, nbyte);
+    if (ret) {
+       xnfree(buf);
+       return ret;
+    }
+
      while (sent_len < nbyte) {

        ret = rtdm_event_timedwait(&ts->send_evt, sk_sndtimeo, NULL);
@@ -2031,13 +2064,17 @@ static ssize_t rt_tcp_write(struct rtdm_fd *fd, const 
void *buf, size_t nbyte)
                case -EWOULDBLOCK:
                case -ETIMEDOUT:
                case -EINTR:
+                   xnfree(buf);
                    return sent_len ? : ret;

                case -EIDRM: /* event is destroyed */
                default:
-                   if (ts->is_closed)
+                   if (ts->is_closed) {
+                       xnfree(buf);
                        return -EBADF;
+                   }

+                   xnfree(buf);
                    return sent_len ? : ret;
            }

@@ -2054,6 +2091,7 @@ static ssize_t rt_tcp_write(struct rtdm_fd *fd, const 
void *buf, size_t nbyte)
            rtdm_event_signal(&ts->send_evt);
      }

+    xnfree(buf);
      return (ret < 0 ? ret : sent_len);
  }

@@ -2104,7 +2142,6 @@ static ssize_t rt_tcp_sendmsg(struct rtdm_fd *fd,
        struct user_msghdr _msg;
        ssize_t ret;
        size_t len;
-       void *buf;

        if (msg_flags)
                return -EOPNOTSUPP;
@@ -2122,18 +2159,9 @@ static ssize_t rt_tcp_sendmsg(struct rtdm_fd *fd,
                return ret;

        len = iov[0].iov_len;
-       if (len > 0) {
-               buf = xnmalloc(len);
-               if (buf == NULL) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               ret = rtdm_copy_from_user(fd, buf, iov[0].iov_base, len);
-               if (!ret)
-                       ret = rt_tcp_write(fd, buf, len);
-               xnfree(buf);
-       }
-out:
+       if (len > 0)
+           ret = rt_tcp_write(fd, iov[0].iov_base, len);
+
        rtdm_drop_iovec(iov, iov_fast);

        return ret;
--
2.19.1


Thanks, applied.

Jan

--
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux

Reply via email to