Skip to content

Fixed memory leak #80

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed

Conversation

AirisX
Copy link
Contributor

@AirisX AirisX commented Dec 19, 2017

I compiled the nginx-connector with the flag "-fsanitize=leak" and found that the "ModSecurity" object from the "ngx_http_modsecurity_conf_t" structure is not freed.

I tried to fix it according to the examples.

@defanator
Copy link
Collaborator

Hi @AirisX, have you checked this change with ASAN as well?

I'm seeing the following with your patch applied:

2017/12/22 10:22:55 [notice] 16066#16066: using the "epoll" event method
2017/12/22 10:22:55 [notice] 16066#16066: nginx/1.13.7
2017/12/22 10:22:55 [notice] 16066#16066: built by gcc 6.3.0 20170406 (Ubuntu 6.3.0-12ubuntu2) 
2017/12/22 10:22:55 [notice] 16066#16066: OS: Linux 4.10.0-30-generic
2017/12/22 10:22:55 [notice] 16066#16066: getrlimit(RLIMIT_NOFILE): 131072:131072
2017/12/22 10:22:55 [notice] 16067#16067: start worker processes
2017/12/22 10:22:55 [notice] 16067#16067: start worker process 16068
2017/12/22 10:23:01 [notice] 16067#16067: signal 15 (SIGTERM) received from 26525, exiting
2017/12/22 10:23:01 [notice] 16068#16068: exiting
2017/12/22 10:23:01 [notice] 16067#16067: signal 14 (SIGALRM) received
ASAN:DEADLYSIGNAL
=================================================================
==16068==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7fbfcf57139f bp 0x7fbfcf87cfe8 sp 0x7fffaa467870 T0)
    #0 0x7fbfcf57139e in modsecurity::ModSecurity::~ModSecurity() /home/test/ModSecurity/src/modsecurity.cc:92
    #1 0x7fbfcf57170d in msc_cleanup /home/test/ModSecurity/src/modsecurity.cc:465
    #2 0x56297fc9ffc5 in ngx_http_modsecurity_config_cleanup ../ModSecurity-nginx/src/ngx_http_modsecurity_module.c:654
    #3 0x56297fa87149 in ngx_destroy_pool src/core/ngx_palloc.c:57
    #4 0x56297faec20c in ngx_worker_process_exit src/os/unix/ngx_process_cycle.c:997
    #5 0x56297faec540 in ngx_worker_process_cycle src/os/unix/ngx_process_cycle.c:743
    #6 0x56297fae8b91 in ngx_spawn_process src/os/unix/ngx_process.c:198
    #7 0x56297faec84d in ngx_start_worker_processes src/os/unix/ngx_process_cycle.c:358
    #8 0x56297faee46c in ngx_master_process_cycle src/os/unix/ngx_process_cycle.c:130
    #9 0x56297fa7f0fd in main src/core/nginx.c:381
    #10 0x7fbfce5833f0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x203f0)
    #11 0x56297fa815d9 in _start (/home/test/nginx-static+0x875d9)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/test/ModSecurity/src/modsecurity.cc:92 in modsecurity::ModSecurity::~ModSecurity()
==16068==ABORTING
2017/12/22 10:23:02 [notice] 16067#16067: signal 14 (SIGALRM) received
2017/12/22 10:23:02 [notice] 16067#16067: signal 17 (SIGCHLD) received from 16068
2017/12/22 10:23:02 [notice] 16067#16067: worker process 16068 exited with code 1
2017/12/22 10:23:02 [notice] 16067#16067: exit
ASAN:DEADLYSIGNAL
=================================================================
==16067==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7fbfcf57139f bp 0x7fbfcf87cfe8 sp 0x7fffaa467a80 T0)
    #0 0x7fbfcf57139e in modsecurity::ModSecurity::~ModSecurity() /home/test/ModSecurity/src/modsecurity.cc:92
    #1 0x7fbfcf57170d in msc_cleanup /home/test/ModSecurity/src/modsecurity.cc:465
    #2 0x56297fc9ffc5 in ngx_http_modsecurity_config_cleanup ../ModSecurity-nginx/src/ngx_http_modsecurity_module.c:654
    #3 0x56297fa87149 in ngx_destroy_pool src/core/ngx_palloc.c:57
    #4 0x56297faead36 in ngx_master_process_exit src/os/unix/ngx_process_cycle.c:720
    #5 0x56297faeef8c in ngx_master_process_cycle src/os/unix/ngx_process_cycle.c:178
    #6 0x56297fa7f0fd in main src/core/nginx.c:381
    #7 0x7fbfce5833f0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x203f0)
    #8 0x56297fa815d9 in _start (/home/test/nginx-static+0x875d9)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/test/ModSecurity/src/modsecurity.cc:92 in modsecurity::ModSecurity::~ModSecurity()
==16067==ABORTING

Trying to figure out what is happening there, my current assumption is that ngx_http_modsecurity_config_cleanup() can definitely be called multiple times, and it's not clear whether we should call msc_cleanup() at the very first cleanup call. I'd like to have @zimmerle comment here though, as I'm not sure about any possible issues in libmodsecurity caused by such behavior of the connector.

@defanator
Copy link
Collaborator

Further investigation showed that t->modsec in cleanup handler contains invalid pointer since it's not being passed while merging configuration.

Currently applied the following patch and investigating deeper:

@@ -620,6 +622,7 @@ ngx_http_modsecurity_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
 
     ngx_conf_merge_value(c->enable, p->enable, 0);
     ngx_conf_merge_value(c->sanity_checks_enabled, p->sanity_checks_enabled, 0);
+    c->modsec = p->modsec;
 
 #if defined(MODSECURITY_DDEBUG) && (MODSECURITY_DDEBUG)
     dd("PARENT RULES");

@AirisX
Copy link
Contributor Author

AirisX commented Dec 22, 2017

Hi @defanator,

just yesterday i found a core-dump originated from the pre-production build with this patch. This dump appeared after the stopping the nginx process. After tracing this dump i got the same you are point on. In my case it was line 94 in modsecurity.cc (I am using slightly modified libmodsecurity). Here is the line itself:

delete m_global_collection;

But my other experimental build with this patch and without all the extra modules has no this problem. I still do not understand what it depends on.

By the way, what libmodsecurity brunch are you using?

As for ngx_http_modsecurity_config_cleanup() you right, it is invoked multiple times. But only the last invoke contains ngx_http_modsecurity_conf_t structure with not null modsec pointer. This structure was filled at the first invoke of the ngx_http_modsecurity_create_conf in ngx_http_modsecurity_create_main_conf. Thus to ngx_http_modsecurity_config_cleanup applied the principle of LIFO.

@AirisX
Copy link
Contributor Author

AirisX commented Dec 22, 2017

I think it is necessary explicitly initialize t->modsec pointer with NULL to prevent invoke msc_cleanup with address 0x000000000000 among multiple invokes of the ngx_http_modsecurity_config_cleanup. Like this:

--- a/src/ngx_http_modsecurity_module.c
+++ b/src/ngx_http_modsecurity_module.c
@@ -545,6 +545,7 @@ static void *ngx_http_modsecurity_create_conf(ngx_conf_t *cf)
     conf->enable = NGX_CONF_UNSET;
     conf->sanity_checks_enabled = NGX_CONF_UNSET;
     conf->rules_set = msc_create_rules_set();
+    conf->modsec = NULL;

     cln = ngx_pool_cleanup_add(cf->pool, 0);
     if (cln == NULL) {

@defanator
Copy link
Collaborator

@AirisX I'm using v3/master branch for ModSecurity, and master branch for ModSecurity-nginx. I do all my testing in isolated Vagrant environment created from this project:

https://github.com/defanator/modsecurity-performance

What "extra" modules you were using? How did you build your nginx with modules - statically (--add-module) or dynamically (--add-dynamic-module)?

@defanator
Copy link
Collaborator

@AirisX I have tested your patch with addition from #80 (comment) and all seems to work fine.

Full diff was as follows:

diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c
index 6d6ee7a..4fae30c 100644
--- a/src/ngx_http_modsecurity_module.c
+++ b/src/ngx_http_modsecurity_module.c
@@ -545,6 +545,7 @@ static void *ngx_http_modsecurity_create_conf(ngx_conf_t *cf)
     conf->enable = NGX_CONF_UNSET;
     conf->sanity_checks_enabled = NGX_CONF_UNSET;
     conf->rules_set = msc_create_rules_set();
+    conf->modsec = NULL;
 
     cln = ngx_pool_cleanup_add(cf->pool, 0);
     if (cln == NULL) {
@@ -647,13 +648,15 @@ ngx_http_modsecurity_config_cleanup(void *data)
     ngx_pool_t *old_pool;
     ngx_http_modsecurity_conf_t *t = (ngx_http_modsecurity_conf_t *) data;
 
-    dd("deleting a loc conf -- RuleSet is: \"%p\"", t->rules_set);
+    dd("deleting a loc conf -- RuleSet is: \"%p\", modsec is: \"%p\"", t->rules_set, t->modsec);
 
     old_pool = ngx_http_modsecurity_pcre_malloc_init(NULL);
     msc_rules_cleanup(t->rules_set);
+    msc_cleanup(t->modsec);
     ngx_http_modsecurity_pcre_malloc_done(old_pool);
 
     t->rules_set = NULL;
+    t->modsec = NULL;
 }
 

Could you please add that change to the branch linked with this PR?

(dd part is not needed obviously; I have long-awaiting changesets to remove unnecessary dd's and turn the rest into ngx_log_debugX)

@AirisX
Copy link
Contributor Author

AirisX commented Dec 25, 2017

Hi @defanator, I also have tested patch mentioned in comment #80 (comment) and there are no longer core-dumps. As it turned out, the composition of the modules used doesn't matter, and the fact is that the modsec pointer was initialized with the garbage value.

I added this change to the brunch.

@defanator defanator self-assigned this Dec 25, 2017
@defanator
Copy link
Collaborator

@zimmerle I'm fine with merging this one - would you like to take a look as well?

@defanator
Copy link
Collaborator

@zimmerle @victorhora guys, could we finally merge this one? I'm happy to do this myself. I suppose we'd like to keep CHANGES here as well? (this one definitely worth to mention there)

zimmerle pushed a commit that referenced this pull request Mar 22, 2018
zimmerle pushed a commit that referenced this pull request Mar 22, 2018
@zimmerle
Copy link
Contributor

Sorry for the long delay.

Thank you @AirisX, @defanator and @victorhora. Merged!

@zimmerle zimmerle closed this Mar 22, 2018
pracj3am pushed a commit to cdn77/ModSecurity-nginx that referenced this pull request Nov 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants