components/apache2/patches/CVE-2014-0118.patch
branchs11u2-sru
changeset 3268 17a417ef54a5
equal deleted inserted replaced
3262:80d85b37410d 3268:17a417ef54a5
       
     1 Patch origin: upstream
       
     2 Patch status: will be part of next version
       
     3 
       
     4 http://svn.apache.org/viewvc?view=revision&revision=1611426
       
     5 
       
     6 --- modules/filters/mod_deflate.c	2014/07/17 18:19:00	1611425
       
     7 +++ modules/filters/mod_deflate.c	2014/07/17 18:20:46	1611426
       
     8 @@ -37,6 +37,7 @@
       
     9  #include "httpd.h"
       
    10  #include "http_config.h"
       
    11  #include "http_log.h"
       
    12 +#include "http_core.h"
       
    13  #include "apr_lib.h"
       
    14  #include "apr_strings.h"
       
    15  #include "apr_general.h"
       
    16 @@ -51,6 +52,9 @@
       
    17  static const char deflateFilterName[] = "DEFLATE";
       
    18  module AP_MODULE_DECLARE_DATA deflate_module;
       
    19  
       
    20 +#define AP_INFLATE_RATIO_LIMIT 200
       
    21 +#define AP_INFLATE_RATIO_BURST 3
       
    22 +
       
    23  typedef struct deflate_filter_config_t
       
    24  {
       
    25      int windowSize;
       
    26 @@ -62,6 +66,12 @@
       
    27      char *note_output_name;
       
    28  } deflate_filter_config;
       
    29  
       
    30 +typedef struct deflate_dirconf_t {
       
    31 +    apr_off_t inflate_limit;
       
    32 +    int ratio_limit,
       
    33 +        ratio_burst;
       
    34 +} deflate_dirconf_t;
       
    35 +
       
    36  /* RFC 1952 Section 2.3 defines the gzip header:
       
    37   *
       
    38   * +---+---+---+---+---+---+---+---+---+---+
       
    39 @@ -193,6 +203,14 @@
       
    40      return c;
       
    41  }
       
    42  
       
    43 +static void *create_deflate_dirconf(apr_pool_t *p, char *dummy)
       
    44 +{
       
    45 +    deflate_dirconf_t *dc = apr_pcalloc(p, sizeof(*dc));
       
    46 +    dc->ratio_limit = AP_INFLATE_RATIO_LIMIT;
       
    47 +    dc->ratio_burst = AP_INFLATE_RATIO_BURST;
       
    48 +    return dc;
       
    49 +}
       
    50 +
       
    51  static const char *deflate_set_window_size(cmd_parms *cmd, void *dummy,
       
    52                                             const char *arg)
       
    53  {
       
    54 @@ -284,6 +302,55 @@
       
    55      return NULL;
       
    56  }
       
    57  
       
    58 +
       
    59 +static const char *deflate_set_inflate_limit(cmd_parms *cmd, void *dirconf,
       
    60 +                                      const char *arg)
       
    61 +{
       
    62 +    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
       
    63 +    char *errp;
       
    64 +
       
    65 +    if (APR_SUCCESS != apr_strtoff(&dc->inflate_limit, arg, &errp, 10)) {
       
    66 +        return "DeflateInflateLimitRequestBody is not parsable.";
       
    67 +    }
       
    68 +    if (*errp || dc->inflate_limit < 0) {
       
    69 +        return "DeflateInflateLimitRequestBody requires a non-negative integer.";
       
    70 +    }
       
    71 +
       
    72 +    return NULL;
       
    73 +}
       
    74 +
       
    75 +static const char *deflate_set_inflate_ratio_limit(cmd_parms *cmd,
       
    76 +                                                   void *dirconf,
       
    77 +                                                   const char *arg)
       
    78 +{
       
    79 +    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
       
    80 +    int i;
       
    81 +
       
    82 +    i = atoi(arg);
       
    83 +    if (i <= 0)
       
    84 +        return "DeflateInflateRatioLimit must be positive";
       
    85 +
       
    86 +    dc->ratio_limit = i;
       
    87 +
       
    88 +    return NULL;
       
    89 +}
       
    90 +
       
    91 +static const char *deflate_set_inflate_ratio_burst(cmd_parms *cmd,
       
    92 +                                                   void *dirconf,
       
    93 +                                                   const char *arg)
       
    94 +{
       
    95 +    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
       
    96 +    int i;
       
    97 +
       
    98 +    i = atoi(arg);
       
    99 +    if (i <= 0)
       
   100 +        return "DeflateInflateRatioBurst must be positive";
       
   101 +
       
   102 +    dc->ratio_burst = i;
       
   103 +
       
   104 +    return NULL;
       
   105 +}
       
   106 +
       
   107  typedef struct deflate_ctx_t
       
   108  {
       
   109      z_stream stream;
       
   110 @@ -294,8 +361,26 @@
       
   111      unsigned char *validation_buffer;
       
   112      apr_size_t validation_buffer_length;
       
   113      int inflate_init;
       
   114 +    int ratio_hits;
       
   115 +    apr_off_t inflate_total;
       
   116  } deflate_ctx;
       
   117  
       
   118 +/* Check whether the (inflate) ratio exceeds the configured limit/burst. */
       
   119 +static int check_ratio(request_rec *r, deflate_ctx *ctx,
       
   120 +                       const deflate_dirconf_t *dc)
       
   121 +{
       
   122 +    if (ctx->stream.total_in) {
       
   123 +        int ratio = ctx->stream.total_out / ctx->stream.total_in;
       
   124 +        if (ratio < dc->ratio_limit) {
       
   125 +            ctx->ratio_hits = 0;
       
   126 +        }
       
   127 +        else if (++ctx->ratio_hits > dc->ratio_burst) {
       
   128 +            return 0;
       
   129 +        }
       
   130 +    }
       
   131 +    return 1;
       
   132 +}
       
   133 +
       
   134  /* Number of validation bytes (CRC and length) after the compressed data */
       
   135  #define VALIDATION_SIZE 8
       
   136  /* Do not update ctx->crc, see comment in flush_libz_buffer */
       
   137 @@ -744,6 +829,8 @@
       
   138      int zRC;
       
   139      apr_status_t rv;
       
   140      deflate_filter_config *c;
       
   141 +    deflate_dirconf_t *dc;
       
   142 +    apr_off_t inflate_limit;
       
   143  
       
   144      /* just get out of the way of things we don't want. */
       
   145      if (mode != AP_MODE_READBYTES) {
       
   146 @@ -751,6 +838,7 @@
       
   147      }
       
   148  
       
   149      c = ap_get_module_config(r->server->module_config, &deflate_module);
       
   150 +    dc = ap_get_module_config(r->per_dir_config, &deflate_module);
       
   151  
       
   152      if (!ctx) {
       
   153          char deflate_hdr[10];
       
   154 @@ -803,11 +891,13 @@
       
   155          if (len != 10 ||
       
   156              deflate_hdr[0] != deflate_magic[0] ||
       
   157              deflate_hdr[1] != deflate_magic[1]) {
       
   158 +            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Failed to inflate input: wrong/partial magic bytes");
       
   159              return APR_EGENERAL;
       
   160          }
       
   161  
       
   162          /* We can't handle flags for now. */
       
   163          if (deflate_hdr[3] != 0) {
       
   164 +            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Failed to inflate input: cannot handle deflate flags");
       
   165              return APR_EGENERAL;
       
   166          }
       
   167  
       
   168 @@ -831,6 +921,12 @@
       
   169          apr_brigade_cleanup(ctx->bb);
       
   170      }
       
   171  
       
   172 +    inflate_limit = dc->inflate_limit; 
       
   173 +    if (inflate_limit == 0) { 
       
   174 +        /* The core is checking the deflated body, we'll check the inflated */
       
   175 +        inflate_limit = ap_get_limit_req_body(f->r);
       
   176 +    }
       
   177 +
       
   178      if (APR_BRIGADE_EMPTY(ctx->proc_bb)) {
       
   179          rv = ap_get_brigade(f->next, ctx->bb, mode, block, readbytes);
       
   180  
       
   181 @@ -863,6 +959,17 @@
       
   182  
       
   183                  ctx->stream.next_out = ctx->buffer;
       
   184                  len = c->bufferSize - ctx->stream.avail_out;
       
   185 + 
       
   186 +                ctx->inflate_total += len;
       
   187 +                if (inflate_limit && ctx->inflate_total > inflate_limit) { 
       
   188 +                    inflateEnd(&ctx->stream);
       
   189 +                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
       
   190 +                            "Inflated content length of %" APR_OFF_T_FMT
       
   191 +                            " is larger than the configured limit"
       
   192 +                            " of %" APR_OFF_T_FMT, 
       
   193 +                            ctx->inflate_total, inflate_limit);
       
   194 +                    return APR_ENOSPC;
       
   195 +                }
       
   196  
       
   197                  ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
       
   198                  tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
       
   199 @@ -891,6 +998,26 @@
       
   200                      ctx->stream.next_out = ctx->buffer;
       
   201                      len = c->bufferSize - ctx->stream.avail_out;
       
   202  
       
   203 +                      ctx->inflate_total += len;
       
   204 +                      if (inflate_limit && ctx->inflate_total > inflate_limit) { 
       
   205 +                          inflateEnd(&ctx->stream);
       
   206 +                          ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
       
   207 +                                  "Inflated content length of %" APR_OFF_T_FMT
       
   208 +                                  " is larger than the configured limit"
       
   209 +                                  " of %" APR_OFF_T_FMT, 
       
   210 +                                  ctx->inflate_total, inflate_limit);
       
   211 +                          return APR_ENOSPC;
       
   212 +                      }
       
   213 +
       
   214 +                      if (!check_ratio(r, ctx, dc)) {
       
   215 +                          inflateEnd(&ctx->stream);
       
   216 +                          ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
       
   217 +                                  "Inflated content ratio is larger than the "
       
   218 +                                  "configured limit %i by %i time(s)",
       
   219 +                                  dc->ratio_limit, dc->ratio_burst);
       
   220 +                          return APR_EINVAL;
       
   221 +                      }
       
   222 +
       
   223                      ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
       
   224                      tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
       
   225                                                        NULL, f->c->bucket_alloc);
       
   226 @@ -1003,6 +1130,7 @@
       
   227      int zRC;
       
   228      apr_status_t rv;
       
   229      deflate_filter_config *c;
       
   230 +    deflate_dirconf_t *dc;
       
   231  
       
   232      /* Do nothing if asked to filter nothing. */
       
   233      if (APR_BRIGADE_EMPTY(bb)) {
       
   234 @@ -1010,6 +1138,7 @@
       
   235      }
       
   236  
       
   237      c = ap_get_module_config(r->server->module_config, &deflate_module);
       
   238 +    dc = ap_get_module_config(r->per_dir_config, &deflate_module);
       
   239  
       
   240      if (!ctx) {
       
   241  
       
   242 @@ -1272,6 +1401,14 @@
       
   243          while (ctx->stream.avail_in != 0) {
       
   244              if (ctx->stream.avail_out == 0) {
       
   245  
       
   246 +                if (!check_ratio(r, ctx, dc)) {
       
   247 +                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
       
   248 +                            "Inflated content ratio is larger than the "
       
   249 +                            "configured limit %i by %i time(s)",
       
   250 +                            dc->ratio_limit, dc->ratio_burst);
       
   251 +                    return APR_EINVAL;
       
   252 +                }
       
   253 +
       
   254                  ctx->stream.next_out = ctx->buffer;
       
   255                  len = c->bufferSize - ctx->stream.avail_out;
       
   256  
       
   257 @@ -1346,12 +1483,20 @@
       
   258                    "Set the Deflate Memory Level (1-9)"),
       
   259      AP_INIT_TAKE1("DeflateCompressionLevel", deflate_set_compressionlevel, NULL, RSRC_CONF,
       
   260                    "Set the Deflate Compression Level (1-9)"),
       
   261 +    AP_INIT_TAKE1("DeflateInflateLimitRequestBody", deflate_set_inflate_limit, NULL, OR_ALL,
       
   262 +                  "Set a limit on size of inflated input"),
       
   263 +    AP_INIT_TAKE1("DeflateInflateRatioLimit", deflate_set_inflate_ratio_limit, NULL, OR_ALL,
       
   264 +                  "Set the inflate ratio limit above which inflation is "
       
   265 +                  "aborted (default: " APR_STRINGIFY(AP_INFLATE_RATIO_LIMIT) ")"),
       
   266 +    AP_INIT_TAKE1("DeflateInflateRatioBurst", deflate_set_inflate_ratio_burst, NULL, OR_ALL,
       
   267 +                  "Set the maximum number of following inflate ratios above limit "
       
   268 +                  "(default: " APR_STRINGIFY(AP_INFLATE_RATIO_BURST) ")"),
       
   269      {NULL}
       
   270  };
       
   271  
       
   272  module AP_MODULE_DECLARE_DATA deflate_module = {
       
   273      STANDARD20_MODULE_STUFF,
       
   274 -    NULL,                         /* dir config creater */
       
   275 +    create_deflate_dirconf,       /* dir config creater */
       
   276      NULL,                         /* dir merger --- default is to override */
       
   277      create_deflate_server_config, /* server config */
       
   278      NULL,                         /* merge server config */