Mercurial > hg > nginx-quic
changeset 7536:c3f60d618c17
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().
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 18 Jul 2019 18:27:44 +0300 |
parents | 56b4fb46ba7d |
children | 01e26357916a |
files | src/core/ngx_hash.c |
diffstat | 1 files changed, 25 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- 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;