From b59f227ab010837874614551c1f86ed06f3075dd Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 12 Oct 2017 17:10:33 -0700 Subject: LDPRELOAD: Add ioctl, fcntl, and setsockopt support Add support for the following system calls: ioctl (FIONREAD) fcntl (F_GETFL) fcntl (F_SETFL) setsockopt (SOL_IPV6, IPV6_V6ONLY) setsockopt (SOL_TCP, TCP_NODELAY) setsockopt (SOL_SOCKET, SO_REUSEADDR) setsockopt (SOL_SOCKET, SO_BROADCAST) This patch supersedes https://gerrit.fd.io/r/#/c/8765/ Change-Id: I5d5309d9f43d93a990b389d8cb667631de1903fe Signed-off-by: Steven --- extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c | 55 ++++++ extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.h | 5 + .../src/libvcl-ldpreload/vcom_socket.c | 201 +++++++++++++++++---- .../src/libvcl-ldpreload/vcom_socket.h | 2 + .../src/libvcl-ldpreload/vcom_socket_wrapper.c | 21 +++ .../src/libvcl-ldpreload/vcom_socket_wrapper.h | 3 + 6 files changed, 255 insertions(+), 32 deletions(-) (limited to 'extras/vcl-ldpreload') diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c index 6245c5d2487..d5b3e127297 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c @@ -426,6 +426,61 @@ out: return rv; } +int +vcom_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap) +{ + if (vcom_init () != 0) + { + return -1; + } + + return vcom_socket_ioctl_va (__fd, __cmd, __ap); +} + +int +vcom_ioctl (int __fd, unsigned long int __cmd, ...) +{ + int rv = -1; + va_list ap; + + if (is_vcom_socket_fd (__fd)) + { + va_start (ap, __cmd); + rv = vcom_ioctl_va (__fd, __cmd, ap); + va_end (ap); + } + return rv; +} + +int +ioctl (int __fd, unsigned long int __cmd, ...) +{ + int rv; + va_list ap; + pid_t pid = getpid (); + + va_start (ap, __cmd); + if (is_vcom_socket_fd (__fd)) + { + rv = vcom_ioctl_va (__fd, __cmd, ap); + if (VCOM_DEBUG > 0) + fprintf (stderr, + "[%d] ioctl: " + "'%04d'='%04d', '%04ld'\n", pid, rv, __fd, __cmd); + if (rv < 0) + { + errno = -rv; + rv = -1; + } + goto out; + } + rv = libc_vioctl (__fd, __cmd, ap); + +out: + va_end (ap); + return rv; +} + /* * Check the first NFDS descriptors each in READFDS (if not NULL) for * read readiness, in WRITEFDS (if not NULL) for write readiness, diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.h b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.h index f6ee8a2bab0..bedeef807ac 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.h +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.h @@ -55,6 +55,11 @@ extern ssize_t __wur vcom_writev (int __fd, const struct iovec *__iov, */ extern int vcom_fcntl (int __fd, int __cmd, ...); +/* + * VPP implementation of glibc APIs ioctl + */ +extern int vcom_ioctl (int __fd, unsigned long int __cmd, ...); + /* * vpp implementation of glibc APIs from */ diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c index 86b923c1457..5378548f9c2 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c @@ -18,6 +18,7 @@ #include #define __need_IOV_MAX #include +#include #include #include @@ -653,8 +654,6 @@ vcom_socket_check_fcntl_cmd (int __cmd) /* Fallthrough */ case F_GETFD: case F_SETFD: - case F_GETFL: - case F_SETFL: case F_GETLK: case F_SETLK: case F_SETLKW: @@ -662,25 +661,36 @@ vcom_socket_check_fcntl_cmd (int __cmd) case F_SETOWN: return 2; -#if 0 - /* cmd handled by vppcom */ - case F_XXXXX: + /* cmd handled by vcom and vppcom */ + case F_SETFL: + case F_GETFL: return 3; -#endif - /* invalid cmd */ + + /* cmd not handled by vcom and vppcom */ default: - return 0; + return 1; } return 0; } -/* TBD: move it to vppcom */ static int -vppcom_session_fcntl_va (int __fd, int __cmd, va_list __ap) +vppcom_session_fcntl_va (int __sid, int __cmd, va_list __ap) { - int rv; + int flags = va_arg (__ap, int); + int rv = -EOPNOTSUPP; + uint32_t size; - rv = -EINVAL; + size = sizeof (flags); + if (__cmd == F_SETFL) + { + rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size); + } + else if (__cmd == F_GETFL) + { + rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size); + if (rv == VPPCOM_OK) + rv = flags; + } return rv; } @@ -712,7 +722,7 @@ vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap) break; /*cmd not handled by vcom and vppcom */ case 1: - rv = -EBADF; + rv = libc_vfcntl (vsock->fd, __cmd, __ap); break; /* cmd handled by vcom socket resource */ case 2: @@ -731,6 +741,93 @@ vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap) return rv; } +/* + * RETURN: 0 - invalid cmd + * 1 - cmd not handled by vcom and vppcom + * 2 - cmd handled by vcom socket resource + * 3 - cmd handled by vppcom + */ +static int +vcom_socket_check_ioctl_cmd (unsigned long int __cmd) +{ + int rc; + + switch (__cmd) + { + /* cmd handled by vppcom */ + case FIONREAD: + rc = 3; + break; + + /* cmd not handled by vcom and vppcom */ + default: + rc = 1; + break; + } + return rc; +} + +static int +vppcom_session_ioctl_va (int __sid, int __cmd, va_list __ap) +{ + int rv; + + if (__cmd == FIONREAD) + rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_NREAD, 0, 0); + else + rv = -EOPNOTSUPP; + return rv; +} + +int +vcom_socket_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap) +{ + int rv = -EBADF; + vcom_socket_main_t *vsm = &vcom_socket_main; + uword *p; + vcom_socket_t *vsock; + + p = hash_get (vsm->sockidx_by_fd, __fd); + if (!p) + return -EBADF; + + vsock = pool_elt_at_index (vsm->vsockets, p[0]); + if (!vsock) + return -ENOTSOCK; + + if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) + return -EINVAL; + + switch (vcom_socket_check_ioctl_cmd (__cmd)) + { + /* Not supported cmd */ + case 0: + rv = -EOPNOTSUPP; + break; + + /* cmd not handled by vcom and vppcom */ + case 1: + rv = libc_vioctl (vsock->fd, __cmd, __ap); + break; + + /* cmd handled by vcom socket resource */ + case 2: + rv = libc_vioctl (vsock->fd, __cmd, __ap); + break; + + /* cmd handled by vppcom */ + case 3: + rv = vppcom_session_ioctl_va (vsock->sid, __cmd, __ap); + break; + + default: + rv = -EINVAL; + break; + } + + return rv; +} + static inline int vcom_socket_fds_2_sid_fds ( /* dest */ @@ -1809,17 +1906,41 @@ vcom_socket_getsockopt (int __fd, int __level, int __optname, /* TBD: move it to vppcom */ int -vppcom_setsockopt (int __fd, int __level, int __optname, - const void *__optval, socklen_t __optlen) +vppcom_session_setsockopt (int __sid, int __level, int __optname, + const void *__optval, socklen_t __optlen) { - /* 1. for socket level options that are NOT socket attributes - * and that has corresponding vpp options set it from vppcom */ -#if 0 - return 0; -#endif + int rv = -EOPNOTSUPP; - /* 2. unhandled options */ - return -ENOPROTOOPT; + switch (__level) + { + case SOL_IPV6: + switch (__optname) + { + case IPV6_V6ONLY: + rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_V6ONLY, 0, 0); + return rv; + default: + return rv; + } + break; + case SOL_SOCKET: + switch (__optname) + { + case SO_REUSEADDR: + rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_REUSEADDR, 0, 0); + return rv; + case SO_BROADCAST: + rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_BROADCAST, 0, 0); + return rv; + default: + return rv; + } + break; + default: + return rv; + } + + return rv; } int @@ -1864,10 +1985,36 @@ vcom_socket_setsockopt (int __fd, int __level, int __optname, switch (__level) { + case SOL_IPV6: + switch (__optname) + { + case IPV6_V6ONLY: + rv = vppcom_session_setsockopt (vsock->sid, __level, __optname, + __optval, __optlen); + return rv; + default: + return -EOPNOTSUPP; + } + break; + case SOL_TCP: + switch (__optname) + { + case TCP_NODELAY: + return 0; + default: + return -EOPNOTSUPP; + } + break; /* handle options at socket level */ case SOL_SOCKET: switch (__optname) { + case SO_REUSEADDR: + case SO_BROADCAST: + rv = vppcom_session_setsockopt (vsock->sid, __level, __optname, + __optval, __optlen); + return rv; + /* * 1. for socket level options that are socket attributes, * set it from libc_getsockopt @@ -1878,10 +2025,8 @@ vcom_socket_setsockopt (int __fd, int __level, int __optname, * return -ENOPROTOOPT */ case SO_DEBUG: case SO_DONTROUTE: - case SO_BROADCAST: case SO_SNDBUF: case SO_RCVBUF: - case SO_REUSEADDR: case SO_REUSEPORT: case SO_KEEPALIVE: case SO_TYPE: @@ -1942,15 +2087,7 @@ vcom_socket_setsockopt (int __fd, int __level, int __optname, break; default: - /* 1. handle options that are NOT socket level options, - * but have corresponding vpp otions. */ - rv = vppcom_setsockopt (vsock->sid, __level, __optname, - __optval, __optlen); - return rv; -#if 0 - /* 2. unhandled options */ return -ENOPROTOOPT; -#endif } return rv; diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h index 7170e208012..ef57646966b 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h @@ -347,6 +347,8 @@ ssize_t vcom_socket_writev (int __fd, const struct iovec *__iov, int vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap); +int vcom_socket_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap); + int vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds, fd_set * __restrict vcom_writefds, diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.c b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.c index 74a0dcf3b11..087cd6bbc52 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.c +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.c @@ -555,6 +555,27 @@ libc_vfcntl (int fd, int cmd, va_list ap) return rc; } +DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE int +libc_vioctl (int fd, int cmd, va_list ap) +{ + long int args[4]; + int rc; + int i; + + swrap_bind_symbol_libc (ioctl); + + for (i = 0; i < 4; i++) + { + args[i] = va_arg (ap, long int); + } + + rc = swrap.libc.symbols._libc_ioctl.f (fd, + cmd, + args[0], args[1], args[2], args[3]); + + return rc; +} + int libc_getpeername (int sockfd, struct sockaddr *addr, socklen_t * addrlen) { diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.h b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.h index ef3ece01eb2..49ee7eee9e6 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.h +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.h @@ -131,6 +131,9 @@ int libc_eventfd (int count, int flags); DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE int libc_vfcntl (int fd, int cmd, va_list ap); +DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE int +libc_vioctl (int fd, int cmd, va_list ap); + int libc_getpeername (int sockfd, struct sockaddr *addr, socklen_t * addrlen); int libc_getsockname (int sockfd, struct sockaddr *addr, socklen_t * addrlen); -- cgit 1.2.3-korg