While it's no possible to inject swrap__close_nocancel() into
libc.so.6 directly, because it's no weak symbol, it seems to
be possible to inject it to other glibc libraries like
libpthread.so.0, which is better than nothing.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14640
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
check_function_exists(pledge HAVE_PLEDGE)
check_function_exists(_socket HAVE__SOCKET)
check_function_exists(_close HAVE__CLOSE)
check_function_exists(pledge HAVE_PLEDGE)
check_function_exists(_socket HAVE__SOCKET)
check_function_exists(_close HAVE__CLOSE)
+check_function_exists(__close_nocancel HAVE___CLOSE_NOCANCEL)
if (UNIX)
find_library(DLFCN_LIBRARY dl)
if (UNIX)
find_library(DLFCN_LIBRARY dl)
#cmakedefine HAVE_PLEDGE 1
#cmakedefine HAVE__SOCKET 1
#cmakedefine HAVE__CLOSE 1
#cmakedefine HAVE_PLEDGE 1
#cmakedefine HAVE__SOCKET 1
#cmakedefine HAVE__CLOSE 1
+#cmakedefine HAVE___CLOSE_NOCANCEL 1
#cmakedefine HAVE_ACCEPT_PSOCKLEN_T 1
#cmakedefine HAVE_IOCTL_INT 1
#cmakedefine HAVE_ACCEPT_PSOCKLEN_T 1
#cmakedefine HAVE_IOCTL_INT 1
const struct sockaddr *addr,
socklen_t addrlen);
typedef int (*__libc_close)(int fd);
const struct sockaddr *addr,
socklen_t addrlen);
typedef int (*__libc_close)(int fd);
+#ifdef HAVE___CLOSE_NOCANCEL
+typedef int (*__libc___close_nocancel)(int fd);
+#endif
typedef int (*__libc_connect)(int sockfd,
const struct sockaddr *addr,
socklen_t addrlen);
typedef int (*__libc_connect)(int sockfd,
const struct sockaddr *addr,
socklen_t addrlen);
#endif
SWRAP_SYMBOL_ENTRY(bind);
SWRAP_SYMBOL_ENTRY(close);
#endif
SWRAP_SYMBOL_ENTRY(bind);
SWRAP_SYMBOL_ENTRY(close);
+#ifdef HAVE___CLOSE_NOCANCEL
+ SWRAP_SYMBOL_ENTRY(__close_nocancel);
+#endif
SWRAP_SYMBOL_ENTRY(connect);
SWRAP_SYMBOL_ENTRY(dup);
SWRAP_SYMBOL_ENTRY(dup2);
SWRAP_SYMBOL_ENTRY(connect);
SWRAP_SYMBOL_ENTRY(dup);
SWRAP_SYMBOL_ENTRY(dup2);
return swrap.libc.symbols._libc_close.f(fd);
}
return swrap.libc.symbols._libc_close.f(fd);
}
+#ifdef HAVE___CLOSE_NOCANCEL
+static int libc___close_nocancel(int fd)
+{
+ swrap_bind_symbol_all();
+
+ return swrap.libc.symbols._libc___close_nocancel.f(fd);
+}
+#endif /* HAVE___CLOSE_NOCANCEL */
+
static int libc_connect(int sockfd,
const struct sockaddr *addr,
socklen_t addrlen)
static int libc_connect(int sockfd,
const struct sockaddr *addr,
socklen_t addrlen)
#endif
swrap_bind_symbol_libsocket(bind);
swrap_bind_symbol_libc(close);
#endif
swrap_bind_symbol_libsocket(bind);
swrap_bind_symbol_libc(close);
+#ifdef HAVE___CLOSE_NOCANCEL
+ swrap_bind_symbol_libc(__close_nocancel);
+#endif
swrap_bind_symbol_libsocket(connect);
swrap_bind_symbol_libc(dup);
swrap_bind_symbol_libc(dup2);
swrap_bind_symbol_libsocket(connect);
swrap_bind_symbol_libc(dup);
swrap_bind_symbol_libc(dup2);
return swrap_close(fd);
}
return swrap_close(fd);
}
+#ifdef HAVE___CLOSE_NOCANCEL
+
+static int swrap___close_nocancel(int fd)
+{
+ return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
+}
+
+int __close_nocancel(int fd);
+int __close_nocancel(int fd)
+{
+ return swrap___close_nocancel(fd);
+}
+
+#endif /* HAVE___CLOSE_NOCANCEL */
+
/****************************
* DUP
***************************/
/****************************
* DUP
***************************/
#include <cmocka.h>
#include <unistd.h>
#include <cmocka.h>
#include <unistd.h>
+#include <errno.h>
+
+#ifdef HAVE___CLOSE_NOCANCEL
+extern int __close_nocancel(int fd);
+#endif
static int setup(void **state)
{
static int setup(void **state)
{
static void test_dup2_existing_open_fd(void **state)
{
int s, dup_s;
static void test_dup2_existing_open_fd(void **state)
{
int s, dup_s;
(void) state; /* unused */
(void) state; /* unused */
dup_s = dup2(s, s);
assert_int_equal(dup_s, s);
dup_s = dup2(s, s);
assert_int_equal(dup_s, s);
+#ifdef HAVE___CLOSE_NOCANCEL
+ rc = __close_nocancel(s);
+ assert_return_code(rc, errno);
+ rc = close(s);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EBADF);
+ rc = __close_nocancel(s);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EBADF);
+#else
+ rc = close(s);
+ assert_return_code(rc, errno);
+#endif