src/uid_wrapper.c: make use of socket_wrapper_syscall_{valid,va}()
authorStefan Metzmacher <metze@samba.org>
Mon, 16 Jan 2023 10:22:02 +0000 (11:22 +0100)
committerAndreas Schneider <asn@samba.org>
Tue, 17 Jan 2023 13:31:10 +0000 (14:31 +0100)
If we find socket_wrapper_syscall_{valid,va}() symbols in the already
loaded libraries, we'll try to hand over syscall() invocations to
socket_wrapper.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
src/uid_wrapper.c

index dd52c423237427841f38ac46d3e3b06f846833e5..5b6a82b8fef32d8d03e5fd1110554d113ca9bd2e 100644 (file)
@@ -298,6 +298,28 @@ struct uwrap_libc_symbols {
 };
 #undef UWRAP_SYMBOL_ENTRY
 
+#define UWRAP_SYMBOL_ENTRY(i)         \
+       union {                       \
+               __rtld_default_##i f; \
+               void *obj;            \
+       } _rtld_default_##i
+
+#ifdef HAVE_SYSCALL
+typedef bool (*__rtld_default_socket_wrapper_syscall_valid)(long int sysno);
+typedef long int (*__rtld_default_socket_wrapper_syscall_va)(long int sysno,
+                                                            va_list va);
+#endif
+
+struct uwrap_rtld_default_symbols {
+#ifdef HAVE_SYSCALL
+       UWRAP_SYMBOL_ENTRY(socket_wrapper_syscall_valid);
+       UWRAP_SYMBOL_ENTRY(socket_wrapper_syscall_va);
+#else
+       uint8_t dummy;
+#endif
+};
+#undef UWRAP_SYMBOL_ENTRY
+
 /*****************
  * LIBPTHREAD
  *****************/
@@ -347,6 +369,10 @@ struct uwrap {
                struct uwrap_libc_symbols symbols;
        } libc;
 
+       struct {
+               struct uwrap_rtld_default_symbols symbols;
+       } rtld_default;
+
        struct {
                void *handle;
                struct uwrap_libpthread_symbols symbols;
@@ -624,6 +650,12 @@ static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
                        _uwrap_bind_symbol(UWRAP_LIBPTHREAD, #sym_name); \
        }
 
+#define uwrap_bind_symbol_rtld_default_optional(sym_name)                      \
+       if (uwrap.rtld_default.symbols._rtld_default_##sym_name.obj == NULL) { \
+               uwrap.rtld_default.symbols._rtld_default_##sym_name.obj =      \
+                       dlsym(RTLD_DEFAULT, #sym_name);                        \
+       }
+
 /* DO NOT call this function during library initialization! */
 static void __uwrap_bind_symbol_all_once(void)
 {
@@ -662,6 +694,8 @@ static void __uwrap_bind_symbol_all_once(void)
        uwrap_bind_symbol_libc(setgroups);
 #ifdef HAVE_SYSCALL
        uwrap_bind_symbol_libc(syscall);
+       uwrap_bind_symbol_rtld_default_optional(socket_wrapper_syscall_valid);
+       uwrap_bind_symbol_rtld_default_optional(socket_wrapper_syscall_va);
 #endif
        uwrap_bind_symbol_libpthread(pthread_create);
        uwrap_bind_symbol_libpthread(pthread_exit);
@@ -847,6 +881,36 @@ static long int libc_vsyscall(long int sysno, va_list va)
 
        return rc;
 }
+
+static bool uwrap_swrap_syscall_valid(long int sysno)
+{
+       uwrap_bind_symbol_all();
+
+       if (uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_valid.f == NULL) {
+               return false;
+       }
+
+       return uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_valid.f(
+                                               sysno);
+}
+
+DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
+static long int uwrap_swrap_syscall_va(long int sysno, va_list va)
+{
+       uwrap_bind_symbol_all();
+
+       if (uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_va.f == NULL) {
+               /*
+                * Fallback to libc, if socket_wrapper_vsyscall is not
+                * available.
+                */
+               return libc_vsyscall(sysno, va);
+       }
+
+       return uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_va.f(
+                                               sysno,
+                                               va);
+}
 #endif
 
 static int libpthread_pthread_create(pthread_t *thread,
@@ -2650,6 +2714,16 @@ long int syscall (long int sysno, ...)
         * fork() which calls syscall() after invoking uwrap_thread_prepare().
         */
        if (!uwrap_is_uwrap_related_syscall(sysno)) {
+               /*
+                * We need to give socket_wrapper a
+                * chance to take over...
+                */
+               if (uwrap_swrap_syscall_valid(sysno)) {
+                       rc = uwrap_swrap_syscall_va(sysno, va);
+                       va_end(va);
+                       return rc;
+               }
+
                rc = libc_vsyscall(sysno, va);
                va_end(va);
                return rc;