Welcome! Log In Create A New Profile

Advanced

[nginx] Core: fixed segfault with too large bucket sizes (ticket #1806).

Maxim Dounin
July 18, 2019 11:30AM
details: https://hg.nginx.org/nginx/rev/c3f60d618c17
branches:
changeset: 7536:c3f60d618c17
user: Maxim Dounin <mdounin@mdounin.ru>
date: Thu Jul 18 18:27:44 2019 +0300
description:
Core: fixed segfault with too large bucket sizes (ticket #1806).

To save memory hash code uses u_short to store resulting bucket sizes,
so maximum bucket size is limited to 65536 minus ngx_cacheline_size (larger
values will be aligned to 65536 which will overflow u_short). However,
there were no checks to enforce this, and using larger bucket sizes
resulted in overflows and segmentation faults.

Appropriate safety checks to enforce this added to ngx_hash_init().

diffstat:

src/core/ngx_hash.c | 30 +++++++++++++++++++++++++-----
1 files changed, 25 insertions(+), 5 deletions(-)

diffs (61 lines):

diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c
--- a/src/core/ngx_hash.c
+++ b/src/core/ngx_hash.c
@@ -265,6 +265,14 @@ ngx_hash_init(ngx_hash_init_t *hinit, ng
return NGX_ERROR;
}

+ if (hinit->bucket_size > 65536 - ngx_cacheline_size) {
+ ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
+ "could not build %s, too large "
+ "%s_bucket_size: %i",
+ hinit->name, hinit->name, hinit->bucket_size);
+ return NGX_ERROR;
+ }
+
for (n = 0; n < nelts; n++) {
if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
{
@@ -300,17 +308,19 @@ ngx_hash_init(ngx_hash_init_t *hinit, ng
}

key = names[n].key_hash % size;
- test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
+ len = test[key] + NGX_HASH_ELT_SIZE(&names[n]);

#if 0
ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
- "%ui: %ui %ui \"%V\"",
- size, key, test[key], &names[n].key);
+ "%ui: %ui %uz \"%V\"",
+ size, key, len, &names[n].key);
#endif

- if (test[key] > (u_short) bucket_size) {
+ if (len > bucket_size) {
goto next;
}
+
+ test[key] = (u_short) len;
}

goto found;
@@ -341,7 +351,17 @@ found:
}

key = names[n].key_hash % size;
- test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
+ len = test[key] + NGX_HASH_ELT_SIZE(&names[n]);
+
+ if (len > 65536 - ngx_cacheline_size) {
+ ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
+ "could not build %s, you should "
+ "increase %s_max_size: %i",
+ hinit->name, hinit->name, hinit->max_size);
+ return NGX_ERROR;
+ }
+
+ test[key] = (u_short) len;
}

len = 0;
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[nginx] Core: fixed segfault with too large bucket sizes (ticket #1806).

Maxim Dounin 267 July 18, 2019 11:30AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 222
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready