Author: dchagin
Date: Sun Feb 12 15:22:50 2017
New Revision: 313684
URL: https://svnweb.freebsd.org/changeset/base/313684

Log:
  Fix r313284.
  
  Members of the syscall argument structures are padded to a word size. So,
  for COMPAT_LINUX32 we should convert user supplied system call arguments
  which is 32-bit in that case to the array of register_t.
  
  Reported by:  Oleg V. Nauman
  MFC after:    1 week

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

Modified: head/sys/compat/linux/linux_socket.c
==============================================================================
--- head/sys/compat/linux/linux_socket.c        Sun Feb 12 09:49:44 2017        
(r313683)
+++ head/sys/compat/linux/linux_socket.c        Sun Feb 12 15:22:50 2017        
(r313684)
@@ -1683,39 +1683,45 @@ linux_getsockopt(struct thread *td, stru
 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
 
 /* Argument list sizes for linux_socketcall */
-
-#define LINUX_AL(x) ((x) * sizeof(l_ulong))
-
-static const unsigned char lxs_args[] = {
-       LINUX_AL(0) /* unused*/,        LINUX_AL(3) /* socket */,
-       LINUX_AL(3) /* bind */,         LINUX_AL(3) /* connect */,
-       LINUX_AL(2) /* listen */,       LINUX_AL(3) /* accept */,
-       LINUX_AL(3) /* getsockname */,  LINUX_AL(3) /* getpeername */,
-       LINUX_AL(4) /* socketpair */,   LINUX_AL(4) /* send */,
-       LINUX_AL(4) /* recv */,         LINUX_AL(6) /* sendto */,
-       LINUX_AL(6) /* recvfrom */,     LINUX_AL(2) /* shutdown */,
-       LINUX_AL(5) /* setsockopt */,   LINUX_AL(5) /* getsockopt */,
-       LINUX_AL(3) /* sendmsg */,      LINUX_AL(3) /* recvmsg */,
-       LINUX_AL(4) /* accept4 */,      LINUX_AL(5) /* recvmmsg */,
-       LINUX_AL(4) /* sendmmsg */
+static const unsigned char lxs_args_cnt[] = {
+       0 /* unused*/,          3 /* socket */,
+       3 /* bind */,           3 /* connect */,
+       2 /* listen */,         3 /* accept */,
+       3 /* getsockname */,    3 /* getpeername */,
+       4 /* socketpair */,     4 /* send */,
+       4 /* recv */,           6 /* sendto */,
+       6 /* recvfrom */,       2 /* shutdown */,
+       5 /* setsockopt */,     5 /* getsockopt */,
+       3 /* sendmsg */,        3 /* recvmsg */,
+       4 /* accept4 */,        5 /* recvmmsg */,
+       4 /* sendmmsg */
 };
-
-#define        LINUX_AL_SIZE   (nitems(lxs_args) - 1)
+#define        LINUX_ARGS_CNT          (nitems(lxs_args_cnt) - 1)
+#define        LINUX_ARG_SIZE(x)       (lxs_args_cnt[x] * sizeof(l_ulong))
 
 int
 linux_socketcall(struct thread *td, struct linux_socketcall_args *args)
 {
        l_ulong a[6];
+#if defined(__amd64__) && defined(COMPAT_LINUX32)
+       register_t l_args[6];
+#endif
        void *arg;
        int error;
 
-       if (args->what < LINUX_SOCKET || args->what > LINUX_AL_SIZE)
+       if (args->what < LINUX_SOCKET || args->what > LINUX_ARGS_CNT)
                return (EINVAL);
-       error = copyin(PTRIN(args->args), a, lxs_args[args->what]);
-       if (error)
+       error = copyin(PTRIN(args->args), a, LINUX_ARG_SIZE(args->what));
+       if (error != 0)
                return (error);
 
+#if defined(__amd64__) && defined(COMPAT_LINUX32)
+       for (int i = 0; i < lxs_args_cnt[args->what]; ++i)
+               l_args[i] = a[i];
+       arg = l_args;
+#else
        arg = a;
+#endif
        switch (args->what) {
        case LINUX_SOCKET:
                return (linux_socket(td, arg));
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to