Path from Jeff Trawick: > Attached is a patch to trunk that allows you to hook in to the stat > calls from directory walk. Call apr_stat() like core_dirwalk_stat() > but check for APR_STATUS_IS_EACCES(rv) and decide whether to run > lingering close and exit. Let us know how that goes. Backported to Apache 2.4.2. Index: httpd-2.4.2/server/core.c =================================================================== --- httpd-2.4.2.orig/server/core.c +++ httpd-2.4.2/server/core.c @@ -4779,6 +4779,12 @@ static apr_status_t core_insert_network_ return APR_SUCCESS; } +static apr_status_t core_dirwalk_stat(apr_finfo_t *finfo, request_rec *r, + apr_int32_t wanted) +{ + return apr_stat(finfo, r->filename, wanted, r->pool); +} + static void core_dump_config(apr_pool_t *p, server_rec *s) { core_server_config *sconf = ap_get_core_module_config(s->module_config); @@ -4855,7 +4861,8 @@ static void register_hooks(apr_pool_t *p ap_hook_child_status(ap_core_child_status, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_insert_network_bucket(core_insert_network_bucket, NULL, NULL, APR_HOOK_REALLY_LAST); - + ap_hook_dirwalk_stat(core_dirwalk_stat, NULL, NULL, APR_HOOK_REALLY_LAST); + /* register the core's insert_filter hook and register core-provided * filters */ Index: httpd-2.4.2/server/request.c =================================================================== --- httpd-2.4.2.orig/server/request.c +++ httpd-2.4.2/server/request.c @@ -70,6 +70,7 @@ APR_HOOK_STRUCT( APR_HOOK_LINK(insert_filter) APR_HOOK_LINK(create_request) APR_HOOK_LINK(post_perdir_config) + APR_HOOK_LINK(dirwalk_stat) ) AP_IMPLEMENT_HOOK_RUN_FIRST(int,translate_name, @@ -91,6 +92,9 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int,auth_che AP_IMPLEMENT_HOOK_VOID(insert_filter, (request_rec *r), (r)) AP_IMPLEMENT_HOOK_RUN_ALL(int, create_request, (request_rec *r), (r), OK, DECLINED) +AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t,dirwalk_stat, + (apr_finfo_t *finfo, request_rec *r, apr_int32_t wanted), + (finfo, r, wanted), AP_DECLINED) /** * This hook allows modules to affect the request immediately after the @@ -621,7 +625,7 @@ AP_DECLARE(int) ap_directory_walk(reques * with APR_ENOENT, knowing that the path is good. */ if (r->finfo.filetype == APR_NOFILE || r->finfo.filetype == APR_LNK) { - rv = apr_stat(&r->finfo, r->filename, APR_FINFO_MIN, r->pool); + rv = ap_run_dirwalk_stat(&r->finfo, r, APR_FINFO_MIN); /* some OSs will return APR_SUCCESS/APR_REG if we stat * a regular file but we have '/' at the end of the name; @@ -687,9 +691,8 @@ AP_DECLARE(int) ap_directory_walk(reques * check. */ if (!(opts & OPT_SYM_LINKS)) { - rv = apr_stat(&thisinfo, r->filename, - APR_FINFO_MIN | APR_FINFO_NAME | APR_FINFO_LINK, - r->pool); + rv = ap_run_dirwalk_stat(&thisinfo, r, + APR_FINFO_MIN | APR_FINFO_NAME | APR_FINFO_LINK); /* * APR_INCOMPLETE is as fine as result as APR_SUCCESS as we * have added APR_FINFO_NAME to the wanted parameter of @@ -1104,9 +1107,8 @@ AP_DECLARE(int) ap_directory_walk(reques * the name of its target, if we are fixing the filename * case/resolving aliases. */ - rv = apr_stat(&thisinfo, r->filename, - APR_FINFO_MIN | APR_FINFO_NAME | APR_FINFO_LINK, - r->pool); + rv = ap_run_dirwalk_stat(&thisinfo, r, + APR_FINFO_MIN | APR_FINFO_NAME | APR_FINFO_LINK); if (APR_STATUS_IS_ENOENT(rv)) { /* Nothing? That could be nice. But our directory Index: httpd-2.4.2/include/http_request.h =================================================================== --- httpd-2.4.2.orig/include/http_request.h +++ httpd-2.4.2/include/http_request.h @@ -528,6 +528,15 @@ AP_DECLARE(void) ap_hook_check_authz(ap_ */ AP_DECLARE_HOOK(void,insert_filter,(request_rec *r)) +/** + * This hook allows modules to handle/emulate the apr_stat() calls + * needed for directory walk. + * @param r The current request + * @return apr_status_t or AP_DECLINED (let later modules decide) + * @ingroup hooks + */ +AP_DECLARE_HOOK(apr_status_t,dirwalk_stat,(apr_finfo_t *finfo, request_rec *r, apr_int32_t wanted)) + AP_DECLARE(int) ap_location_walk(request_rec *r); AP_DECLARE(int) ap_directory_walk(request_rec *r); AP_DECLARE(int) ap_file_walk(request_rec *r);