[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 05/22] linux-user: Fix socketcall() syscall support
From: |
riku . voipio |
Subject: |
[Qemu-devel] [PULL 05/22] linux-user: Fix socketcall() syscall support |
Date: |
Mon, 17 Oct 2016 16:24:23 +0300 |
From: Aleksandar Markovic <address@hidden>
Since not all Linux host platforms support socketcall() (most notably
Intel), do_socketcall() function in Qemu's syscalls.c is implemented to
mirror the corespondant implementation of socketcall() in Linux kernel,
and to utilise individual socket operations that are supported on all
Linux platforms. (see kernel source file net/socket.c, definition of
socketcall).
However, error codes produced by Qemu implementation are wrong for the
cases of invalid values of the first argument. Also, naming of constants
is not consistent with kernel one, and not consistant with Qemu convention
of prefixing such constants with "TARGET_". This patch in that light
brings do_socketcall() closer to its kernel counterpart, and in that way
fixes the errors and yields more consisrtent Qemu code.
There were also three missing cases (among 20) for strace support for
socketcall(). The array that contains pointers for appropriate printing
functions is updated with 3 elements, however pointers to functions are
left NULL, and its implementation is left for future.
Also, this patch fixes failure of LTP test socketcall02, if executed on some
Qemu emulated sywstems (uer mode).
Signed-off-by: Aleksandar Markovic <address@hidden>
Signed-off-by: Riku Voipio <address@hidden>
---
linux-user/strace.c | 39 ++++++++-------
linux-user/syscall.c | 119 ++++++++++++++++++++++++----------------------
linux-user/syscall_defs.h | 42 ++++++++--------
3 files changed, 105 insertions(+), 95 deletions(-)
diff --git a/linux-user/strace.c b/linux-user/strace.c
index f37b386..a0e45b5 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1675,29 +1675,32 @@ print_optint:
}
#define PRINT_SOCKOP(name, func) \
- [SOCKOP_##name] = { #name, func }
+ [TARGET_SYS_##name] = { #name, func }
static struct {
const char *name;
void (*print)(const char *, abi_long);
} scall[] = {
- PRINT_SOCKOP(socket, do_print_socket),
- PRINT_SOCKOP(bind, do_print_sockaddr),
- PRINT_SOCKOP(connect, do_print_sockaddr),
- PRINT_SOCKOP(listen, do_print_listen),
- PRINT_SOCKOP(accept, do_print_sockaddr),
- PRINT_SOCKOP(getsockname, do_print_sockaddr),
- PRINT_SOCKOP(getpeername, do_print_sockaddr),
- PRINT_SOCKOP(socketpair, do_print_socketpair),
- PRINT_SOCKOP(send, do_print_sendrecv),
- PRINT_SOCKOP(recv, do_print_sendrecv),
- PRINT_SOCKOP(sendto, do_print_msgaddr),
- PRINT_SOCKOP(recvfrom, do_print_msgaddr),
- PRINT_SOCKOP(shutdown, do_print_shutdown),
- PRINT_SOCKOP(sendmsg, do_print_msg),
- PRINT_SOCKOP(recvmsg, do_print_msg),
- PRINT_SOCKOP(setsockopt, do_print_sockopt),
- PRINT_SOCKOP(getsockopt, do_print_sockopt),
+ PRINT_SOCKOP(SOCKET, do_print_socket),
+ PRINT_SOCKOP(BIND, do_print_sockaddr),
+ PRINT_SOCKOP(CONNECT, do_print_sockaddr),
+ PRINT_SOCKOP(LISTEN, do_print_listen),
+ PRINT_SOCKOP(ACCEPT, do_print_sockaddr),
+ PRINT_SOCKOP(GETSOCKNAME, do_print_sockaddr),
+ PRINT_SOCKOP(GETPEERNAME, do_print_sockaddr),
+ PRINT_SOCKOP(SOCKETPAIR, do_print_socketpair),
+ PRINT_SOCKOP(SEND, do_print_sendrecv),
+ PRINT_SOCKOP(RECV, do_print_sendrecv),
+ PRINT_SOCKOP(SENDTO, do_print_msgaddr),
+ PRINT_SOCKOP(RECVFROM, do_print_msgaddr),
+ PRINT_SOCKOP(SHUTDOWN, do_print_shutdown),
+ PRINT_SOCKOP(SETSOCKOPT, do_print_sockopt),
+ PRINT_SOCKOP(GETSOCKOPT, do_print_sockopt),
+ PRINT_SOCKOP(SENDMSG, do_print_msg),
+ PRINT_SOCKOP(RECVMSG, do_print_msg),
+ PRINT_SOCKOP(ACCEPT4, NULL),
+ PRINT_SOCKOP(RECVMMSG, NULL),
+ PRINT_SOCKOP(SENDMMSG, NULL),
};
static void
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 032cb76..05b4c41 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3898,89 +3898,94 @@ fail:
}
#ifdef TARGET_NR_socketcall
-/* do_socketcall() Must return target values and target errnos. */
+/* do_socketcall() must return target values and target errnos. */
static abi_long do_socketcall(int num, abi_ulong vptr)
{
- static const unsigned ac[] = { /* number of arguments per call */
- [SOCKOP_socket] = 3, /* domain, type, protocol */
- [SOCKOP_bind] = 3, /* sockfd, addr, addrlen */
- [SOCKOP_connect] = 3, /* sockfd, addr, addrlen */
- [SOCKOP_listen] = 2, /* sockfd, backlog */
- [SOCKOP_accept] = 3, /* sockfd, addr, addrlen */
- [SOCKOP_accept4] = 4, /* sockfd, addr, addrlen, flags */
- [SOCKOP_getsockname] = 3, /* sockfd, addr, addrlen */
- [SOCKOP_getpeername] = 3, /* sockfd, addr, addrlen */
- [SOCKOP_socketpair] = 4, /* domain, type, protocol, tab */
- [SOCKOP_send] = 4, /* sockfd, msg, len, flags */
- [SOCKOP_recv] = 4, /* sockfd, msg, len, flags */
- [SOCKOP_sendto] = 6, /* sockfd, msg, len, flags, addr, addrlen */
- [SOCKOP_recvfrom] = 6, /* sockfd, msg, len, flags, addr, addrlen */
- [SOCKOP_shutdown] = 2, /* sockfd, how */
- [SOCKOP_sendmsg] = 3, /* sockfd, msg, flags */
- [SOCKOP_recvmsg] = 3, /* sockfd, msg, flags */
- [SOCKOP_sendmmsg] = 4, /* sockfd, msgvec, vlen, flags */
- [SOCKOP_recvmmsg] = 4, /* sockfd, msgvec, vlen, flags */
- [SOCKOP_setsockopt] = 5, /* sockfd, level, optname, optval, optlen */
- [SOCKOP_getsockopt] = 5, /* sockfd, level, optname, optval, optlen */
+ static const unsigned nargs[] = { /* number of arguments per operation */
+ [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
+ [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
+ [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
+ [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
+ [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
+ [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
+ [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
+ [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
+ [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
+ [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
+ [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
+ [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
+ [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
+ [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
+ [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
+ [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
+ [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
+ [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
+ [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
+ [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
};
abi_long a[6]; /* max 6 args */
+ unsigned i;
- /* first, collect the arguments in a[] according to ac[] */
- if (num >= 0 && num < ARRAY_SIZE(ac)) {
- unsigned i;
- assert(ARRAY_SIZE(a) >= ac[num]); /* ensure we have space for args */
- for (i = 0; i < ac[num]; ++i) {
- if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
- return -TARGET_EFAULT;
- }
+ /* check the range of the first argument num */
+ /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
+ if (num < 1 || num > TARGET_SYS_SENDMMSG) {
+ return -TARGET_EINVAL;
+ }
+ /* ensure we have space for args */
+ if (nargs[num] > ARRAY_SIZE(a)) {
+ return -TARGET_EINVAL;
+ }
+ /* collect the arguments in a[] according to nargs[] */
+ for (i = 0; i < nargs[num]; ++i) {
+ if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
+ return -TARGET_EFAULT;
}
}
-
- /* now when we have the args, actually handle the call */
+ /* now when we have the args, invoke the appropriate underlying function */
switch (num) {
- case SOCKOP_socket: /* domain, type, protocol */
+ case TARGET_SYS_SOCKET: /* domain, type, protocol */
return do_socket(a[0], a[1], a[2]);
- case SOCKOP_bind: /* sockfd, addr, addrlen */
+ case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
return do_bind(a[0], a[1], a[2]);
- case SOCKOP_connect: /* sockfd, addr, addrlen */
+ case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
return do_connect(a[0], a[1], a[2]);
- case SOCKOP_listen: /* sockfd, backlog */
+ case TARGET_SYS_LISTEN: /* sockfd, backlog */
return get_errno(listen(a[0], a[1]));
- case SOCKOP_accept: /* sockfd, addr, addrlen */
+ case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
return do_accept4(a[0], a[1], a[2], 0);
- case SOCKOP_accept4: /* sockfd, addr, addrlen, flags */
- return do_accept4(a[0], a[1], a[2], a[3]);
- case SOCKOP_getsockname: /* sockfd, addr, addrlen */
+ case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
return do_getsockname(a[0], a[1], a[2]);
- case SOCKOP_getpeername: /* sockfd, addr, addrlen */
+ case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
return do_getpeername(a[0], a[1], a[2]);
- case SOCKOP_socketpair: /* domain, type, protocol, tab */
+ case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
return do_socketpair(a[0], a[1], a[2], a[3]);
- case SOCKOP_send: /* sockfd, msg, len, flags */
+ case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
- case SOCKOP_recv: /* sockfd, msg, len, flags */
+ case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
- case SOCKOP_sendto: /* sockfd, msg, len, flags, addr, addrlen */
+ case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
- case SOCKOP_recvfrom: /* sockfd, msg, len, flags, addr, addrlen */
+ case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
- case SOCKOP_shutdown: /* sockfd, how */
+ case TARGET_SYS_SHUTDOWN: /* sockfd, how */
return get_errno(shutdown(a[0], a[1]));
- case SOCKOP_sendmsg: /* sockfd, msg, flags */
+ case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
+ return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
+ case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
+ return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
+ case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
return do_sendrecvmsg(a[0], a[1], a[2], 1);
- case SOCKOP_recvmsg: /* sockfd, msg, flags */
+ case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
return do_sendrecvmsg(a[0], a[1], a[2], 0);
- case SOCKOP_sendmmsg: /* sockfd, msgvec, vlen, flags */
- return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
- case SOCKOP_recvmmsg: /* sockfd, msgvec, vlen, flags */
+ case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
+ return do_accept4(a[0], a[1], a[2], a[3]);
+ case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
- case SOCKOP_setsockopt: /* sockfd, level, optname, optval, optlen */
- return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
- case SOCKOP_getsockopt: /* sockfd, level, optname, optval, optlen */
- return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
+ case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
+ return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
default:
gemu_log("Unsupported socketcall: %d\n", num);
- return -TARGET_ENOSYS;
+ return -TARGET_EINVAL;
}
}
#endif
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 7872b9d..adb7153 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -9,26 +9,28 @@
#include "syscall_nr.h"
-#define SOCKOP_socket 1
-#define SOCKOP_bind 2
-#define SOCKOP_connect 3
-#define SOCKOP_listen 4
-#define SOCKOP_accept 5
-#define SOCKOP_getsockname 6
-#define SOCKOP_getpeername 7
-#define SOCKOP_socketpair 8
-#define SOCKOP_send 9
-#define SOCKOP_recv 10
-#define SOCKOP_sendto 11
-#define SOCKOP_recvfrom 12
-#define SOCKOP_shutdown 13
-#define SOCKOP_setsockopt 14
-#define SOCKOP_getsockopt 15
-#define SOCKOP_sendmsg 16
-#define SOCKOP_recvmsg 17
-#define SOCKOP_accept4 18
-#define SOCKOP_recvmmsg 19
-#define SOCKOP_sendmmsg 20
+
+/* socket operations for socketcall() */
+#define TARGET_SYS_SOCKET 1 /* socket() */
+#define TARGET_SYS_BIND 2 /* bind() */
+#define TARGET_SYS_CONNECT 3 /* connect() */
+#define TARGET_SYS_LISTEN 4 /* listen() */
+#define TARGET_SYS_ACCEPT 5 /* accept() */
+#define TARGET_SYS_GETSOCKNAME 6 /* getsockname() */
+#define TARGET_SYS_GETPEERNAME 7 /* getpeername() */
+#define TARGET_SYS_SOCKETPAIR 8 /* socketpair() */
+#define TARGET_SYS_SEND 9 /* send() */
+#define TARGET_SYS_RECV 10 /* recv() */
+#define TARGET_SYS_SENDTO 11 /* sendto() */
+#define TARGET_SYS_RECVFROM 12 /* recvfrom() */
+#define TARGET_SYS_SHUTDOWN 13 /* shutdown() */
+#define TARGET_SYS_SETSOCKOPT 14 /* setsockopt() */
+#define TARGET_SYS_GETSOCKOPT 15 /* getsockopt() */
+#define TARGET_SYS_SENDMSG 16 /* sendmsg() */
+#define TARGET_SYS_RECVMSG 17 /* recvmsg() */
+#define TARGET_SYS_ACCEPT4 18 /* accept4() */
+#define TARGET_SYS_RECVMMSG 19 /* recvmmsg() */
+#define TARGET_SYS_SENDMMSG 20 /* sendmmsg() */
#define IPCOP_semop 1
#define IPCOP_semget 2
--
2.1.4
- [Qemu-devel] [PULL 00/22] linux-user changes, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 02/22] linux-user: Add support for ustat() syscall, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 01/22] linux-user: Add support for adjtimex() syscall, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 03/22] linux-user: Fix mq_open() syscall support, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 04/22] linux-user: Fix msgrcv() and msgsnd() syscalls support, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 08/22] linux-user: sparc64: Use correct target SHMLBA in shmat(), riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 06/22] linux-user: Fix syslog() syscall support, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 11/22] linux-user: Don't use alloca() for epoll_wait's epoll event array, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 09/22] linux-user: add kcmp() syscall, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 05/22] linux-user: Fix socketcall() syscall support,
riku . voipio <=
- [Qemu-devel] [PULL 07/22] linux-user: Remove a duplicate item from strace.list, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 10/22] linux-user: add RTA_PRIORITY in netlink, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 13/22] linux-user: Fix definition of target_sigevent for 32-bit guests, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 14/22] linux-user: Add support for clock_adjtime() syscall, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 15/22] linux-user: Add support for syncfs() syscall, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 12/22] linux-user: use libc wrapper instead of direct mremap syscall, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 19/22] linux-user: Fix fadvise64() syscall support for Mips32, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 18/22] linux-user: Redirect termbits.h for Mips64 to termbits.h for Mips32, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 17/22] linux-user: Update ioctls definitions for Mips32, riku . voipio, 2016/10/17
- [Qemu-devel] [PULL 16/22] linux-user: Update mips_syscall_args[] array in main.c, riku . voipio, 2016/10/17