public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/curl] f44: Resolves: CVE-2026-10536 - HTTP/2 stream-dependency tree UAF
@ 2026-09-08 13:41 Jan Macku
  0 siblings, 0 replies; only message in thread
From: Jan Macku @ 2026-09-08 13:41 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/curl
Branch : f44
Commit : 252bf4722c528c3e230bef5f37e6603871018a30
Author : Jan Macku <jamacku@redhat.com>
Date   : 2026-08-27T15:40:52+02:00
Stats  : +382/-1 in 2 file(s)
URL    : https://src.fedoraproject.org/rpms/curl/c/252bf4722c528c3e230bef5f37e6603871018a30?branch=f44

Log:
Resolves: CVE-2026-10536 - HTTP/2 stream-dependency tree UAF

---
diff --git a/0022-curl-8.18.0-CVE-2026-10536.patch b/0022-curl-8.18.0-CVE-2026-10536.patch
new file mode 100644
index 0000000..c04e728
--- /dev/null
+++ b/0022-curl-8.18.0-CVE-2026-10536.patch
@@ -0,0 +1,375 @@
+From a83cc30ca7d11833a34bb3ca7366dbf762e189f6 Mon Sep 17 00:00:00 2001
+From: Stefan Eissing <stefan@eissing.org>
+Date: Fri, 22 May 2026 09:11:41 +0200
+Subject: [PATCH] http2: remove stream dependency tracking
+
+The HTTP/2 feature is deprecated, few servers implement it and our
+implementation is complicated by its state management. Make the two
+CURLOPT_* involved a nop and deprecate them.
+
+Closes #21723
+
+(cherry picked from commit bfbff7852f050232edd3e5ca5c6bf2021c340f5a)
+---
+ docs/libcurl/curl_easy_setopt.md              |  5 +-
+ docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.md   |  8 ++
+ docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.md |  8 ++
+ docs/libcurl/symbols-in-versions              |  4 +-
+ include/curl/curl.h                           |  6 +-
+ lib/http2.c                                   | 18 ++--
+ lib/setopt.c                                  |  9 +-
+ lib/url.c                                     | 98 -------------------
+ lib/url.h                                     |  8 --
+ lib/urldata.h                                 | 15 ---
+ 10 files changed, 34 insertions(+), 145 deletions(-)
+
+diff --git a/docs/libcurl/curl_easy_setopt.md b/docs/libcurl/curl_easy_setopt.md
+index 771442b185..71ea9a5251 100644
+--- a/docs/libcurl/curl_easy_setopt.md
++++ b/docs/libcurl/curl_easy_setopt.md
+@@ -1162,11 +1162,12 @@ Redirect stderr to another stream. See CURLOPT_STDERR(3)
+ 
+ ## CURLOPT_STREAM_DEPENDS
+ 
+-This HTTP/2 stream depends on another. See CURLOPT_STREAM_DEPENDS(3)
++**Deprecated option** This HTTP/2 stream depends on another. See
++CURLOPT_STREAM_DEPENDS(3)
+ 
+ ## CURLOPT_STREAM_DEPENDS_E
+ 
+-This HTTP/2 stream depends on another exclusively. See
++**Deprecated option** This HTTP/2 stream depends on another exclusively. See
+ CURLOPT_STREAM_DEPENDS_E(3)
+ 
+ ## CURLOPT_STREAM_WEIGHT
+diff --git a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.md b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.md
+index 5e3e177dce..e0e8ef0c53 100644
+--- a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.md
++++ b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.md
+@@ -44,6 +44,10 @@ an error. It must be another easy handle, and it also needs to be a handle of
+ a transfer that is about to be sent over the same HTTP/2 connection for this
+ option to have an actual effect.
+ 
++Since version 8.21.0 setting this option no longer has an effect. HTTP/2
++stream dependencies were introduced in RFC 7540 and then later deprecated
++in RFC 9113.
++
+ # DEFAULT
+ 
+ NULL
+@@ -69,6 +73,10 @@ int main(void)
+ }
+ ~~~
+ 
++# DEPRECATED
++
++Deprecated since 8.21.0.
++
+ # %AVAILABILITY%
+ 
+ # RETURN VALUE
+diff --git a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.md b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.md
+index fe95ae8d71..fe8f97f950 100644
+--- a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.md
++++ b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.md
+@@ -47,6 +47,10 @@ an error. It must be another easy handle, and it also needs to be a handle of
+ a transfer that is about to be sent over the same HTTP/2 connection for this
+ option to have an actual effect.
+ 
++Since version 8.21.0 setting this option no longer has an effect. HTTP/2
++stream dependencies were introduced in RFC 7540 and then later deprecated
++in RFC 9113.
++
+ # DEFAULT
+ 
+ NULL
+@@ -72,6 +76,10 @@ int main(void)
+ }
+ ~~~
+ 
++# DEPRECATED
++
++Deprecated since 8.21.0.
++
+ # %AVAILABILITY%
+ 
+ # RETURN VALUE
+diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
+index e0e0a8e63a..2a045a82ed 100644
+--- a/docs/libcurl/symbols-in-versions
++++ b/docs/libcurl/symbols-in-versions
+@@ -878,8 +878,8 @@ CURLOPT_SSLKEYPASSWD            7.9.3         7.17.0
+ CURLOPT_SSLKEYTYPE              7.9.3
+ CURLOPT_SSLVERSION              7.1
+ CURLOPT_STDERR                  7.1
+-CURLOPT_STREAM_DEPENDS          7.46.0
+-CURLOPT_STREAM_DEPENDS_E        7.46.0
++CURLOPT_STREAM_DEPENDS          7.46.0        8.21.0
++CURLOPT_STREAM_DEPENDS_E        7.46.0        8.21.0
+ CURLOPT_STREAM_WEIGHT           7.46.0
+ CURLOPT_SUPPRESS_CONNECT_HEADERS 7.54.0
+ CURLOPT_TCP_FASTOPEN            7.49.0
+diff --git a/include/curl/curl.h b/include/curl/curl.h
+index e755f098f2..d9ce7307e2 100644
+--- a/include/curl/curl.h
++++ b/include/curl/curl.h
+@@ -1980,10 +1980,12 @@ typedef enum {
+   CURLOPT(CURLOPT_STREAM_WEIGHT, CURLOPTTYPE_LONG, 239),
+ 
+   /* Set stream dependency on another curl handle */
+-  CURLOPT(CURLOPT_STREAM_DEPENDS, CURLOPTTYPE_OBJECTPOINT, 240),
++  CURLOPTDEPRECATED(CURLOPT_STREAM_DEPENDS, CURLOPTTYPE_OBJECTPOINT, 240,
++                    8.21.0, "Has no function"),
+ 
+   /* Set E-xclusive stream dependency on another curl handle */
+-  CURLOPT(CURLOPT_STREAM_DEPENDS_E, CURLOPTTYPE_OBJECTPOINT, 241),
++  CURLOPTDEPRECATED(CURLOPT_STREAM_DEPENDS_E, CURLOPTTYPE_OBJECTPOINT, 241,
++                    8.21.0, "Has no function"),
+ 
+   /* Do not send any tftp option requests to the server */
+   CURLOPT(CURLOPT_TFTP_NO_OPTIONS, CURLOPTTYPE_LONG, 242),
+diff --git a/lib/http2.c b/lib/http2.c
+index a8b8d5c52f..c3177b9294 100644
+--- a/lib/http2.c
++++ b/lib/http2.c
+@@ -1933,16 +1933,12 @@ static int sweight_in_effect(const struct Curl_easy *data)
+  * struct.
+  */
+ 
+-static void h2_pri_spec(struct cf_h2_ctx *ctx,
+-                        struct Curl_easy *data,
++static void h2_pri_spec(struct Curl_easy *data,
+                         nghttp2_priority_spec *pri_spec)
+ {
+   struct Curl_data_priority *prio = &data->set.priority;
+-  struct h2_stream_ctx *depstream = H2_STREAM_CTX(ctx, prio->parent);
+-  int32_t depstream_id = depstream ? depstream->id : 0;
+-  nghttp2_priority_spec_init(pri_spec, depstream_id,
+-                             sweight_wanted(data),
+-                             data->set.priority.exclusive);
++  nghttp2_priority_spec_init(pri_spec, 0,
++                             sweight_wanted(data), FALSE);
+   data->state.priority = *prio;
+ }
+ 
+@@ -1960,13 +1956,11 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
+   int rv = 0;
+ 
+   if(stream && stream->id > 0 &&
+-     ((sweight_wanted(data) != sweight_in_effect(data)) ||
+-      (data->set.priority.exclusive != data->state.priority.exclusive) ||
+-      (data->set.priority.parent != data->state.priority.parent))) {
++     (sweight_wanted(data) != sweight_in_effect(data))) {
+     /* send new weight and/or dependency */
+     nghttp2_priority_spec pri_spec;
+ 
+-    h2_pri_spec(ctx, data, &pri_spec);
++    h2_pri_spec(data, &pri_spec);
+     CURL_TRC_CF(data, cf, "[%d] Queuing PRIORITY", stream->id);
+     DEBUGASSERT(stream->id != -1);
+     rv = nghttp2_submit_priority(ctx->h2, NGHTTP2_FLAG_NONE,
+@@ -2274,7 +2268,7 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream,
+     goto out;
+   }
+ 
+-  h2_pri_spec(ctx, data, &pri_spec);
++  h2_pri_spec(data, &pri_spec);
+   if(!nghttp2_session_check_request_allowed(ctx->h2))
+     CURL_TRC_CF(data, cf, "send request NOT allowed (via nghttp2)");
+ 
+diff --git a/lib/setopt.c b/lib/setopt.c
+index a74ca5e8f3..355a59c0a1 100644
+--- a/lib/setopt.c
++++ b/lib/setopt.c
+@@ -1508,13 +1508,10 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
+ 
+ #ifdef USE_HTTP2
+   case CURLOPT_STREAM_DEPENDS:
+-  case CURLOPT_STREAM_DEPENDS_E: {
+-    struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
+-    if(!dep || GOOD_EASY_HANDLE(dep))
+-      return Curl_data_priority_add_child(dep, data,
+-                                          option == CURLOPT_STREAM_DEPENDS_E);
++  case CURLOPT_STREAM_DEPENDS_E:
++    /* not doing stream dependencies any longer, but accept options
++     * for backward compatibility */
+     break;
+-  }
+ #endif
+ 
+   default:
+diff --git a/lib/url.c b/lib/url.c
+index fefc1a0518..900b0f7352 100644
+--- a/lib/url.c
++++ b/lib/url.c
+@@ -120,12 +120,6 @@
+ #include "smtp.h"
+ #include "ws.h"
+ 
+-#ifdef USE_NGHTTP2
+-static void data_priority_cleanup(struct Curl_easy *data);
+-#else
+-#define data_priority_cleanup(x)
+-#endif
+-
+ /* Some parts of the code (e.g. chunked encoding) assume this buffer has at
+  * more than just a few bytes to play with. Do not let it become too small or
+  * bad things will happen.
+@@ -282,8 +276,6 @@ CURLcode Curl_close(struct Curl_easy **datap)
+   Curl_safefree(data->info.contenttype);
+   Curl_safefree(data->info.wouldredirect);
+ 
+-  data_priority_cleanup(data);
+-
+   /* No longer a dirty share, if it exists */
+   if(data->share) {
+     Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+@@ -3970,96 +3962,6 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
+ 
+ #if defined(USE_HTTP2) || defined(USE_HTTP3)
+ 
+-#ifdef USE_NGHTTP2
+-
+-static void priority_remove_child(struct Curl_easy *parent,
+-                                  struct Curl_easy *child)
+-{
+-  struct Curl_data_prio_node **pnext = &parent->set.priority.children;
+-  struct Curl_data_prio_node *pnode = parent->set.priority.children;
+-
+-  DEBUGASSERT(child->set.priority.parent == parent);
+-  while(pnode && pnode->data != child) {
+-    pnext = &pnode->next;
+-    pnode = pnode->next;
+-  }
+-
+-  DEBUGASSERT(pnode);
+-  if(pnode) {
+-    *pnext = pnode->next;
+-    curlx_free(pnode);
+-  }
+-
+-  child->set.priority.parent = 0;
+-  child->set.priority.exclusive = FALSE;
+-}
+-
+-CURLcode Curl_data_priority_add_child(struct Curl_easy *parent,
+-                                      struct Curl_easy *child,
+-                                      bool exclusive)
+-{
+-  if(child->set.priority.parent) {
+-    priority_remove_child(child->set.priority.parent, child);
+-  }
+-
+-  if(parent) {
+-    struct Curl_data_prio_node **tail;
+-    struct Curl_data_prio_node *pnode;
+-
+-    pnode = curlx_calloc(1, sizeof(*pnode));
+-    if(!pnode)
+-      return CURLE_OUT_OF_MEMORY;
+-    pnode->data = child;
+-
+-    if(parent->set.priority.children && exclusive) {
+-      /* exclusive: move all existing children underneath the new child */
+-      struct Curl_data_prio_node *node = parent->set.priority.children;
+-      while(node) {
+-        node->data->set.priority.parent = child;
+-        node = node->next;
+-      }
+-
+-      tail = &child->set.priority.children;
+-      while(*tail)
+-        tail = &(*tail)->next;
+-
+-      DEBUGASSERT(!*tail);
+-      *tail = parent->set.priority.children;
+-      parent->set.priority.children = 0;
+-    }
+-
+-    tail = &parent->set.priority.children;
+-    while(*tail) {
+-      (*tail)->data->set.priority.exclusive = FALSE;
+-      tail = &(*tail)->next;
+-    }
+-
+-    DEBUGASSERT(!*tail);
+-    *tail = pnode;
+-  }
+-
+-  child->set.priority.parent = parent;
+-  child->set.priority.exclusive = exclusive;
+-  return CURLE_OK;
+-}
+-
+-#endif /* USE_NGHTTP2 */
+-
+-#ifdef USE_NGHTTP2
+-static void data_priority_cleanup(struct Curl_easy *data)
+-{
+-  while(data->set.priority.children) {
+-    struct Curl_easy *tmp = data->set.priority.children->data;
+-    priority_remove_child(data, tmp);
+-    if(data->set.priority.parent)
+-      Curl_data_priority_add_child(data->set.priority.parent, tmp, FALSE);
+-  }
+-
+-  if(data->set.priority.parent)
+-    priority_remove_child(data->set.priority.parent, data);
+-}
+-#endif
+-
+ void Curl_data_priority_clear_state(struct Curl_easy *data)
+ {
+   memset(&data->state.priority, 0, sizeof(data->state.priority));
+diff --git a/lib/url.h b/lib/url.h
+index 3a8d57c377..ddac784e75 100644
+--- a/lib/url.h
++++ b/lib/url.h
+@@ -111,12 +111,4 @@ void Curl_data_priority_clear_state(struct Curl_easy *data);
+ #define Curl_data_priority_clear_state(x)
+ #endif /* USE_HTTP2 || USE_HTTP3 */
+ 
+-#ifdef USE_NGHTTP2
+-CURLcode Curl_data_priority_add_child(struct Curl_easy *parent,
+-                                      struct Curl_easy *child,
+-                                      bool exclusive);
+-#else
+-#define Curl_data_priority_add_child(x, y, z) CURLE_NOT_BUILT_IN
+-#endif
+-
+ #endif /* HEADER_CURL_URL_H */
+diff --git a/lib/urldata.h b/lib/urldata.h
+index 1de8c4bfb1..7e36cc2336 100644
+--- a/lib/urldata.h
++++ b/lib/urldata.h
+@@ -864,27 +864,12 @@ struct auth {
+                    should be RFC compliant */
+ };
+ 
+-#ifdef USE_NGHTTP2
+-struct Curl_data_prio_node {
+-  struct Curl_data_prio_node *next;
+-  struct Curl_easy *data;
+-};
+-#endif
+-
+ /**
+  * Priority information for an easy handle in relation to others
+  * on the same connection.
+  */
+ struct Curl_data_priority {
+-#ifdef USE_NGHTTP2
+-  /* tree like dependencies only implemented in nghttp2 */
+-  struct Curl_easy *parent;
+-  struct Curl_data_prio_node *children;
+-#endif
+   int weight;
+-#ifdef USE_NGHTTP2
+-  BIT(exclusive);
+-#endif
+ };
+ 
+ /* Timers */
+-- 
+2.55.0
+

diff --git a/curl.spec b/curl.spec
index 2dff466..196f505 100644
--- a/curl.spec
+++ b/curl.spec
@@ -12,7 +12,7 @@
 Summary: A utility for getting files from remote servers (FTP, HTTP, and others)
 Name: curl
 Version: 8.18.0
-Release: 9%{?dist}
+Release: 10%{?dist}
 License: curl
 Source0: https://curl.se/download/%{name}-%{version_no_tilde}.tar.xz
 Source1: https://curl.se/download/%{name}-%{version_no_tilde}.tar.xz.asc
@@ -87,6 +87,9 @@ Patch020: 0020-curl-8.18.0-CVE-2026-9545.patch
 # Fix UAF after pause in socket callback (CVE-2026-9080)
 Patch021: 0021-curl-8.18.0-CVE-2026-9080.patch
 
+# Fix HTTP/2 stream-dependency tree UAF (CVE-2026-10536)
+Patch022: 0022-curl-8.18.0-CVE-2026-10536.patch
+
 # patch making libcurl multilib ready
 Patch101: 0101-curl-7.32.0-multilib.patch
 
@@ -513,6 +516,9 @@ rm -f ${RPM_BUILD_ROOT}%{_mandir}/man1/wcurl.1*
 %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal
 
 %changelog
+* Tue Sep 08 2026 Jan Macku <jamacku@redhat.com> - 8.18.0-10
+- Fix HTTP/2 stream-dependency tree UAF (CVE-2026-10536)
+
 * Mon Aug 24 2026 Jan Macku <jamacku@redhat.com> - 8.18.0-9
 - Fix QUIC zero-length UDP datagrams busy-loop (CVE-2026-11352)
 - Fix WS Auto-PONG memory exhaustion (CVE-2026-11586)

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-08 13:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-08 13:41 [rpms/curl] f44: Resolves: CVE-2026-10536 - HTTP/2 stream-dependency tree UAF Jan Macku

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox