httpd/SOURCES/httpd-2.4.37-CVE-2024-38476.patch

302 lines
12 KiB
Diff

-- backported bnotes needed by this CVE fix from https://svn.apache.org/viewvc?view=revision&revision=1887384
-- modified it a little bit so it actually doesn't store bnotes into req structure to not brake compatibility
-- but it stores AP_REQUEST_TRUSTED_CT info into r->notes
diff --git a/include/http_protocol.h b/include/http_protocol.h
index 8ed77ac..81949ca 100644
--- a/include/http_protocol.h
+++ b/include/http_protocol.h
@@ -402,6 +402,17 @@ AP_DECLARE(void) ap_clear_method_list(ap_method_list_t *l);
*/
AP_DECLARE(void) ap_set_content_type(request_rec *r, const char *ct);
+/**
+ * Set the content type for this request (r->content_type).
+ * @param r The current request
+ * @param ct The new content type
+ * @param trusted If non-zero, The content-type should come from a
+ * trusted source such as server configuration rather
+ * than application output.
+ * for the AddOutputFilterByType directive to work correctly.
+ */
+AP_DECLARE(void) ap_set_content_type_ex(request_rec *r, const char *ct, int trusted);
+
/**
* Set the Accept-Ranges header for this response
* @param r The current request
diff --git a/include/httpd.h b/include/httpd.h
index 99f7f04..d8746c1 100644
--- a/include/httpd.h
+++ b/include/httpd.h
@@ -645,6 +645,7 @@ struct ap_method_list_t {
/** the array used for extension methods */
apr_array_header_t *method_list;
};
+/** @} */
/**
* @defgroup module_magic Module Magic mime types
@@ -715,6 +716,31 @@ struct ap_method_list_t {
/** @} // values_request_rec_used_path_info */
+#define AP_REQUEST_TRUSTED_CT "rh-bnotes-trusted-ct"
+
+/**
+ * This is a convenience macro to ease with getting specific request
+ * binary notes.
+ */
+#define AP_REQUEST_GET_BNOTE(r, mask) (apr_table_get(r->notes, mask) ? 1 : 0)
+
+/**
+ * This is a convenience macro to ease with setting specific request
+ * binary notes.
+ */
+#define AP_REQUEST_SET_BNOTE(r, mask, val) do { \
+ if (val) \
+ apr_table_setn(r->notes, mask, "1"); \
+ else \
+ apr_table_unset(r->notes, mask); \
+} while (0)
+
+/**
+ * Returns true if the content-type field is from a trusted source
+ */
+#define AP_REQUEST_IS_TRUSTED_CT(r) \
+ (!!AP_REQUEST_GET_BNOTE((r), AP_REQUEST_TRUSTED_CT))
+/** @} */
/*
* Things which may vary per file-lookup WITHIN a request ---
diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c
index df862e0..d003aea 100644
--- a/modules/http/http_protocol.c
+++ b/modules/http/http_protocol.c
@@ -1077,8 +1077,14 @@ AP_DECLARE(void) ap_set_content_type(request_rec *r, const char *ct)
}
else if (!r->content_type || strcmp(r->content_type, ct)) {
r->content_type = ct;
+ AP_REQUEST_SET_BNOTE(r, AP_REQUEST_TRUSTED_CT, 0);
}
}
+AP_DECLARE(void) ap_set_content_type_ex(request_rec *r, const char *ct, int trusted)
+{
+ ap_set_content_type(r, ct);
+ AP_REQUEST_SET_BNOTE(r, AP_REQUEST_TRUSTED_CT, trusted ? AP_REQUEST_TRUSTED_CT : 0);
+}
AP_DECLARE(void) ap_set_accept_ranges(request_rec *r)
{
diff --git a/modules/http/mod_mime.c b/modules/http/mod_mime.c
index 28c53be..4cd1c48 100644
--- a/modules/http/mod_mime.c
+++ b/modules/http/mod_mime.c
@@ -759,7 +759,7 @@ static int find_ct(request_rec *r)
int found_metadata = 0;
if (r->finfo.filetype == APR_DIR) {
- ap_set_content_type(r, DIR_MAGIC_TYPE);
+ ap_set_content_type_ex(r, DIR_MAGIC_TYPE, 1);
return OK;
}
@@ -837,7 +837,7 @@ static int find_ct(request_rec *r)
if (exinfo == NULL || !exinfo->forced_type) {
if ((type = apr_hash_get(mime_type_extensions, ext,
APR_HASH_KEY_STRING)) != NULL) {
- ap_set_content_type(r, (char*) type);
+ ap_set_content_type_ex(r, (char*) type, 1);
found = 1;
}
}
@@ -846,7 +846,7 @@ static int find_ct(request_rec *r)
/* empty string is treated as special case for RemoveType */
if (exinfo->forced_type && *exinfo->forced_type) {
- ap_set_content_type(r, exinfo->forced_type);
+ ap_set_content_type_ex(r, exinfo->forced_type, 1);
found = 1;
}
@@ -951,33 +951,33 @@ static int find_ct(request_rec *r)
memcpy(tmp, ctp->subtype, ctp->subtype_len);
tmp += ctp->subtype_len;
*tmp = 0;
- ap_set_content_type(r, base_content_type);
+ ap_set_content_type_ex(r, base_content_type, AP_REQUEST_IS_TRUSTED_CT(r));
while (pp != NULL) {
if (charset && !strcmp(pp->attr, "charset")) {
if (!override) {
- ap_set_content_type(r,
+ ap_set_content_type_ex(r,
apr_pstrcat(r->pool,
r->content_type,
"; charset=",
charset,
- NULL));
+ NULL), AP_REQUEST_IS_TRUSTED_CT(r));
override = 1;
}
}
else {
- ap_set_content_type(r,
+ ap_set_content_type_ex(r,
apr_pstrcat(r->pool,
r->content_type,
"; ", pp->attr,
"=", pp->val,
- NULL));
+ NULL), AP_REQUEST_IS_TRUSTED_CT(r));
}
pp = pp->next;
}
if (charset && !override) {
- ap_set_content_type(r, apr_pstrcat(r->pool, r->content_type,
+ ap_set_content_type_ex(r, apr_pstrcat(r->pool, r->content_type,
"; charset=", charset,
- NULL));
+ NULL), AP_REQUEST_IS_TRUSTED_CT(r));
}
}
}
diff --git a/modules/mappers/mod_actions.c b/modules/mappers/mod_actions.c
index ac9c3b7..5e398b5 100644
--- a/modules/mappers/mod_actions.c
+++ b/modules/mappers/mod_actions.c
@@ -182,8 +182,10 @@ static int action_handler(request_rec *r)
return DECLINED;
/* Second, check for actions (which override the method scripts) */
- action = r->handler ? r->handler :
- ap_field_noparam(r->pool, r->content_type);
+ action = r->handler;
+ if (!action && AP_REQUEST_IS_TRUSTED_CT(r)) {
+ action = ap_field_noparam(r->pool, r->content_type);
+ }
if (action && (t = apr_table_get(conf->action_types, action))) {
int virtual = (*t++ == '0' ? 0 : 1);
diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c
index da68353..e91ba5f 100644
--- a/modules/mappers/mod_negotiation.c
+++ b/modules/mappers/mod_negotiation.c
@@ -1169,7 +1169,7 @@ static int read_types_multi(negotiation_state *neg)
* might be doing.
*/
if (sub_req->handler && !sub_req->content_type) {
- ap_set_content_type(sub_req, CGI_MAGIC_TYPE);
+ ap_set_content_type_ex(sub_req, CGI_MAGIC_TYPE, 1);
}
/*
@@ -3008,14 +3008,14 @@ static int handle_map_file(request_rec *r)
/* set MIME type and charset as negotiated */
if (best->mime_type && *best->mime_type) {
if (best->content_charset && *best->content_charset) {
- ap_set_content_type(r, apr_pstrcat(r->pool,
+ ap_set_content_type_ex(r, apr_pstrcat(r->pool,
best->mime_type,
"; charset=",
best->content_charset,
- NULL));
+ NULL), 1);
}
else {
- ap_set_content_type(r, apr_pstrdup(r->pool, best->mime_type));
+ ap_set_content_type_ex(r, apr_pstrdup(r->pool, best->mime_type), 1);
}
}
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
index a25c7ae..2b70d66 100644
--- a/modules/mappers/mod_rewrite.c
+++ b/modules/mappers/mod_rewrite.c
@@ -5477,7 +5477,7 @@ static int hook_mimetype(request_rec *r)
rewritelog((r, 1, NULL, "force filename %s to have MIME-type '%s'",
r->filename, t));
- ap_set_content_type(r, t);
+ ap_set_content_type_ex(r, t, 1);
}
/* handler */
diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c
index 1ea970d..55ab281 100644
--- a/modules/metadata/mod_headers.c
+++ b/modules/metadata/mod_headers.c
@@ -792,14 +792,14 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers,
break;
case hdr_set:
if (!strcasecmp(hdr->header, "Content-Type")) {
- ap_set_content_type(r, process_tags(hdr, r));
+ ap_set_content_type_ex(r, process_tags(hdr, r), 1);
}
apr_table_setn(headers, hdr->header, process_tags(hdr, r));
break;
case hdr_setifempty:
if (NULL == apr_table_get(headers, hdr->header)) {
if (!strcasecmp(hdr->header, "Content-Type")) {
- ap_set_content_type(r, process_tags(hdr, r));
+ ap_set_content_type_ex(r, process_tags(hdr, r), 1);
}
apr_table_setn(headers, hdr->header, process_tags(hdr, r));
}
@@ -818,7 +818,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers,
const char *repl = process_regexp(hdr, r->content_type, r);
if (repl == NULL)
return 0;
- ap_set_content_type(r, repl);
+ ap_set_content_type_ex(r, repl, 1);
}
if (apr_table_get(headers, hdr->header)) {
edit_do ed;
diff --git a/modules/metadata/mod_mime_magic.c b/modules/metadata/mod_mime_magic.c
index c12529a..fe30f27 100644
--- a/modules/metadata/mod_mime_magic.c
+++ b/modules/metadata/mod_mime_magic.c
@@ -789,7 +789,7 @@ static int magic_rsl_to_request(request_rec *r)
/* XXX: this could be done at config time I'm sure... but I'm
* confused by all this magic_rsl stuff. -djg */
ap_content_type_tolower(tmp);
- ap_set_content_type(r, tmp);
+ ap_set_content_type_ex(r, tmp, 1);
if (state == rsl_encoding) {
tmp = rsl_strdup(r, encoding_frag,
@@ -2326,7 +2326,7 @@ static int revision_suffix(request_rec *r)
/* extract content type/encoding/language from sub-request */
if (sub->content_type) {
- ap_set_content_type(r, apr_pstrdup(r->pool, sub->content_type));
+ ap_set_content_type_ex(r, apr_pstrdup(r->pool, sub->content_type), 1);
#if MIME_MAGIC_DEBUG
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01557)
MODNAME ": subrequest %s got %s",
diff --git a/server/config.c b/server/config.c
index f815b22..fc4d76b 100644
--- a/server/config.c
+++ b/server/config.c
@@ -419,7 +419,7 @@ AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r)
}
if (!r->handler) {
- if (r->content_type) {
+ if (r->content_type && AP_REQUEST_IS_TRUSTED_CT(r)) {
handler = r->content_type;
if ((p=ap_strchr_c(handler, ';')) != NULL) {
char *new_handler = (char *)apr_pmemdup(r->pool, handler,
diff --git a/server/core.c b/server/core.c
index 8575aae..82706cf 100644
--- a/server/core.c
+++ b/server/core.c
@@ -4722,7 +4722,7 @@ static int core_override_type(request_rec *r)
/* Check for overrides with ForceType / SetHandler
*/
if (conf->mime_type && strcmp(conf->mime_type, "none"))
- ap_set_content_type(r, (char*) conf->mime_type);
+ ap_set_content_type_ex(r, (char*) conf->mime_type, 1);
if (conf->expr_handler) {
const char *err;