httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stri...@apache.org
Subject cvs commit: httpd-2.0/server core.c request.c
Date Tue, 01 Jul 2003 01:25:07 GMT
striker     2003/06/30 18:25:07

  Modified:    .        Tag: APACHE_2_0_BRANCH CHANGES STATUS
               include  Tag: APACHE_2_0_BRANCH http_core.h
               modules/http Tag: APACHE_2_0_BRANCH http_request.c
               server   Tag: APACHE_2_0_BRANCH core.c request.c
  Removed:     build    Tag: APACHE_2_0_BRANCH httpd_roll_release
  Log:
  Backport from 2.1:
  
  Prevent the server from crashing when entering infinite loops. The
  new LimitInternalRecursion directive configures limits of subsequent
  internal redirects and nested subrequests, after which the request
  will be aborted.  PR 19753 (and probably others).
  
  Reviewed by: Andre Malo, Brian Pane, Justin Erenkrantz
  
  Revision  Changes    Path
  No                   revision
  No                   revision
  1.988.2.121 +6 -0      httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.988.2.120
  retrieving revision 1.988.2.121
  diff -u -r1.988.2.120 -r1.988.2.121
  --- CHANGES	1 Jul 2003 00:13:29 -0000	1.988.2.120
  +++ CHANGES	1 Jul 2003 01:25:04 -0000	1.988.2.121
  @@ -1,5 +1,11 @@
   Changes with Apache 2.0.47
   
  +  *) Prevent the server from crashing when entering infinite loops. The
  +     new LimitInternalRecursion directive configures limits of subsequent
  +     internal redirects and nested subrequests, after which the request
  +     will be aborted.  PR 19753 (and probably others).
  +     [William Rowe, Jeff Trawick, André Malo]
  +		      
     *) core_output_filter: don't split the brigade after a FLUSH bucket if
        it's the last bucket.  This prevents creating unneccessary empty
        brigades which may not be destroyed until the end of a keepalive
  
  
  
  1.751.2.350 +1 -11     httpd-2.0/STATUS
  
  Index: STATUS
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/STATUS,v
  retrieving revision 1.751.2.349
  retrieving revision 1.751.2.350
  diff -u -r1.751.2.349 -r1.751.2.350
  --- STATUS	1 Jul 2003 00:13:28 -0000	1.751.2.349
  +++ STATUS	1 Jul 2003 01:25:04 -0000	1.751.2.350
  @@ -70,16 +70,6 @@
         http://cvs.apache.org/viewcvs.cgi/httpd-2.0/server/protocol.c.diff?r1=1.131&r2=1.132&diff_format=h
         +1: brianp, jerenkrantz
   
  -    * Backport LimitInteralRecursion to 2.0 and 1.3.
  -      (1.3 patch is here: <http://cvs.apache.org/~nd/recursion13.patch>)
  -      (2.0 patch is here: <http://cvs.apache.org/~nd/recursion20.patch>)
  -      PR 19753.
  -      include/http_core.h r1.75, r1.76
  -      modules/http/http_request.c r1.156, r1.158
  -      server/core.c r1.236, r1.237
  -      server/request.c r1.126, r1.127
  -      +1: nd, brianp (for 2.0), jerenkrantz (both)
  -
       * Replace some of the mutex locking in the worker MPM with
         atomic operations for higher concurrency.
         server/mpm/worker/fdqueue.c 1.24, 1.25
  
  
  
  No                   revision
  No                   revision
  1.70.2.3  +18 -0     httpd-2.0/include/http_core.h
  
  Index: http_core.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/include/http_core.h,v
  retrieving revision 1.70.2.2
  retrieving revision 1.70.2.3
  diff -u -r1.70.2.2 -r1.70.2.3
  --- http_core.h	8 May 2003 20:49:32 -0000	1.70.2.2
  +++ http_core.h	1 Jul 2003 01:25:06 -0000	1.70.2.3
  @@ -134,6 +134,12 @@
    */
   #define AP_MIN_BYTES_TO_WRITE  8000
   
  +/* default maximum of internal redirects */
  +# define AP_DEFAULT_MAX_INTERNAL_REDIRECTS 10
  +
  +/* default maximum subrequest nesting level */
  +# define AP_DEFAULT_MAX_SUBREQ_DEPTH 10
  +
   /**
    * Retrieve the value of Options for this request
    * @param r The current request
  @@ -258,6 +264,14 @@
   AP_DECLARE(void) ap_custom_response(request_rec *r, int status, const char *string);
   
   /**
  + * Check if the current request is beyond the configured max. number of redirects or subrequests
  + * @param r The current request
  + * @return true (is exceeded) or false
  + * @deffunc int ap_is_recursion_limit_exceeded(const request_rec *r)
  + */
  +AP_DECLARE(int) ap_is_recursion_limit_exceeded(const request_rec *r);
  +
  +/**
    * Check for a definition from the server command line
    * @param name The define to check for
    * @return 1 if defined, 0 otherwise
  @@ -562,6 +576,10 @@
       char *access_name;
       apr_array_header_t *sec_dir;
       apr_array_header_t *sec_url;
  +
  +    /* recursion backstopper */
  +    int redirect_limit; /* maximum number of internal redirects */
  +    int subreq_limit;   /* maximum nesting level of subrequests */
   } core_server_config;
   
   /* for AddOutputFiltersByType in core.c */
  
  
  
  No                   revision
  No                   revision
  1.152.2.5 +22 -3     httpd-2.0/modules/http/http_request.c
  
  Index: http_request.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/http/http_request.c,v
  retrieving revision 1.152.2.4
  retrieving revision 1.152.2.5
  diff -u -r1.152.2.4 -r1.152.2.5
  --- http_request.c	19 May 2003 15:24:05 -0000	1.152.2.4
  +++ http_request.c	1 Jul 2003 01:25:06 -0000	1.152.2.5
  @@ -332,8 +332,14 @@
   static request_rec *internal_internal_redirect(const char *new_uri,
                                                  request_rec *r) {
       int access_status;
  -    request_rec *new = (request_rec *) apr_pcalloc(r->pool,
  -                                                   sizeof(request_rec));
  +    request_rec *new;
  +
  +    if (ap_is_recursion_limit_exceeded(r)) {
  +        ap_die(HTTP_INTERNAL_SERVER_ERROR, r);
  +        return NULL;
  +    }
  +
  +    new = (request_rec *) apr_pcalloc(r->pool, sizeof(request_rec));
   
       new->connection = r->connection;
       new->server     = r->server;
  @@ -480,7 +486,14 @@
   AP_DECLARE(void) ap_internal_redirect(const char *new_uri, request_rec *r)
   {
       request_rec *new = internal_internal_redirect(new_uri, r);
  -    int access_status = ap_process_request_internal(new);
  +    int access_status;
  +
  +    /* ap_die was already called, if an error occured */
  +    if (!new) {
  +        return;
  +    }
  +
  +    access_status = ap_process_request_internal(new);
       if (access_status == OK) {
           if ((access_status = ap_invoke_handler(new)) != 0) {
               ap_die(access_status, new);
  @@ -501,6 +514,12 @@
   {
       int access_status;
       request_rec *new = internal_internal_redirect(new_uri, r);
  +
  +    /* ap_die was already called, if an error occured */
  +    if (!new) {
  +        return;
  +    }
  +
       if (r->handler)
           ap_set_content_type(new, r->content_type);
       access_status = ap_process_request_internal(new);
  
  
  
  No                   revision
  No                   revision
  1.225.2.8 +139 -0    httpd-2.0/server/core.c
  
  Index: core.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/core.c,v
  retrieving revision 1.225.2.7
  retrieving revision 1.225.2.8
  diff -u -r1.225.2.7 -r1.225.2.8
  --- core.c	1 Jul 2003 00:13:34 -0000	1.225.2.7
  +++ core.c	1 Jul 2003 01:25:07 -0000	1.225.2.8
  @@ -474,6 +474,10 @@
       conf->sec_dir = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
       conf->sec_url = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
   
  +    /* recursion stopper */
  +    conf->redirect_limit = 0; /* 0 == unset */
  +    conf->subreq_limit = 0;
  +
       return (void *)conf;
   }
   
  @@ -497,6 +501,14 @@
       conf->sec_dir = apr_array_append(p, base->sec_dir, virt->sec_dir);
       conf->sec_url = apr_array_append(p, base->sec_url, virt->sec_url);
   
  +    conf->redirect_limit = virt->redirect_limit
  +                           ? virt->redirect_limit
  +                           : base->redirect_limit;
  +
  +    conf->subreq_limit = virt->subreq_limit
  +                         ? virt->subreq_limit
  +                         : base->subreq_limit;
  +
       return conf;
   }
   
  @@ -2639,6 +2651,129 @@
   }
   #endif
   
  +static const char *set_recursion_limit(cmd_parms *cmd, void *dummy,
  +                                       const char *arg1, const char *arg2)
  +{
  +    core_server_config *conf = ap_get_module_config(cmd->server->module_config,
  +                                                    &core_module);
  +    int limit = atoi(arg1);
  +
  +    if (limit <= 0) {
  +        return "The recursion limit must be greater than zero.";
  +    }
  +    if (limit < 4) {
  +        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
  +                     "Limiting internal redirects to very low numbers may "
  +                     "cause normal requests to fail.");
  +    }
  +
  +    conf->redirect_limit = limit;
  +
  +    if (arg2) {
  +        limit = atoi(arg2);
  +
  +        if (limit <= 0) {
  +            return "The recursion limit must be greater than zero.";
  +        }
  +        if (limit < 4) {
  +            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
  +                         "Limiting the subrequest depth to a very low level may"
  +                         " cause normal requests to fail.");
  +        }
  +    }
  +
  +    conf->subreq_limit = limit;
  +
  +    return NULL;
  +}
  +
  +static void log_backtrace(const request_rec *r)
  +{
  +    const request_rec *top = r;
  +
  +    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
  +                  "r->uri = %s", r->uri ? r->uri : "(unexpectedly NULL)");
  +
  +    while (top && (top->prev || top->main)) {
  +        if (top->prev) {
  +            top = top->prev;
  +            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
  +                          "redirected from r->uri = %s",
  +                          top->uri ? top->uri : "(unexpectedly NULL)");
  +        }
  +
  +        if (!top->prev && top->main) {
  +            top = top->main;
  +            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
  +                          "subrequested from r->uri = %s",
  +                          top->uri ? top->uri : "(unexpectedly NULL)");
  +        }
  +    }
  +}
  +
  +/*
  + * check whether redirect limit is reached
  + */
  +AP_DECLARE(int) ap_is_recursion_limit_exceeded(const request_rec *r)
  +{
  +    core_server_config *conf = ap_get_module_config(r->server->module_config,
  +                                                    &core_module);
  +    const request_rec *top = r;
  +    int redirects = 0, subreqs = 0;
  +    int rlimit = conf->redirect_limit
  +                 ? conf->redirect_limit
  +                 : AP_DEFAULT_MAX_INTERNAL_REDIRECTS;
  +    int slimit = conf->subreq_limit
  +                 ? conf->subreq_limit
  +                 : AP_DEFAULT_MAX_SUBREQ_DEPTH;
  +
  +
  +    while (top->prev || top->main) {
  +        if (top->prev) {
  +            if (++redirects >= rlimit) {
  +                /* uuh, too much. */
  +                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  +                              "Request exceeded the limit of %d internal "
  +                              "redirects due to probable configuration error. "
  +                              "Use 'LimitInternalRecursion' to increase the "
  +                              "limit if necessary. Use 'LogLevel debug' to get "
  +                              "a backtrace.", rlimit);
  +
  +                /* post backtrace */
  +                log_backtrace(r);
  +
  +                /* return failure */
  +                return 1;
  +            }
  +
  +            top = top->prev;
  +        }
  +
  +        if (!top->prev && top->main) {
  +            if (++subreqs >= slimit) {
  +                /* uuh, too much. */
  +                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  +                              "Request exceeded the limit of %d subrequest "
  +                              "nesting levels due to probable confguration "
  +                              "error. Use 'LimitInternalRecursion' to increase "
  +                              "the limit if necessary. Use 'LogLevel debug' to "
  +                              "get a backtrace.", slimit);
  +
  +                /* post backtrace */
  +                log_backtrace(r);
  +
  +                /* return failure */
  +                return 1;
  +            }
  +
  +            top = top->main;
  +        }
  +    }
  +
  +    /* recursion state: ok */
  +    return 0;
  +}
  +
   static const char *add_ct_output_filters(cmd_parms *cmd, void *conf_,
                                            const char *arg, const char *arg2)
   {
  @@ -3094,6 +3229,10 @@
   AP_INIT_TAKE12("RLimitNPROC", no_set_limit, NULL,
      OR_ALL, "soft/hard limits for max number of processes per uid"),
   #endif
  +
  +/* internal recursion stopper */
  +AP_INIT_TAKE12("LimitInternalRecursion", set_recursion_limit, NULL, RSRC_CONF,
  +              "maximum recursion depth of internal redirects and subrequests"),
   
   AP_INIT_TAKE1("ForceType", ap_set_string_slot_lower,
          (void *)APR_OFFSETOF(core_dir_config, mime_type), OR_FILEINFO,
  
  
  
  1.121.2.5 +22 -0     httpd-2.0/server/request.c
  
  Index: request.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/request.c,v
  retrieving revision 1.121.2.4
  retrieving revision 1.121.2.5
  diff -u -r1.121.2.4 -r1.121.2.5
  --- request.c	8 May 2003 20:49:32 -0000	1.121.2.4
  +++ request.c	1 Jul 2003 01:25:07 -0000	1.121.2.5
  @@ -1631,6 +1631,14 @@
           udir = ap_escape_uri(rnew->pool, udir);    /* re-escape it */
           ap_parse_uri(rnew, ap_make_full_path(rnew->pool, udir, new_file));
       }
  +
  +    /* We cannot return NULL without violating the API. So just turn this
  +     * subrequest into a 500 to indicate the failure. */
  +    if (ap_is_recursion_limit_exceeded(r)) {
  +        rnew->status = HTTP_INTERNAL_SERVER_ERROR;
  +        return rnew;
  +    }
  +
       /* lookup_uri 
        * If the content can be served by the quick_handler, we can
        * safely bypass request_internal processing.
  @@ -1764,6 +1772,13 @@
           ap_parse_uri(rnew, rnew->uri);
       }
   
  +    /* We cannot return NULL without violating the API. So just turn this
  +     * subrequest into a 500. */
  +    if (ap_is_recursion_limit_exceeded(r)) {
  +        rnew->status = HTTP_INTERNAL_SERVER_ERROR;
  +        return rnew;
  +    }
  +
       if ((res = ap_process_request_internal(rnew))) {
           rnew->status = res;
       }
  @@ -1849,6 +1864,13 @@
            * file may not have a uri associated with it -djg
            */
           rnew->uri = apr_pstrdup(rnew->pool, "");
  +    }
  +
  +    /* We cannot return NULL without violating the API. So just turn this
  +     * subrequest into a 500. */
  +    if (ap_is_recursion_limit_exceeded(r)) {
  +        rnew->status = HTTP_INTERNAL_SERVER_ERROR;
  +        return rnew;
       }
   
       if ((res = ap_process_request_internal(rnew))) {
  
  
  

Mime
View raw message