Fix an issue where users can sometimes get spurious 403s on persistent connections (the description in the comments explains the logic). This would particularly hit people with reverse proxies, since these have a higher tendency of accessing things from different vhosts in the same connection. Index: httpd-2.4.1/server/config.c =================================================================== --- httpd-2.4.1.orig/server/config.c +++ httpd-2.4.1/server/config.c @@ -68,6 +68,8 @@ AP_DECLARE_DATA apr_array_header_t *ap_s AP_DECLARE_DATA ap_directive_t *ap_conftree = NULL; +AP_DECLARE_DATA int ap_running_under_mpm_itk = 0; + APR_HOOK_STRUCT( APR_HOOK_LINK(header_parser) APR_HOOK_LINK(pre_config) @@ -2109,6 +2111,32 @@ AP_CORE_DECLARE(int) ap_parse_htaccess(a else { if (!APR_STATUS_IS_ENOENT(status) && !APR_STATUS_IS_ENOTDIR(status)) { + /* + * If we are in a persistent connection, we might end up in a state + * where we can no longer read .htaccess files because we have already + * setuid(). This can either be because the previous request was for + * another vhost (basically the same problem as when setuid() fails in + * itk.c), or it can be because a .htaccess file is readable only by + * root. + * + * In any case, we don't want to give out a 403, since the request has + * a very real chance of succeeding on a fresh connection (where + * presumably uid=0). Thus, we give up serving the request on this + * TCP connection, and do a hard close of the socket. As long as we're + * in a persistent connection (and there _should_ not be a way this + * would happen on the first request in a connection, save for subrequests, + * which we special-case), this is allowed, as it is what happens on + * a timeout. The browser will simply open a new connection and try + * again (there's of course a performance hit, though, both due to + * the new connection setup and the fork() of a new server child). + */ + if (ap_running_under_mpm_itk && r->main == NULL && getuid() != 0) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, status, r, + "Couldn't read %s, closing connection.", + filename); + ap_lingering_close(r->connection); + exit(0); + } ap_log_rerror(APLOG_MARK, APLOG_CRIT, status, r, APLOGNO(00529) "%s pcfg_openfile: unable to check htaccess file, " "ensure it is readable and that '%s' " Index: httpd-2.4.1/server/mpm/itk/itk.c =================================================================== --- httpd-2.4.1.orig/server/mpm/itk/itk.c +++ httpd-2.4.1/server/mpm/itk/itk.c @@ -179,6 +179,7 @@ typedef struct } itk_server_conf; module AP_MODULE_DECLARE_DATA mpm_itk_module; +extern AP_MODULE_DECLARE_DATA int ap_running_under_mpm_itk; #ifdef GPROF /* @@ -541,6 +542,7 @@ static void child_main(int child_num_arg * child initializes */ + ap_running_under_mpm_itk = 1; my_child_num = child_num_arg; ap_my_pid = getpid(); requests_this_child = 0;