Limit conn: fixed counter leak on memory allocation errors.

Previously, if ngx_pool_cleanup_add() failed, already incremented
connection counter was left as is, eventually resulting in unexpected
connection limiting or shared memory exhaustion.  Fix is to decrement
the counter by calling the cleanup handler with data on stack.

Signed-off-by: Elijah Zupancic <e.zupancic@f5.com>
Origin: <https://freenginx.org/hg/nginx/rev/722e252fcabe6413eb63555890273d7b0e7fc132>
This commit is contained in:
Maxim Dounin authored and Roman Arutyunyan committed 2026-10-22 15:59:04 +04:00
1 parent 83f041908b
commit 807e53d990
2 files changed
+32

No files matched your search

@@ -60,6 +60,8 @@ static ngx_rbtree_node_t *ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree,
ngx_str_t *key, uint32_t hash);
static void ngx_http_limit_conn_cleanup(void *data);
static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool);
static void ngx_http_limit_conn_cleanup_node(ngx_shm_zone_t *shm_zone,
ngx_rbtree_node_t *node);
static ngx_int_t ngx_http_limit_conn_status_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
@@ -294,6 +296,7 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
cln = ngx_pool_cleanup_add(r->pool,
sizeof(ngx_http_limit_conn_cleanup_t));
if (cln == NULL) {
ngx_http_limit_conn_cleanup_node(limits[i].shm_zone, node);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@@ -433,6 +436,19 @@ ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool)
}
static void
ngx_http_limit_conn_cleanup_node(ngx_shm_zone_t *shm_zone,
ngx_rbtree_node_t *node)
{
ngx_http_limit_conn_cleanup_t lccln;
lccln.shm_zone = shm_zone;
lccln.node = node;
ngx_http_limit_conn_cleanup(&lccln);
}
static ngx_int_t
ngx_http_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
{
+16
View File
@@ -59,6 +59,8 @@ static ngx_rbtree_node_t *ngx_stream_limit_conn_lookup(ngx_rbtree_t *rbtree,
ngx_str_t *key, uint32_t hash);
static void ngx_stream_limit_conn_cleanup(void *data);
static ngx_inline void ngx_stream_limit_conn_cleanup_all(ngx_pool_t *pool);
static void ngx_stream_limit_conn_cleanup_node(ngx_shm_zone_t *shm_zone,
ngx_rbtree_node_t *node);
static ngx_int_t ngx_stream_limit_conn_status_variable(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data);
@@ -274,6 +276,7 @@ ngx_stream_limit_conn_handler(ngx_stream_session_t *s)
cln = ngx_pool_cleanup_add(s->connection->pool,
sizeof(ngx_stream_limit_conn_cleanup_t));
if (cln == NULL) {
ngx_stream_limit_conn_cleanup_node(limits[i].shm_zone, node);
return NGX_ERROR;
}
@@ -414,6 +417,19 @@ ngx_stream_limit_conn_cleanup_all(ngx_pool_t *pool)
}
static void
ngx_stream_limit_conn_cleanup_node(ngx_shm_zone_t *shm_zone,
ngx_rbtree_node_t *node)
{
ngx_stream_limit_conn_cleanup_t lccln;
lccln.shm_zone = shm_zone;
lccln.node = node;
ngx_stream_limit_conn_cleanup(&lccln);
}
static ngx_int_t
ngx_stream_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
{