swrap: wrap __close_nocancel() if available
authorStefan Metzmacher <metze@samba.org>
Wed, 17 Feb 2021 09:58:29 +0000 (10:58 +0100)
committerAndreas Schneider <asn@samba.org>
Mon, 15 Mar 2021 07:04:58 +0000 (08:04 +0100)
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>
ConfigureChecks.cmake
config.h.cmake
src/socket_wrapper.c
tests/test_tcp_dup2.c

index bfb8c177fd66f84340c28821f96ceb0f897c30bc..2c78b83f168dabde65f1c1b20dc7c03bc0ff0b31 100644 (file)
@@ -74,6 +74,7 @@ check_function_exists(getexecname HAVE_GETEXECNAME)
 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)
index 1148f749c639fb189931b9b1c5208983e7d6916e..0f2fb09e58b224c13f9e6b47661dc9faf59b0525 100644 (file)
@@ -47,6 +47,7 @@
 #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
index 714cd259fa46402066e2c9f1bfff316a4a647af8..44cfad8c6cfd4790ba82a3a76cc91799a28c7466 100644 (file)
@@ -492,6 +492,9 @@ typedef int (*__libc_bind)(int sockfd,
                           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);
@@ -572,6 +575,9 @@ struct swrap_libc_symbols {
 #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);
@@ -851,6 +857,15 @@ static int libc_close(int 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)
@@ -1199,6 +1214,9 @@ static void __swrap_bind_symbol_all_once(void)
 #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);
@@ -7488,6 +7506,21 @@ int close(int 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
  ***************************/
index fd6adc21de6a8d2b241c30bcef869c673f145816..238b9a8609291a50137d60cc1c0235fc81ec3a2a 100644 (file)
@@ -2,6 +2,11 @@
 
 #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)
 {
@@ -20,6 +25,7 @@ static int teardown(void **state)
 static void test_dup2_existing_open_fd(void **state)
 {
        int s, dup_s;
+       int rc;
 
        (void) state; /* unused */
 
@@ -34,7 +40,19 @@ static void test_dup2_existing_open_fd(void **state)
        dup_s = dup2(s, s);
        assert_int_equal(dup_s, s);
 
-       close(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
 }
 
 int main(void) {