import UBI nginx-1.24.0-7.module+el9.8.0+24502+c9b9ab67.3

This commit is contained in:
AlmaLinux RelEng Bot 2026-07-08 05:27:31 -04:00
parent f29d67fe20
commit f5fd2acbae
3 changed files with 323 additions and 60 deletions

View File

@ -1,4 +1,4 @@
From ccb278d26ab1df16b42cf092b793918fcb056a2a Mon Sep 17 00:00:00 2001
From 7b7b03f5ad073bce0ef66431302ec4ef64ef43b3 Mon Sep 17 00:00:00 2001
From: Maxim Dounin <mdounin@mdounin.ru>
Date: Fri, 24 May 2024 00:20:01 +0300
Subject: [PATCH] Added max_headers directive.
@ -11,73 +11,219 @@ might be beneficial to better protect backend servers.
Requested by Maksim Yevmenkin.
The original patch was modified so that the header count and the limit are
stored in a separate module, ngx_http_header_count_module, instead of the
core module. This allows to avoid changing the size of existing structures
and thus avoid potential ABI breakage and keep all the 3rd party modules
compatible with the new version of nginx without recompilation.
Signed-off-by: Elijah Zupancic <e.zupancic@f5.com>
Origin: <https://freenginx.org/hg/nginx/rev/199dc0d6b05be814b5c811876c20af58cd361fea>
---
src/http/ngx_http_core_module.c | 10 ++++++++++
src/http/ngx_http_core_module.h | 2 ++
src/http/ngx_http_request.c | 9 +++++++++
src/http/ngx_http_request.h | 1 +
src/http/v2/ngx_http_v2.c | 9 +++++++++
5 files changed, 31 insertions(+)
auto/modules | 1 +
src/http/ngx_http_core_module.c | 73 +++++++++++++++++++++++++++++++
src/http/ngx_http_header_count.hh | 14 ++++++
src/http/ngx_http_request.c | 24 ++++++++++
src/http/v2/ngx_http_v2.c | 14 ++++++
5 files changed, 126 insertions(+)
create mode 100644 src/http/ngx_http_header_count.hh
diff --git a/auto/modules b/auto/modules
index 94867bf..2b78ada 100644
--- a/auto/modules
+++ b/auto/modules
@@ -67,6 +67,7 @@ if [ $HTTP = YES ]; then
ngx_module_name="ngx_http_module \
ngx_http_core_module \
ngx_http_log_module \
+ ngx_http_header_count_module \
ngx_http_upstream_module"
ngx_module_incs="src/http src/http/modules"
ngx_module_deps="src/http/ngx_http.h \
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 2140e06..b1872bc 100644
index 2140e06..6d386bb 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -252,6 +252,13 @@ static ngx_command_t ngx_http_core_commands[] = {
offsetof(ngx_http_core_srv_conf_t, large_client_header_buffers),
NULL },
@@ -8,6 +8,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
+#include <ngx_http_header_count.hh>
typedef struct {
@@ -39,6 +40,10 @@ static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
+static void *ngx_http_header_count_create_srv_conf(ngx_conf_t *cf);
+static char *ngx_http_header_count_merge_srv_conf(ngx_conf_t *cf,
+ void *parent, void *child);
+
static char *ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
void *dummy);
static char *ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd,
@@ -812,6 +817,48 @@ ngx_module_t ngx_http_core_module = {
NGX_MODULE_V1_PADDING
};
+static ngx_command_t ngx_http_header_count_commands[] = {
+
+ { ngx_string("max_headers"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_num_slot,
+ NGX_HTTP_SRV_CONF_OFFSET,
+ offsetof(ngx_http_core_srv_conf_t, max_headers),
+ offsetof(ngx_http_header_count_conf_t, max_headers),
+ NULL },
+
{ ngx_string("ignore_invalid_headers"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -3459,6 +3466,7 @@ ngx_http_core_create_srv_conf(ngx_conf_t *cf)
cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
+ cscf->max_headers = NGX_CONF_UNSET_UINT;
cscf->ignore_invalid_headers = NGX_CONF_UNSET;
cscf->merge_slashes = NGX_CONF_UNSET;
cscf->underscores_in_headers = NGX_CONF_UNSET;
@@ -3500,6 +3508,8 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
+ ngx_null_command
+};
+
+static ngx_http_module_t ngx_http_header_count_module_ctx = {
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ ngx_http_header_count_create_srv_conf, /* create server configuration */
+ ngx_http_header_count_merge_srv_conf, /* merge server configuration */
+
+ NULL, /* create location configuration */
+ NULL /* merge location configuration */
+};
+
+
+ngx_module_t ngx_http_header_count_module = {
+ NGX_MODULE_V1,
+ &ngx_http_header_count_module_ctx, /* module context */
+ ngx_http_header_count_commands, /* module directives */
+ NGX_HTTP_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
+};
+
ngx_str_t ngx_http_core_get_method = { 3, (u_char *) "GET" };
@@ -3652,6 +3699,32 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
}
+static void *
+ngx_http_header_count_create_srv_conf(ngx_conf_t *cf)
+{
+ ngx_http_header_count_conf_t *hccf;
+
+ hccf = ngx_pcalloc(cf->pool, sizeof(ngx_http_header_count_conf_t));
+ if (hccf == NULL) {
+ return NULL;
+ }
+
+ hccf->max_headers = NGX_CONF_UNSET_UINT;
+ return hccf;
+}
+
+static char *
+ngx_http_header_count_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+ ngx_http_header_count_conf_t *prev = parent;
+ ngx_http_header_count_conf_t *conf = child;
+
+ ngx_conf_merge_uint_value(conf->max_headers, prev->max_headers, 1000);
+
ngx_conf_merge_value(conf->ignore_invalid_headers,
prev->ignore_invalid_headers, 1);
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index e41bc68..821736f 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -196,6 +196,8 @@ typedef struct {
ngx_msec_t client_header_timeout;
+ ngx_uint_t max_headers;
+ return NGX_CONF_OK;
+}
+
ngx_flag_t ignore_invalid_headers;
ngx_flag_t merge_slashes;
ngx_flag_t underscores_in_headers;
+
static ngx_str_t ngx_http_core_text_html_type = ngx_string("text/html");
static ngx_str_t ngx_http_core_image_gif_type = ngx_string("image/gif");
static ngx_str_t ngx_http_core_image_jpeg_type = ngx_string("image/jpeg");
diff --git a/src/http/ngx_http_header_count.hh b/src/http/ngx_http_header_count.hh
new file mode 100644
index 0000000..6a8b86d
--- /dev/null
+++ b/src/http/ngx_http_header_count.hh
@@ -0,0 +1,14 @@
+#ifndef _NGX_HTTP_HEADER_COUNT_H_INCLUDED_
+#define _NGX_HTTP_HEADER_COUNT_H_INCLUDED_
+
+typedef struct {
+ ngx_uint_t count;
+} ngx_http_header_count_t;
+
+typedef struct {
+ ngx_uint_t max_headers;
+} ngx_http_header_count_conf_t;
+
+extern ngx_module_t ngx_http_header_count_module;
+
+#endif /* _NGX_HTTP_HEADER_COUNT_H_INCLUDED_ */
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 5e0340b..720f93e 100644
index 5e0340b..85571a0 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1433,6 +1433,15 @@ ngx_http_process_request_headers(ngx_event_t *rev)
@@ -8,6 +8,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
+#include <ngx_http_header_count.hh>
static void ngx_http_wait_request_handler(ngx_event_t *ev);
@@ -543,6 +544,7 @@ ngx_http_alloc_request(ngx_connection_t *c)
ngx_http_connection_t *hc;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_main_conf_t *cmcf;
+ ngx_http_header_count_t *hc_ctx;
hc = c->data;
@@ -604,6 +606,13 @@ ngx_http_alloc_request(ngx_connection_t *c)
return NULL;
}
+ hc_ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_header_count_t));
+ if (hc_ctx == NULL) {
+ ngx_destroy_pool(r->pool);
+ return NULL;
+ }
+ ngx_http_set_ctx(r, hc_ctx, ngx_http_header_count_module);
+
#if (NGX_HTTP_SSL)
if (c->ssl && !c->ssl->sendfile) {
r->main_filter_need_in_memory = 1;
@@ -1343,6 +1352,8 @@ ngx_http_process_request_headers(ngx_event_t *rev)
ngx_http_request_t *r;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_main_conf_t *cmcf;
+ ngx_http_header_count_conf_t *hccf;
+ ngx_http_header_count_t *hc_ctx;
c = rev->data;
r = c->data;
@@ -1416,6 +1427,10 @@ ngx_http_process_request_headers(ngx_event_t *rev)
rc = ngx_http_parse_header_line(r, r->header_in,
cscf->underscores_in_headers);
+
+ hccf = ngx_http_get_module_srv_conf(r, ngx_http_header_count_module);
+ hc_ctx = ngx_http_get_module_ctx(r, ngx_http_header_count_module);
+
if (rc == NGX_OK) {
r->request_length += r->header_in->pos - r->header_name_start;
@@ -1433,6 +1448,15 @@ ngx_http_process_request_headers(ngx_event_t *rev)
/* a header line has been parsed successfully */
+ if (r->headers_in.count++ >= cscf->max_headers) {
+ if (hc_ctx->count++ >= hccf->max_headers) {
+ r->lingering_close = 1;
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent too many header lines");
@ -89,29 +235,36 @@ index 5e0340b..720f93e 100644
h = ngx_list_push(&r->headers_in.headers);
if (h == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 8c9eed2..01ac4f9 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -181,6 +181,7 @@ typedef struct {
typedef struct {
ngx_list_t headers;
+ ngx_uint_t count;
ngx_table_elt_t *host;
ngx_table_elt_t *connection;
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
index 1116e56..05500a4 100644
index 1116e56..29a534c 100644
--- a/src/http/v2/ngx_http_v2.c
+++ b/src/http/v2/ngx_http_v2.c
@@ -1856,6 +1856,15 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos,
@@ -9,6 +9,7 @@
#include <ngx_core.h>
#include <ngx_http.h>
#include <ngx_http_v2_module.h>
+#include <ngx_http_header_count.hh>
typedef struct {
@@ -1751,6 +1752,8 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos,
ngx_http_v2_header_t *header;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_main_conf_t *cmcf;
+ ngx_http_header_count_conf_t *hccf;
+ ngx_http_header_count_t *hc_ctx;
static ngx_str_t cookie = ngx_string("cookie");
@@ -1856,6 +1859,17 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos,
}
} else {
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+ hccf = ngx_http_get_module_srv_conf(r, ngx_http_header_count_module);
+ hc_ctx = ngx_http_get_module_ctx(r, ngx_http_header_count_module);
+
+ if (r->headers_in.count++ >= cscf->max_headers) {
+ if (hc_ctx->count++ >= hccf->max_headers) {
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "client sent too many header lines");
+ ngx_http_finalize_request(r, NGX_HTTP_REQUEST_HEADER_TOO_LARGE);

View File

@ -0,0 +1,99 @@
From 83cc0876c6d8f880b7c943e39d922e2286c94a41 Mon Sep 17 00:00:00 2001
From: Roman Arutyunyan <arut@nginx.com>
Date: Tue, 2 Jun 2026 19:37:17 +0400
Subject: [PATCH] Upstream: limit header length for HTTP/2 and gRPC
The change applies the HTTP/2 header length limits to avoid buffer
overflow. See 58a7bc3406ac for details.
Reported by Mufeed VH of Winfunc Research.
---
src/http/modules/ngx_http_grpc_module.c | 44 +++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c
index 9f13089..bb636f3 100644
--- a/src/http/modules/ngx_http_grpc_module.c
+++ b/src/http/modules/ngx_http_grpc_module.c
@@ -740,6 +740,12 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
tmp_len = 0;
} else {
+ if (r->method_name.len > NGX_HTTP_V2_MAX_FIELD) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "too long http2 method: \"%V\"", &r->method_name);
+ return NGX_ERROR;
+ }
+
len += 1 + NGX_HTTP_V2_INT_OCTETS + r->method_name.len;
tmp_len = r->method_name.len;
}
@@ -760,6 +766,12 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
uri_len = r->uri.len + escape + sizeof("?") - 1 + r->args.len;
}
+ if (uri_len > NGX_HTTP_V2_MAX_FIELD) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "too long http2 URI");
+ return NGX_ERROR;
+ }
+
len += 1 + NGX_HTTP_V2_INT_OCTETS + uri_len;
if (tmp_len < uri_len) {
@@ -769,6 +781,12 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
/* :authority header */
if (!glcf->host_set) {
+ if (ctx->host.len > NGX_HTTP_V2_MAX_FIELD) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "too long http2 host: \"%V\"", &ctx->host);
+ return NGX_ERROR;
+ }
+
len += 1 + NGX_HTTP_V2_INT_OCTETS + ctx->host.len;
if (tmp_len < ctx->host.len) {
@@ -799,6 +817,18 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
continue;
}
+ if (key_len > NGX_HTTP_V2_MAX_FIELD) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "too long http2 header name");
+ return NGX_ERROR;
+ }
+
+ if (val_len > NGX_HTTP_V2_MAX_FIELD) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "too long http2 header value");
+ return NGX_ERROR;
+ }
+
len += 1 + NGX_HTTP_V2_INT_OCTETS + key_len
+ NGX_HTTP_V2_INT_OCTETS + val_len;
@@ -833,6 +863,20 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
continue;
}
+ if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "too long http2 header name: \"%V\"",
+ &header[i].key);
+ return NGX_ERROR;
+ }
+
+ if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "too long http2 header value: \"%V: %V\"",
+ &header[i].key, &header[i].value);
+ return NGX_ERROR;
+ }
+
len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len
+ NGX_HTTP_V2_INT_OCTETS + header[i].value.len;
--
2.44.0

View File

@ -56,7 +56,7 @@
Name: nginx
Epoch: 1
Version: 1.24.0
Release: 7%{?dist}.2
Release: 7%{?dist}.3
Summary: A high performance web server and reverse proxy server
# BSD License (two clause)
@ -156,6 +156,10 @@ Patch17: 0019-Rewrite-fix-buffer-overflow-with-overlapping-capture.pat
# upstream patch - https://github.com/nginx/nginx/commit/365694160a85229a7cb006738de9260d49ff5fa2
Patch18: 0020-Added-max_headers-directive.patch
# https://redhat.atlassian.net/browse/RHEL-188418
# upstream patch - https://github.com/nginx/nginx/commit/26d824ec3a2f819300edce0ab3b055751c9843ff.patch
Patch19: 0021-Upstream-limit-header-length-for-HTTP-2-and-gRPC.patch
BuildRequires: make
BuildRequires: gcc
BuildRequires: gnupg2
@ -668,6 +672,13 @@ fi
%changelog
* Tue Jul 07 2026 Luboš Uhliarik <luhliari@redhat.com> - 1:1.24.0-7.3
- Resolves: RHEL-191773 - nginx: "HTTP/2 bomb" nginx fix breaks module ABI
causing crashes
- Resolves: RHEL-188413 - nginx: NGINX: Arbitrary code execution or.
Denial of Service via heap-based buffer overflow with crafted HTTP/2
headers (CVE-2026-42055)
* Wed Jun 10 2026 Luboš Uhliarik <luhliari@redhat.com> - 1:1.24.0-7.2
- Resolves: RHEL-178681 - nginx:1.24/nginx: code execution and denial
of service (CVE-2026-9256)