From 19d0fde1ace012e366182b511c528f7ab6a0ed37 Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel.baumann@progress-linux.org>
Date: Thu, 20 Jun 2024 06:07:27 +0200
Subject: Merging upstream version 2:4.20.2+dfsg.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
---
 third_party/socket_wrapper/socket_wrapper.c | 45 ++++++++++++++++++++++++++++-
 third_party/socket_wrapper/wscript          |  3 +-
 2 files changed, 46 insertions(+), 2 deletions(-)

(limited to 'third_party/socket_wrapper')

diff --git a/third_party/socket_wrapper/socket_wrapper.c b/third_party/socket_wrapper/socket_wrapper.c
index c759d35..37799c8 100644
--- a/third_party/socket_wrapper/socket_wrapper.c
+++ b/third_party/socket_wrapper/socket_wrapper.c
@@ -1388,6 +1388,9 @@ static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
 	return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
 }
 
+/* JEMALLOC: This tells socket_wrapper if it should handle syscall() */
+static bool swrap_handle_syscall;
+
 #ifdef HAVE_SYSCALL
 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
 static long int libc_vsyscall(long int sysno, va_list va)
@@ -1396,7 +1399,27 @@ static long int libc_vsyscall(long int sysno, va_list va)
 	long int rc;
 	int i;
 
-	swrap_bind_symbol_all();
+	/*
+	 * JEMALLOC:
+	 *
+	 * This is a workaround to prevent a deadlock in jemalloc calling
+	 * malloc_init() twice. The first allocation call will trigger a
+	 * malloc_init() of jemalloc. The functions calls syscall(SYS_open, ...)
+	 * so it goes to socket or uid wrapper. In this code path we need to
+	 * avoid any allocation calls. This will prevent the deadlock.
+	 *
+	 * We also need to avoid dlopen() as that would trigger the recursion
+	 * into malloc_init(), so we use dlsym(RTLD_NEXT), until we reached
+	 * swrap_constructor() or any real socket call at that time
+	 * swrap_bind_symbol_all() will replace the function pointer again after
+	 * dlopen of libc.
+	 */
+	if (swrap_handle_syscall) {
+		swrap_bind_symbol_all();
+	} else if (swrap.libc.symbols._libc_syscall.obj == NULL) {
+		swrap.libc.symbols._libc_syscall.obj = dlsym(RTLD_NEXT,
+							     "syscall");
+	}
 
 	for (i = 0; i < 8; i++) {
 		args[i] = va_arg(va, long int);
@@ -1517,6 +1540,8 @@ static void __swrap_bind_symbol_all_once(void)
 	swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_valid);
 	swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_va);
 #endif
+
+	swrap_handle_syscall = true;
 }
 
 static void swrap_bind_symbol_all(void)
@@ -8744,6 +8769,21 @@ long int syscall(long int sysno, ...)
 
 	va_start(va, sysno);
 
+	/*
+	 * JEMALLOC:
+	 *
+	 * This is a workaround to prevent a deadlock in jemalloc calling
+	 * malloc_init() twice. The first allocation call will trigger a
+	 * malloc_init() of jemalloc. The functions calls syscall(SYS_open, ...)
+	 * so it goes to socket or uid wrapper. In this code path we need to
+	 * avoid any allocation calls. This will prevent the deadlock.
+	 */
+	if (!swrap_handle_syscall) {
+		rc = libc_vsyscall(sysno, va);
+		va_end(va);
+		return rc;
+	}
+
 	/*
 	 * We should only handle the syscall numbers
 	 * we care about...
@@ -8860,6 +8900,9 @@ void swrap_constructor(void)
 	pthread_atfork(&swrap_thread_prepare,
 		       &swrap_thread_parent,
 		       &swrap_thread_child);
+
+	/* Let socket_wrapper handle syscall() */
+	swrap_handle_syscall = true;
 }
 
 /****************************
diff --git a/third_party/socket_wrapper/wscript b/third_party/socket_wrapper/wscript
index 9d2210d..cdd3493 100644
--- a/third_party/socket_wrapper/wscript
+++ b/third_party/socket_wrapper/wscript
@@ -2,7 +2,7 @@
 
 import os
 
-VERSION = "1.4.2"
+VERSION = "1.4.3"
 
 
 def configure(conf):
@@ -10,6 +10,7 @@ def configure(conf):
         conf.DEFINE('USING_SYSTEM_SOCKET_WRAPPER', 1)
         libsocket_wrapper_so_path = 'libsocket_wrapper.so'
     else:
+        conf.CHECK_HEADERS('gnu/lib-names.h')
 
         if conf.CONFIG_SET("HAVE___THREAD"):
             conf.DEFINE("HAVE_GCC_THREAD_LOCAL_STORAGE", 1)
-- 
cgit v1.2.3