From: Yann Ylavic Date: Thu, 22 Feb 2024 14:12:18 +0000 (+0000) Subject: PR62229: add CGIScriptTimeout to mod_cgi X-Git-Tag: 2.4.59-rc1-candidate~51 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=f688ac31c4e3236572085850e8996e0ae49353dc;p=thirdparty%2Fapache%2Fhttpd.git PR62229: add CGIScriptTimeout to mod_cgi add CGIScriptTimeout to mod_cgi, like mod_cgid's CGIDScriptTimeout. Not addressed: making CGIScriptTimeout name work for either module. Merges r1828172 from https://svn.apache.org/repos/asf/httpd/httpd/trunk. Submitted By: Hank Ibell Committed By: covener Reviewed by: minfrin, ylavic, jfclere git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1915950 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/STATUS b/STATUS index 69dfe04867b..2f379c13105 100644 --- a/STATUS +++ b/STATUS @@ -152,11 +152,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - *) Add CGIScriptTimeout to mod_cgi. - trunk patch: http://svn.apache.org/r1828172 - 2.4.x patch: https://svn.apache.org/repos/asf/httpd/httpd/patches/2.4.x/httpd-2.4-add-CGIScriptTimeout.patch - +1: minfrin, ylavic, jfclere - *) mod_http2 v2.0.26. fixes `Data:` in upgrade responses and a small memory leak in h2 header buckets. trunk patch: http://svn.apache.org/r1915281 diff --git a/changes-entries/add-CGIScriptTimeout.txt b/changes-entries/add-CGIScriptTimeout.txt new file mode 100644 index 00000000000..def7ab451df --- /dev/null +++ b/changes-entries/add-CGIScriptTimeout.txt @@ -0,0 +1,3 @@ + + *) Add CGIScriptTimeout to mod_cgi. [Eric Covener] + diff --git a/docs/manual/mod/mod_cgi.xml b/docs/manual/mod/mod_cgi.xml index aa7dd939437..21c5cf43edf 100644 --- a/docs/manual/mod/mod_cgi.xml +++ b/docs/manual/mod/mod_cgi.xml @@ -175,6 +175,31 @@ + +CGIScriptTimeout +The length of time to wait for more output from the +CGI program +CGIScriptTimeout time[s|ms] +value of Timeout directive when +unset +server config +virtual hostdirectory +.htaccess + + +

This directive limits the length of time to wait for more output from + the CGI program. If the time is exceeded, the request and CGI are + terminated.

+ + Example + + CGIScriptTimeout 20 + + + +
+
+ ScriptLog Location of the CGI script error logfile diff --git a/modules/generators/mod_cgi.c b/modules/generators/mod_cgi.c index 7e4b126c105..63711b2eb09 100644 --- a/modules/generators/mod_cgi.c +++ b/modules/generators/mod_cgi.c @@ -92,6 +92,10 @@ typedef struct { apr_size_t bufbytes; } cgi_server_conf; +typedef struct { + apr_interval_time_t timeout; +} cgi_dirconf; + static void *create_cgi_config(apr_pool_t *p, server_rec *s) { cgi_server_conf *c = @@ -112,6 +116,12 @@ static void *merge_cgi_config(apr_pool_t *p, void *basev, void *overridesv) return overrides->logname ? overrides : base; } +static void *create_cgi_dirconf(apr_pool_t *p, char *dummy) +{ + cgi_dirconf *c = (cgi_dirconf *) apr_pcalloc(p, sizeof(cgi_dirconf)); + return c; +} + static const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg) { server_rec *s = cmd->server; @@ -150,6 +160,17 @@ static const char *set_scriptlog_buffer(cmd_parms *cmd, void *dummy, return NULL; } +static const char *set_script_timeout(cmd_parms *cmd, void *dummy, const char *arg) +{ + cgi_dirconf *dc = dummy; + + if (ap_timeout_parameter_parse(arg, &dc->timeout, "s") != APR_SUCCESS) { + return "CGIScriptTimeout has wrong format"; + } + + return NULL; +} + static const command_rec cgi_cmds[] = { AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF, @@ -158,6 +179,9 @@ AP_INIT_TAKE1("ScriptLogLength", set_scriptlog_length, NULL, RSRC_CONF, "the maximum length (in bytes) of the script debug log"), AP_INIT_TAKE1("ScriptLogBuffer", set_scriptlog_buffer, NULL, RSRC_CONF, "the maximum size (in bytes) to record of a POST request"), +AP_INIT_TAKE1("CGIScriptTimeout", set_script_timeout, NULL, RSRC_CONF | ACCESS_CONF, + "The amount of time to wait between successful reads from " + "the CGI script, in seconds."), {NULL} }; @@ -466,23 +490,26 @@ static apr_status_t run_cgi_child(apr_file_t **script_out, apr_filepath_name_get(r->filename)); } else { + cgi_dirconf *dc = ap_get_module_config(r->per_dir_config, &cgi_module); + apr_interval_time_t timeout = dc->timeout > 0 ? dc->timeout : r->server->timeout; + apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT); *script_in = procnew->out; if (!*script_in) return APR_EBADF; - apr_file_pipe_timeout_set(*script_in, r->server->timeout); + apr_file_pipe_timeout_set(*script_in, timeout); if (e_info->prog_type == RUN_AS_CGI) { *script_out = procnew->in; if (!*script_out) return APR_EBADF; - apr_file_pipe_timeout_set(*script_out, r->server->timeout); + apr_file_pipe_timeout_set(*script_out, timeout); *script_err = procnew->err; if (!*script_err) return APR_EBADF; - apr_file_pipe_timeout_set(*script_err, r->server->timeout); + apr_file_pipe_timeout_set(*script_err, timeout); } } } @@ -675,11 +702,14 @@ static apr_status_t cgi_bucket_read(apr_bucket *b, const char **str, apr_size_t *len, apr_read_type_e block) { struct cgi_bucket_data *data = b->data; - apr_interval_time_t timeout; + apr_interval_time_t timeout = 0; apr_status_t rv; int gotdata = 0; + cgi_dirconf *dc = ap_get_module_config(data->r->per_dir_config, &cgi_module); - timeout = block == APR_NONBLOCK_READ ? 0 : data->r->server->timeout; + if (block != APR_NONBLOCK_READ) { + timeout = dc->timeout > 0 ? dc->timeout : data->r->server->timeout; + } do { const apr_pollfd_t *results; @@ -757,6 +787,8 @@ static int cgi_handler(request_rec *r) apr_status_t rv; cgi_exec_info_t e_info; conn_rec *c; + cgi_dirconf *dc = ap_get_module_config(r->per_dir_config, &cgi_module); + apr_interval_time_t timeout = dc->timeout > 0 ? dc->timeout : r->server->timeout; if (strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script")) { return DECLINED; @@ -976,7 +1008,7 @@ static int cgi_handler(request_rec *r) * stderr output, as normal. */ discard_script_output(bb); apr_brigade_destroy(bb); - apr_file_pipe_timeout_set(script_err, r->server->timeout); + apr_file_pipe_timeout_set(script_err, timeout); log_script_err(r, script_err); } @@ -1027,7 +1059,7 @@ static int cgi_handler(request_rec *r) * connection drops or we stopped sending output for some other * reason */ if (rv == APR_SUCCESS && !r->connection->aborted) { - apr_file_pipe_timeout_set(script_err, r->server->timeout); + apr_file_pipe_timeout_set(script_err, timeout); log_script_err(r, script_err); } @@ -1268,7 +1300,7 @@ static void register_hooks(apr_pool_t *p) AP_DECLARE_MODULE(cgi) = { STANDARD20_MODULE_STUFF, - NULL, /* dir config creater */ + create_cgi_dirconf, /* dir config creater */ NULL, /* dir merger --- default is to override */ create_cgi_config, /* server config */ merge_cgi_config, /* merge server config */