Author: dchagin
Date: Sun May 24 16:26:55 2015
New Revision: 283433
URL: https://svnweb.freebsd.org/changeset/base/283433

Log:
  Rewrite linux_recvfrom. To avoid double conversion of sockaddr use
  kern_recvit() directly.
  And check fromlen parameter before sockaddr copyin and conversion.
  
  Differential Revision:        https://reviews.freebsd.org/D1082

Modified:
  head/sys/compat/linux/linux_socket.c

Modified: head/sys/compat/linux/linux_socket.c
==============================================================================
--- head/sys/compat/linux/linux_socket.c        Sun May 24 16:25:44 2015        
(r283432)
+++ head/sys/compat/linux/linux_socket.c        Sun May 24 16:26:55 2015        
(r283433)
@@ -428,7 +428,6 @@ linux_to_bsd_sockaddr(struct sockaddr *a
        return (error);
 }
 
-
 static int
 linux_sa_put(struct osockaddr *osa)
 {
@@ -1027,41 +1026,50 @@ linux_sendto(struct thread *td, struct l
 int
 linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args)
 {
-       struct recvfrom_args /* {
-               int     s;
-               caddr_t buf;
-               size_t  len;
-               int     flags;
-               struct sockaddr * __restrict from;
-               socklen_t * __restrict fromlenaddr;
-       } */ bsd_args;
-       size_t len;
+       struct msghdr msg;
+       struct iovec aiov;
        int error;
 
-       if ((error = copyin(PTRIN(args->fromlen), &len, sizeof(size_t))))
-               return (error);
+       if (PTRIN(args->fromlen) != NULL) {
+               error = copyin(PTRIN(args->fromlen), &msg.msg_namelen,
+                   sizeof(msg.msg_namelen));
+               if (error != 0)
+                       return (error);
 
-       bsd_args.s = args->s;
-       bsd_args.buf = PTRIN(args->buf);
-       bsd_args.len = args->len;
-       bsd_args.flags = linux_to_bsd_msg_flags(args->flags);
-       /* XXX: */
-       bsd_args.from = (struct sockaddr * __restrict)PTRIN(args->from);
-       bsd_args.fromlenaddr = PTRIN(args->fromlen);/* XXX */
-       
-       linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.from, len);
-       error = sys_recvfrom(td, &bsd_args);
-       bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.from);
-       
-       if (error)
+               error = linux_to_bsd_sockaddr((struct sockaddr 
*)PTRIN(args->from),
+                   msg.msg_namelen);
+               if (error != 0)
+                       return (error);
+       } else
+               msg.msg_namelen = 0;
+
+       msg.msg_name = (struct sockaddr * __restrict)PTRIN(args->from);
+       msg.msg_iov = &aiov;
+       msg.msg_iovlen = 1;
+       aiov.iov_base = PTRIN(args->buf);
+       aiov.iov_len = args->len;
+       msg.msg_control = 0;
+       msg.msg_flags = linux_to_bsd_msg_flags(args->flags);
+
+       error = kern_recvit(td, args->s, &msg, UIO_USERSPACE, NULL);
+       if (error != 0)
                return (error);
-       if (args->from) {
-               error = linux_sa_put((struct osockaddr *)
+
+       if (PTRIN(args->from) != NULL) {
+               error = bsd_to_linux_sockaddr((struct sockaddr *)
                    PTRIN(args->from));
-               if (error)
+               if (error != 0)
                        return (error);
+
+               error = linux_sa_put((struct osockaddr *)
+                   PTRIN(args->from));
        }
-       return (0);
+
+       if (PTRIN(args->fromlen) != NULL)
+               error = copyout(&msg.msg_namelen, PTRIN(args->fromlen),
+                   sizeof(msg.msg_namelen));
+
+       return (error);
 }
 
 int
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to