[nginx] Perl: disabled unrelated calls from variable handlers.

Maxim Dounin mdounin at mdounin.ru
Fri Jul 12 14:53:57 UTC 2019


details:   https://hg.nginx.org/nginx/rev/0cb693b4cbbb
branches:  
changeset: 7528:0cb693b4cbbb
user:      Maxim Dounin <mdounin at mdounin.ru>
date:      Fri Jul 12 15:35:31 2019 +0300
description:
Perl: disabled unrelated calls from variable handlers.

Variable handlers are not expected to send anything to the client, cannot
sleep or read body, and are not expected to modify the request.  Added
appropriate protection to prevent accidental foot shooting.

diffstat:

 src/http/modules/perl/nginx.xs               |  44 ++++++++++++++++++++++++++++
 src/http/modules/perl/ngx_http_perl_module.c |   5 +++
 src/http/modules/perl/ngx_http_perl_module.h |   1 +
 3 files changed, 50 insertions(+), 0 deletions(-)

diffs (164 lines):

diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -110,6 +110,10 @@ status(r, code)
 
     ngx_http_perl_set_request(r, ctx);
 
+    if (ctx->variable) {
+        croak("status(): cannot be used in variable handler");
+    }
+
     r->headers_out.status = SvIV(ST(1));
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -133,6 +137,10 @@ send_http_header(r, ...)
         croak("send_http_header(): called after error");
     }
 
+    if (ctx->variable) {
+        croak("send_http_header(): cannot be used in variable handler");
+    }
+
     if (r->headers_out.status == 0) {
         r->headers_out.status = NGX_HTTP_OK;
     }
@@ -400,6 +408,10 @@ has_request_body(r, next)
 
     ngx_http_perl_set_request(r, ctx);
 
+    if (ctx->variable) {
+        croak("has_request_body(): cannot be used in variable handler");
+    }
+
     if (ctx->next) {
         croak("has_request_body(): another handler active");
     }
@@ -526,6 +538,10 @@ discard_request_body(r)
 
     ngx_http_perl_set_request(r, ctx);
 
+    if (ctx->variable) {
+        croak("discard_request_body(): cannot be used in variable handler");
+    }
+
     rc = ngx_http_discard_request_body(r);
 
     if (rc != NGX_OK) {
@@ -551,6 +567,10 @@ header_out(r, key, value)
         croak("header_out(): called after error");
     }
 
+    if (ctx->variable) {
+        croak("header_out(): cannot be used in variable handler");
+    }
+
     key = ST(1);
     value = ST(2);
 
@@ -640,6 +660,10 @@ print(r, ...)
         croak("print(): called after error");
     }
 
+    if (ctx->variable) {
+        croak("print(): cannot be used in variable handler");
+    }
+
     if (items == 2) {
 
         /*
@@ -750,6 +774,10 @@ sendfile(r, filename, offset = -1, bytes
         croak("sendfile(): called after error");
     }
 
+    if (ctx->variable) {
+        croak("sendfile(): cannot be used in variable handler");
+    }
+
     filename = SvPV_nolen(ST(1));
 
     if (filename == NULL) {
@@ -852,6 +880,10 @@ flush(r)
         croak("flush(): called after error");
     }
 
+    if (ctx->variable) {
+        croak("flush(): cannot be used in variable handler");
+    }
+
     b = ngx_calloc_buf(r->pool);
     if (b == NULL) {
         ctx->error = 1;
@@ -883,6 +915,10 @@ internal_redirect(r, uri)
 
     ngx_http_perl_set_request(r, ctx);
 
+    if (ctx->variable) {
+        croak("internal_redirect(): cannot be used in variable handler");
+    }
+
     uri = ST(1);
 
     if (ngx_http_perl_sv2str(aTHX_ r, &ctx->redirect_uri, uri) != NGX_OK) {
@@ -911,6 +947,10 @@ allow_ranges(r)
 
     ngx_http_perl_set_request(r, ctx);
 
+    if (ctx->variable) {
+        croak("allow_ranges(): cannot be used in variable handler");
+    }
+
     r->allow_ranges = 1;
 
 
@@ -1097,6 +1137,10 @@ sleep(r, sleep, next)
 
     ngx_http_perl_set_request(r, ctx);
 
+    if (ctx->variable) {
+        croak("sleep(): cannot be used in variable handler");
+    }
+
     if (ctx->next) {
         croak("sleep(): another handler active");
     }
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -302,6 +302,7 @@ ngx_http_perl_variable(ngx_http_request_
 
     ngx_int_t                   rc;
     ngx_str_t                   value;
+    ngx_uint_t                  saved;
     ngx_http_perl_ctx_t        *ctx;
     ngx_http_perl_main_conf_t  *pmcf;
 
@@ -321,6 +322,9 @@ ngx_http_perl_variable(ngx_http_request_
         ctx->request = r;
     }
 
+    saved = ctx->variable;
+    ctx->variable = 1;
+
     pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
 
     value.data = NULL;
@@ -347,6 +351,7 @@ ngx_http_perl_variable(ngx_http_request_
         v->not_found = 1;
     }
 
+    ctx->variable = saved;
     ctx->filename.data = NULL;
     ctx->redirect_uri.len = 0;
 
diff --git a/src/http/modules/perl/ngx_http_perl_module.h b/src/http/modules/perl/ngx_http_perl_module.h
--- a/src/http/modules/perl/ngx_http_perl_module.h
+++ b/src/http/modules/perl/ngx_http_perl_module.h
@@ -33,6 +33,7 @@ typedef struct {
 
     unsigned                  done:1;
     unsigned                  error:1;
+    unsigned                  variable:1;
 
     ngx_array_t              *variables;  /* array of ngx_http_perl_var_t */
 


More information about the nginx-devel mailing list