From f446258f0269a62289cca0210157cb8558d0edc3 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 16 May 2023 23:40:42 +0200
Subject: [PATCH] hostip: include easy_lock.h before using
 GLOBAL_INIT_IS_THREADSAFE

Since that header file is the only place that define can be defined.

Reported-by: Marc Deslauriers

Follow-up to 13718030ad4b3209

Closes #11121

Upstream-Status: Backport [https://github.com/curl/curl/commit/f446258f0269a62289cca0210157cb8558d0edc3]
CVE: CVE-2023-28320
Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
---
 lib/easy_lock.h | 109 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/hostip.c    |  10 ++---
 lib/hostip.h    |   9 ----
 3 files changed, 113 insertions(+), 15 deletions(-)
 create mode 100644 lib/easy_lock.h

diff --git a/lib/easy_lock.h b/lib/easy_lock.h
new file mode 100644
index 0000000..6399a39
--- /dev/null
+++ b/lib/easy_lock.h
@@ -0,0 +1,109 @@
+#ifndef HEADER_CURL_EASY_LOCK_H
+#define HEADER_CURL_EASY_LOCK_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#define GLOBAL_INIT_IS_THREADSAFE
+
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+
+#ifdef __MINGW32__
+#ifndef __MINGW64_VERSION_MAJOR
+#if (__MINGW32_MAJOR_VERSION < 5) || \
+    (__MINGW32_MAJOR_VERSION == 5 && __MINGW32_MINOR_VERSION == 0)
+/* mingw >= 5.0.1 defines SRWLOCK, and slightly different from MS define */
+typedef PVOID SRWLOCK, *PSRWLOCK;
+#endif
+#endif
+#ifndef SRWLOCK_INIT
+#define SRWLOCK_INIT NULL
+#endif
+#endif /* __MINGW32__ */
+
+#define curl_simple_lock SRWLOCK
+#define CURL_SIMPLE_LOCK_INIT SRWLOCK_INIT
+
+#define curl_simple_lock_lock(m) AcquireSRWLockExclusive(m)
+#define curl_simple_lock_unlock(m) ReleaseSRWLockExclusive(m)
+
+#elif defined(HAVE_ATOMIC) && defined(HAVE_STDATOMIC_H)
+#include <stdatomic.h>
+#if defined(HAVE_SCHED_YIELD)
+#include <sched.h>
+#endif
+
+#define curl_simple_lock atomic_int
+#define CURL_SIMPLE_LOCK_INIT 0
+
+/* a clang-thing */
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+
+#ifndef __INTEL_COMPILER
+/* The Intel compiler tries to look like GCC *and* clang *and* lies in its
+   __has_builtin() function, so override it. */
+
+/* if GCC on i386/x86_64 or if the built-in is present */
+#if ( (defined(__GNUC__) && !defined(__clang__)) &&     \
+      (defined(__i386__) || defined(__x86_64__))) ||    \
+  __has_builtin(__builtin_ia32_pause)
+#define HAVE_BUILTIN_IA32_PAUSE
+#endif
+
+#endif
+
+static inline void curl_simple_lock_lock(curl_simple_lock *lock)
+{
+  for(;;) {
+    if(!atomic_exchange_explicit(lock, true, memory_order_acquire))
+      break;
+    /* Reduce cache coherency traffic */
+    while(atomic_load_explicit(lock, memory_order_relaxed)) {
+      /* Reduce load (not mandatory) */
+#ifdef HAVE_BUILTIN_IA32_PAUSE
+      __builtin_ia32_pause();
+#elif defined(__aarch64__)
+      __asm__ volatile("yield" ::: "memory");
+#elif defined(HAVE_SCHED_YIELD)
+      sched_yield();
+#endif
+    }
+  }
+}
+
+static inline void curl_simple_lock_unlock(curl_simple_lock *lock)
+{
+  atomic_store_explicit(lock, false, memory_order_release);
+}
+
+#else
+
+#undef  GLOBAL_INIT_IS_THREADSAFE
+
+#endif
+
+#endif /* HEADER_CURL_EASY_LOCK_H */
diff --git a/lib/hostip.c b/lib/hostip.c
index e15c17a..c2e0962 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -72,6 +72,8 @@
 #include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
 #endif

+#include "easy_lock.h"
+
 #if defined(CURLRES_SYNCH) &&                   \
   defined(HAVE_ALARM) &&                        \
   defined(SIGALRM) &&                           \
@@ -81,10 +83,6 @@
 #define USE_ALARM_TIMEOUT
 #endif

-#ifdef USE_ALARM_TIMEOUT
-#include "easy_lock.h"
-#endif
-
 #define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */

 /*
@@ -260,8 +258,8 @@ void Curl_hostcache_prune(struct Curl_easy *data)
 /* Beware this is a global and unique instance. This is used to store the
    return address that we can jump back to from inside a signal handler. This
    is not thread-safe stuff. */
-sigjmp_buf curl_jmpenv;
-curl_simple_lock curl_jmpenv_lock;
+static sigjmp_buf curl_jmpenv;
+static curl_simple_lock curl_jmpenv_lock;
 #endif

 /* lookup address, returns entry if found and not stale */
diff --git a/lib/hostip.h b/lib/hostip.h
index 1db5981..a46bdc6 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -189,15 +189,6 @@ Curl_cache_addr(struct Curl_easy *data, struct Curl_addrinfo *addr,
 #define CURL_INADDR_NONE INADDR_NONE
 #endif

-#ifdef HAVE_SIGSETJMP
-/* Forward-declaration of variable defined in hostip.c. Beware this
- * is a global and unique instance. This is used to store the return
- * address that we can jump back to from inside a signal handler.
- * This is not thread-safe stuff.
- */
-extern sigjmp_buf curl_jmpenv;
-#endif
-
 /*
  * Function provided by the resolver backend to set DNS servers to use.
  */
--
2.25.1

