swrap: export a public socket_wrapper_indicate_no_inet_fd() helper function
authorStefan Metzmacher <metze@samba.org>
Wed, 17 Feb 2021 11:29:27 +0000 (12:29 +0100)
committerAndreas Schneider <asn@samba.org>
Mon, 15 Mar 2021 07:04:58 +0000 (08:04 +0100)
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>
doc/socket_wrapper.1
doc/socket_wrapper.1.adoc
src/socket_wrapper.c
src/socket_wrapper.h
src/socket_wrapper_noop.c
tests/test_public_functions.c

index b6363cd65ac412e0bf2e9cc54e9c001e99aa180e..c98822790aa3d9ae242f1b7bf585966f4476e455 100644 (file)
@@ -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
index fd0b74584224113e660b69151a78174565117919..39c46eee8aaf5b482356dfeee12c8b723aaa972a 100644 (file)
@@ -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
 ---------
 
index 63de14885fdd93addfde0fe965d5e772b7c07fe4..714cd259fa46402066e2c9f1bfff316a4a647af8 100644 (file)
@@ -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);
index f1a97e8eb3182c7d61f1c605e24d4f8646ccec15..3ec5031f7d16d66b7f7fff23476ff55cec90d656 100644 (file)
  */
 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__ */
index 45aff8f7d0c7ea769f48e82dc0864117ab1a8e92..aadf35098210701f08262d8d353f83021810620c 100644 (file)
@@ -55,3 +55,9 @@ bool socket_wrapper_enabled(void)
 {
        return false;
 }
+
+void socket_wrapper_indicate_no_inet_fd(int fd)
+{
+       (void) fd; /* unused */
+       return;
+}
index 11d03ef4280df54122b98cfd584fecc392a47fde..816cd7d5bc09f255f92bab216fde3fb56620c51d 100644 (file)
@@ -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);