diff options
author | Stefan Metzmacher <metze@samba.org> | 2021-02-17 10:58:29 +0100 |
---|---|---|
committer | Andreas Schneider <asn@samba.org> | 2021-03-15 08:04:58 +0100 |
commit | 181a3fa5e4c242d72d311f5baa771c680647eda7 (patch) | |
tree | 3d2200b8d94d3510c5b7d6cc1ca5caa72be59c6d | |
parent | ba970e5d32cceb0750eaa71fb83da3e2eef881d5 (diff) | |
download | socket_wrapper-181a3fa5e4c242d72d311f5baa771c680647eda7.tar.gz socket_wrapper-181a3fa5e4c242d72d311f5baa771c680647eda7.tar.xz socket_wrapper-181a3fa5e4c242d72d311f5baa771c680647eda7.zip |
swrap: wrap __close_nocancel() if available
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>
-rw-r--r-- | ConfigureChecks.cmake | 1 | ||||
-rw-r--r-- | config.h.cmake | 1 | ||||
-rw-r--r-- | src/socket_wrapper.c | 33 | ||||
-rw-r--r-- | tests/test_tcp_dup2.c | 20 |
4 files changed, 54 insertions, 1 deletions
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index bfb8c17..2c78b83 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -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) diff --git a/config.h.cmake b/config.h.cmake index 1148f74..0f2fb09 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -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 diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index 714cd25..44cfad8 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -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 ***************************/ diff --git a/tests/test_tcp_dup2.c b/tests/test_tcp_dup2.c index fd6adc2..238b9a8 100644 --- a/tests/test_tcp_dup2.c +++ b/tests/test_tcp_dup2.c @@ -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) { |