From ba970e5d32cceb0750eaa71fb83da3e2eef881d5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 17 Feb 2021 12:29:27 +0100 Subject: swrap: export a public socket_wrapper_indicate_no_inet_fd() helper function BUG: https://bugzilla.samba.org/show_bug.cgi?id=14640 Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider --- doc/socket_wrapper.1 | 69 +++++++++++++++++++++++++++++++++++++++++++ doc/socket_wrapper.1.adoc | 25 ++++++++++++++++ src/socket_wrapper.c | 22 ++++++++++++++ src/socket_wrapper.h | 25 ++++++++++++++++ src/socket_wrapper_noop.c | 6 ++++ tests/test_public_functions.c | 31 +++++++++++++++++++ 6 files changed, 178 insertions(+) diff --git a/doc/socket_wrapper.1 b/doc/socket_wrapper.1 index b6363cd..c988227 100644 --- a/doc/socket_wrapper.1 +++ b/doc/socket_wrapper.1 @@ -281,6 +281,75 @@ bool socket_wrapper_enabled(void); .\} This returns true when socket wrapper is actively in use. .RE +.sp +void socket_wrapper_indicate_no_inet_fd(int fd); +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +. sp -1 +. IP \(bu 2.3 +.\} +This allows socket_wrapper aware applications to +indicate that the given fd does not belong to +an inet socket. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +. sp -1 +. IP \(bu 2.3 +.\} +socket_wrapper may not be able to intercept the __close_nocancel() +syscall made from within libc.so. As result it\(cqs possible +that the in memory meta date of socket_wrapper references +stale file descriptors, which are already reused for unrelated +kernel objects, e.g. files, directories, ... +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +. sp -1 +. IP \(bu 2.3 +.\} +Socket wrapper already intercepts a lot of unrelated +functions like eventfd(), timerfd_create(), ... in order +to remove stale meta data for the returned fd, but +it will never be able to handle all possible syscalls. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +. sp -1 +. IP \(bu 2.3 +.\} +socket_wrapper_indicate_no_inet_fd() gives applications a way +to do the same, explicitly without waiting for new syscalls to +be added to libsocket_wrapper.so. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +. sp -1 +. IP \(bu 2.3 +.\} +This is a no\-op if socket_wrapper is not in use or +if the there is no in memory meta data for the given fd. +.RE .SH "RESOURCES" .sp \fBProject web site:\fP \c diff --git a/doc/socket_wrapper.1.adoc b/doc/socket_wrapper.1.adoc index fd0b745..39c46ee 100644 --- a/doc/socket_wrapper.1.adoc +++ b/doc/socket_wrapper.1.adoc @@ -156,6 +156,31 @@ bool socket_wrapper_enabled(void); - This returns true when socket wrapper is actively in use. +void socket_wrapper_indicate_no_inet_fd(int fd); + +- This allows socket_wrapper aware applications to + indicate that the given fd does not belong to + an inet socket. + +- socket_wrapper may not be able to intercept the __close_nocancel() + syscall made from within libc.so. As result it's possible + that the in memory meta date of socket_wrapper references + stale file descriptors, which are already reused for unrelated + kernel objects, e.g. files, directories, ... + +- Socket wrapper already intercepts a lot of unrelated + functions like eventfd(), timerfd_create(), ... in order + to remove stale meta data for the returned fd, but + it will never be able to handle all possible syscalls. + +- socket_wrapper_indicate_no_inet_fd() gives applications a way + to do the same, explicitly without waiting for new syscalls to + be added to libsocket_wrapper.so. + +- This is a no-op if socket_wrapper is not in use or + if the there is no in memory meta data for the given fd. + + RESOURCES --------- diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index 63de148..714cd25 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -7456,6 +7456,28 @@ static void swrap_remove_stale(int fd) swrap_remove_wrapper(__func__, swrap_noop_close, fd); } +/* + * This allows socket_wrapper aware applications to + * indicate that the given fd does not belong to + * an inet socket. + * + * We already overload a lot of unrelated functions + * like eventfd(), timerfd_create(), ... in order to + * call swrap_remove_stale() on the returned fd, but + * we'll never be able to handle all possible syscalls. + * + * socket_wrapper_indicate_no_inet_fd() gives them a way + * to do the same. + * + * We don't export swrap_remove_stale() in order to + * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3 + * log files. + */ +void socket_wrapper_indicate_no_inet_fd(int fd) +{ + swrap_remove_wrapper(__func__, swrap_noop_close, fd); +} + static int swrap_close(int fd) { return swrap_remove_wrapper(__func__, libc_close, fd); diff --git a/src/socket_wrapper.h b/src/socket_wrapper.h index f1a97e8..3ec5031 100644 --- a/src/socket_wrapper.h +++ b/src/socket_wrapper.h @@ -61,4 +61,29 @@ */ bool socket_wrapper_enabled(void); +/* + * This allows socket_wrapper aware applications to + * indicate that the given fd does not belong to + * an inet socket. + * + * socket_wrapper may not be able to intercept the __close_nocancel() + * syscall made from within libc.so. As result it's possible + * that the in memory meta date of socket_wrapper references + * stale file descriptors, which are already reused for unrelated + * kernel objects, e.g. files, directories, ... + * + * Socket wrapper already intercepts a lot of unrelated + * functions like eventfd(), timerfd_create(), ... in order + * to remove stale meta data for the returned fd, but + * it will never be able to handle all possible syscalls. + * + * socket_wrapper_indicate_no_inet_fd() gives applications a way + * to do the same, explicitly without waiting for new syscalls to + * be added to libsocket_wrapper.so. + * + * This is a no-op if socket_wrapper is not in use or + * if the there is no in memory meta data for the given fd. + */ +void socket_wrapper_indicate_no_inet_fd(int fd); + #endif /* __SOCKET_WRAPPER_H__ */ diff --git a/src/socket_wrapper_noop.c b/src/socket_wrapper_noop.c index 45aff8f..aadf350 100644 --- a/src/socket_wrapper_noop.c +++ b/src/socket_wrapper_noop.c @@ -55,3 +55,9 @@ bool socket_wrapper_enabled(void) { return false; } + +void socket_wrapper_indicate_no_inet_fd(int fd) +{ + (void) fd; /* unused */ + return; +} diff --git a/tests/test_public_functions.c b/tests/test_public_functions.c index 11d03ef..816cd7d 100644 --- a/tests/test_public_functions.c +++ b/tests/test_public_functions.c @@ -60,6 +60,31 @@ static void test_call_enabled_false(void **state) assert_false(s != NULL); } +static void test_call_indicate_no_inet_fd(void **state) +{ + int rc; + int s = -1; + + (void) state; /* unused */ + + socket_wrapper_indicate_no_inet_fd(987654321); + socket_wrapper_indicate_no_inet_fd(-1); + + rc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (rc >= 0) { + s = rc; + rc = 0; + } + assert_return_code(rc, errno); + + socket_wrapper_indicate_no_inet_fd(987654321); + socket_wrapper_indicate_no_inet_fd(-1); + socket_wrapper_indicate_no_inet_fd(s); + socket_wrapper_indicate_no_inet_fd(0); + socket_wrapper_indicate_no_inet_fd(1); + socket_wrapper_indicate_no_inet_fd(2); +} + int main(void) { int rc; @@ -70,6 +95,12 @@ int main(void) { cmocka_unit_test_setup_teardown(test_call_enabled_false, setup_disabled, teardown_disabled), + cmocka_unit_test_setup_teardown(test_call_indicate_no_inet_fd, + setup_enabled, + teardown_enabled), + cmocka_unit_test_setup_teardown(test_call_indicate_no_inet_fd, + setup_disabled, + teardown_disabled), }; rc = cmocka_run_group_tests(max_sockets_tests, NULL, NULL); -- cgit