]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
vtls_scache: check reentrancy
authorStefan Eissing <stefan@eissing.org>
Mon, 20 Apr 2026 08:21:43 +0000 (10:21 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 20 Apr 2026 09:22:00 +0000 (11:22 +0200)
Track lock status of session cache, add DEBUGASSERT()s for proper
calling sequences. Add check of lock status.

Use lock status check to prevent reentry of import/export calls.
Deny such calls with CURLE_RECURSIVE_API_CALL.

Closes #21383

lib/easy.c
lib/vtls/vtls_scache.c
lib/vtls/vtls_scache.h

index b2096fb8d3030bceab3975851b814ff0bd1fbc32..a472d6ddc52e0ed613c038cd21e0693dd38a5fcc 100644 (file)
@@ -1339,6 +1339,8 @@ CURLcode curl_easy_ssls_import(CURL *curl, const char *session_key,
   struct Curl_easy *data = curl;
   if(!GOOD_EASY_HANDLE(data))
     return CURLE_BAD_FUNCTION_ARGUMENT;
+  if(Curl_is_in_callback(data) || Curl_ssl_scache_is_locked(data))
+    return CURLE_RECURSIVE_API_CALL;
   return Curl_ssl_session_import(data, session_key,
                                  shmac, shmac_len, sdata, sdata_len);
 #else
@@ -1360,6 +1362,8 @@ CURLcode curl_easy_ssls_export(CURL *curl,
   struct Curl_easy *data = curl;
   if(!GOOD_EASY_HANDLE(data))
     return CURLE_BAD_FUNCTION_ARGUMENT;
+  if(Curl_is_in_callback(data) || Curl_ssl_scache_is_locked(data))
+    return CURLE_RECURSIVE_API_CALL;
   return Curl_ssl_session_export(data, export_fn, userptr);
 #else
   (void)curl;
index 505b4fe5ecad5691868eadbed0b8c3970d8c3059..59fa256bc31dc8106dd18abbad8adc10e10028be 100644 (file)
@@ -301,6 +301,7 @@ struct Curl_ssl_scache {
   size_t peer_count;
   int default_lifetime_secs;
   long age;
+  BIT(is_locked);
 };
 
 static struct Curl_ssl_scache *cf_ssl_scache_get(struct Curl_easy *data)
@@ -583,15 +584,26 @@ bool Curl_ssl_scache_use(struct Curl_cfilter *cf, struct Curl_easy *data)
 /* Lock shared SSL session data */
 void Curl_ssl_scache_lock(struct Curl_easy *data)
 {
-  if(CURL_SHARE_ssl_scache(data))
-    Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+  struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
+  if(scache) {
+    if(CURL_SHARE_ssl_scache(data))
+      Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION,
+                      CURL_LOCK_ACCESS_SINGLE);
+    DEBUGASSERT(!scache->is_locked);
+    scache->is_locked = TRUE;
+  }
 }
 
 /* Unlock shared SSL session data */
 void Curl_ssl_scache_unlock(struct Curl_easy *data)
 {
-  if(CURL_SHARE_ssl_scache(data))
-    Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+  struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
+  if(scache) {
+    DEBUGASSERT(scache->is_locked);
+    scache->is_locked = FALSE;
+    if(CURL_SHARE_ssl_scache(data))
+      Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+  }
 }
 
 static bool cf_ssl_scache_match_auth(struct Curl_ssl_scache_peer *peer,
@@ -1000,6 +1012,12 @@ void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf,
 
 #define CURL_SSL_TICKET_MAX   (16 * 1024)
 
+bool Curl_ssl_scache_is_locked(struct Curl_easy *data)
+{
+  struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
+  return scache && scache->is_locked;
+}
+
 static CURLcode cf_ssl_scache_peer_set_hmac(struct Curl_ssl_scache_peer *peer)
 {
   CURLcode result;
@@ -1082,7 +1100,6 @@ CURLcode Curl_ssl_session_import(struct Curl_easy *data,
   struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
   struct Curl_ssl_scache_peer *peer = NULL;
   struct Curl_ssl_session *s = NULL;
-  bool locked = FALSE;
   CURLcode result;
 
   if(!scache) {
@@ -1099,7 +1116,6 @@ CURLcode Curl_ssl_session_import(struct Curl_easy *data,
     goto out;
 
   Curl_ssl_scache_lock(data);
-  locked = TRUE;
 
   if(ssl_peer_key) {
     result = cf_ssl_add_peer(data, scache, ssl_peer_key, NULL, &peer);
@@ -1140,7 +1156,7 @@ CURLcode Curl_ssl_session_import(struct Curl_easy *data,
   }
 
 out:
-  if(locked)
+  if(scache && scache->is_locked)
     Curl_ssl_scache_unlock(data);
   Curl_ssl_session_destroy(s);
   return result;
@@ -1163,8 +1179,6 @@ CURLcode Curl_ssl_session_export(struct Curl_easy *data,
 
   if(!export_fn)
     return CURLE_BAD_FUNCTION_ARGUMENT;
-  if(!scache)
-    return CURLE_OK;
 
   Curl_ssl_scache_lock(data);
 
index 916e4b505b7ea1d3b76da435ce2e7da0d94103ea..181c2ec333c71d5355bb98d4e98b1b0f30d037fd 100644 (file)
@@ -199,6 +199,8 @@ void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf,
 
 #ifdef USE_SSLS_EXPORT
 
+bool Curl_ssl_scache_is_locked(struct Curl_easy *data);
+
 CURLcode Curl_ssl_session_import(struct Curl_easy *data,
                                  const char *ssl_peer_key,
                                  const unsigned char *shmac, size_t shmac_len,