check_include_file(sys/signalfd.h HAVE_SYS_SIGNALFD_H)
check_include_file(sys/eventfd.h HAVE_SYS_EVENTFD_H)
check_include_file(sys/timerfd.h HAVE_SYS_TIMERFD_H)
+check_include_file(sys/syscall.h HAVE_SYS_SYSCALL_H)
check_include_file(gnu/lib-names.h HAVE_GNU_LIB_NAMES_H)
check_include_file(rpc/rpc.h HAVE_RPC_RPC_H)
+check_include_file(syscall.h HAVE_SYSCALL_H)
# SYMBOLS
set(CMAKE_REQUIRED_FLAGS -D_GNU_SOURCE)
check_function_exists(__close_nocancel HAVE___CLOSE_NOCANCEL)
check_function_exists(recvmmsg HAVE_RECVMMSG)
check_function_exists(sendmmsg HAVE_SENDMMSG)
+check_function_exists(syscall HAVE_SYSCALL)
if (UNIX)
find_library(DLFCN_LIBRARY dl)
HAVE_EVENTFD_UNSIGNED_INT)
endif (HAVE_EVENTFD)
+if (HAVE_SYSCALL)
+ set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
+
+ check_prototype_definition(syscall
+ "int syscall(int sysno, ...)"
+ "-1"
+ "unistd.h;sys/syscall.h"
+ HAVE_SYSCALL_INT)
+ set(CMAKE_REQUIRED_DEFINITIONS)
+endif (HAVE_SYSCALL)
+
if (HAVE_RECVMMSG)
# Linux legacy glibc < 2.21
set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
#cmakedefine HAVE_SYS_FILIO_H 1
#cmakedefine HAVE_SYS_SIGNALFD_H 1
#cmakedefine HAVE_SYS_EVENTFD_H 1
+#cmakedefine HAVE_SYS_SYSCALL_H 1
#cmakedefine HAVE_SYS_TIMERFD_H 1
#cmakedefine HAVE_GNU_LIB_NAMES_H 1
#cmakedefine HAVE_RPC_RPC_H 1
+#cmakedefine HAVE_SYSCALL_H 1
/**************************** STRUCTS ****************************/
#cmakedefine HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT 1
#cmakedefine HAVE_SENDMMSG 1
#cmakedefine HAVE_SENDMMSG_SSIZE_T 1
+#cmakedefine HAVE_SYSCALL 1
+#cmakedefine HAVE_SYSCALL_INT 1
/*************************** LIBRARIES ***************************/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#endif
+#ifdef HAVE_SYSCALL_H
+#include <syscall.h>
+#endif
#include <sys/socket.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_FILIO_H
#endif
typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
+#ifdef HAVE_SYSCALL
+typedef long int (*__libc_syscall)(long int sysno, ...);
+#endif
#define SWRAP_SYMBOL_ENTRY(i) \
union { \
#endif
SWRAP_SYMBOL_ENTRY(write);
SWRAP_SYMBOL_ENTRY(writev);
+#ifdef HAVE_SYSCALL
+ SWRAP_SYMBOL_ENTRY(syscall);
+#endif
};
struct swrap {
return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
}
+#ifdef HAVE_SYSCALL
+DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
+static long int libc_vsyscall(long int sysno, va_list va)
+{
+ long int args[8];
+ long int rc;
+ int i;
+
+ swrap_bind_symbol_all();
+
+ for (i = 0; i < 8; i++) {
+ args[i] = va_arg(va, long int);
+ }
+
+ rc = swrap.libc.symbols._libc_syscall.f(sysno,
+ args[0],
+ args[1],
+ args[2],
+ args[3],
+ args[4],
+ args[5],
+ args[6],
+ args[7]);
+
+ return rc;
+}
+#endif /* HAVE_SYSCALL */
+
/* DO NOT call this function during library initialization! */
static void __swrap_bind_symbol_all_once(void)
{
#endif
swrap_bind_symbol_libc(write);
swrap_bind_symbol_libsocket(writev);
+#ifdef HAVE_SYSCALL
+ swrap_bind_symbol_libc(syscall);
+#endif
}
static void swrap_bind_symbol_all(void)
}
#endif /* HAVE_PLEDGE */
+#ifdef HAVE_SYSCALL
+static bool swrap_is_swrap_related_syscall(long int sysno)
+{
+ switch (sysno) {
+#ifdef SYS_close
+ case SYS_close:
+ return true;
+#endif /* SYS_close */
+
+#ifdef SYS_recvmmsg
+ case SYS_recvmmsg:
+ return true;
+#endif /* SYS_recvmmsg */
+
+#ifdef SYS_sendmmsg
+ case SYS_sendmmsg:
+ return true;
+#endif /* SYS_sendmmsg */
+
+ default:
+ return false;
+ }
+}
+
+static long int swrap_syscall(long int sysno, va_list vp)
+{
+ long int rc;
+
+ switch (sysno) {
+#ifdef SYS_close
+ case SYS_close:
+ {
+ int fd = (int)va_arg(vp, int);
+
+ SWRAP_LOG(SWRAP_LOG_TRACE,
+ "calling swrap_close syscall %lu",
+ sysno);
+ rc = swrap_close(fd);
+ }
+ break;
+#endif /* SYS_close */
+
+#ifdef SYS_recvmmsg
+ case SYS_recvmmsg:
+ {
+ int fd = (int)va_arg(vp, int);
+ struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
+ unsigned int vlen = va_arg(vp, unsigned int);
+ int flags = va_arg(vp, int);
+ struct timespec *timeout = va_arg(vp, struct timespec *);
+
+ SWRAP_LOG(SWRAP_LOG_TRACE,
+ "calling swrap_recvmmsg syscall %lu",
+ sysno);
+ rc = swrap_recvmmsg(fd, msgvec, vlen, flags, timeout);
+ }
+ break;
+#endif /* SYS_recvmmsg */
+
+#ifdef SYS_sendmmsg
+ case SYS_sendmmsg:
+ {
+ int fd = (int)va_arg(vp, int);
+ struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
+ unsigned int vlen = va_arg(vp, unsigned int);
+ int flags = va_arg(vp, int);
+
+ SWRAP_LOG(SWRAP_LOG_TRACE,
+ "calling swrap_sendmmsg syscall %lu",
+ sysno);
+ rc = swrap_sendmmsg(fd, msgvec, vlen, flags);
+ }
+ break;
+#endif /* SYS_sendmmsg */
+
+ default:
+ rc = -1;
+ errno = ENOSYS;
+ break;
+ }
+
+ return rc;
+}
+
+#ifdef HAVE_SYSCALL_INT
+int syscall(int sysno, ...)
+#else
+long int syscall(long int sysno, ...)
+#endif
+{
+#ifdef HAVE_SYSCALL_INT
+ int rc;
+#else
+ long int rc;
+#endif
+ va_list va;
+
+ va_start(va, sysno);
+
+ /*
+ * We should only handle the syscall numbers
+ * we care about...
+ */
+ if (!swrap_is_swrap_related_syscall(sysno)) {
+ rc = libc_vsyscall(sysno, va);
+ va_end(va);
+ return rc;
+ }
+
+ if (!socket_wrapper_enabled()) {
+ rc = libc_vsyscall(sysno, va);
+ va_end(va);
+ return rc;
+ }
+
+ rc = swrap_syscall(sysno, va);
+ va_end(va);
+
+ return rc;
+}
+#endif /* HAVE_SYSCALL */
+
static void swrap_thread_prepare(void)
{
/*