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