
Changes to Apache core, request and mod_autoindex to use the privilege separated
file io functions. Adds hook functions for privileged wrapper functions so
the module can be optionally compiled in or out.

Index: server/Makefile.in
===================================================================
--- server/Makefile.in	(revision 602639)
+++ server/Makefile.in	(working copy)
@@ -8,7 +8,7 @@
 LTLIBRARY_NAME    = libmain.la
 LTLIBRARY_SOURCES = \
     test_char.h \
-	config.c log.c main.c vhost.c util.c \
+	config.c log.c main.c vhost.c util.c privsep.c \
 	util_script.c util_md5.c util_cfgtree.c util_ebcdic.c util_time.c \
 	connection.c listen.c util_mutex.c \
 	mpm_common.c util_charset.c util_debug.c util_xml.c \
Index: include/privsep.h
===================================================================
--- include/privsep.h	(revision 0)
+++ include/privsep.h	(revision 0)
@@ -0,0 +1,150 @@
+/* Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PRIVSEP_H
+#define PRIVSEP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "apr.h"
+#include "apr_file_io.h"
+
+#ifndef HAVE_PRIVSEP_TOKEN_T
+typedef privsep_token_t;
+#endif
+
+
+/* privsep token functions */
+
+AP_DECLARE(privsep_token_t*) ap_privsep_preauth_stat_token(const request_rec *r);
+
+AP_DECLARE(privsep_token_t*) ap_privsep_token(const request_rec *r);
+
+
+/* apr privileged wrapper functions */
+
+AP_DECLARE(apr_status_t) ap_privsep_stat(privsep_token_t *token,
+					 apr_finfo_t *finfo, 
+					 const char *fname, 
+					 apr_int32_t wanted,
+					 apr_pool_t *pool);
+
+AP_DECLARE(apr_status_t) ap_privsep_file_perms_set(privsep_token_t *token,
+						    const char *fname, 
+						    apr_fileperms_t perms);
+
+AP_DECLARE(apr_status_t) ap_privsep_dir_make(privsep_token_t *token,
+					      const char *path,
+					      apr_fileperms_t perm, 
+					      apr_pool_t *pool);
+
+AP_DECLARE(apr_status_t) ap_privsep_dir_remove(privsep_token_t *token,
+						const char *path,
+						apr_pool_t *pool);
+
+AP_DECLARE(apr_status_t) ap_privsep_file_remove(privsep_token_t *token,
+						 const char *path,
+						 apr_pool_t *pool);
+
+AP_DECLARE(apr_status_t) ap_privsep_file_rename(privsep_token_t *token,
+						 const char *from_path, 
+						 const char *to_path,
+						 apr_pool_t *p);
+
+AP_DECLARE(apr_status_t) ap_privsep_file_open(privsep_token_t *token,
+					       apr_file_t **new, 
+					       const char *fname, 
+					       apr_int32_t flag, 
+					       apr_fileperms_t perm, 
+					       apr_pool_t *pool);
+
+AP_DECLARE(apr_status_t) ap_privsep_dir_open(privsep_token_t *token,
+					      apr_dir_t **new,
+					      const char *dirname, 
+					      apr_pool_t *pool);
+
+AP_DECLARE(apr_status_t) ap_privsep_dir_read(privsep_token_t *token,
+					      apr_finfo_t *finfo,
+					      apr_int32_t wanted,
+					      apr_dir_t *thedir);
+
+/* privileged wrapper typedefs for hook functions */
+
+typedef privsep_token_t* (ap_privsep_preauth_token_fn)(const request_rec *r);
+
+typedef privsep_token_t* (ap_privsep_token_fn)(const request_rec *r);
+
+typedef apr_status_t (ap_privsep_stat_fn)(privsep_token_t *token,
+					  apr_finfo_t *finfo, 
+					  const char *fname, 
+					  apr_int32_t wanted,
+					  apr_pool_t *pool);
+
+typedef apr_status_t (ap_privsep_file_perms_set_fn)(privsep_token_t *token,
+						    const char *fname, 
+						    apr_fileperms_t perms);
+
+typedef apr_status_t (ap_privsep_dir_make_fn)(privsep_token_t *token,
+					      const char *path,
+					      apr_fileperms_t perm, 
+					      apr_pool_t *pool);
+
+typedef apr_status_t (ap_privsep_dir_remove_fn)(privsep_token_t *token,
+						const char *path,
+						apr_pool_t *pool);
+
+typedef apr_status_t (ap_privsep_file_remove_fn)(privsep_token_t *token,
+						 const char *path,
+						 apr_pool_t *pool);
+
+typedef apr_status_t (ap_privsep_file_rename_fn)(privsep_token_t *token,
+						 const char *from_path, 
+						 const char *to_path,
+						 apr_pool_t *p);
+
+typedef apr_status_t (ap_privsep_file_open_fn)(privsep_token_t *token,
+					       apr_file_t **new, 
+					       const char *fname, 
+					       apr_int32_t flag, 
+					       apr_fileperms_t perm, 
+					       apr_pool_t *pool);
+
+typedef apr_status_t (ap_privsep_dir_open_fn)(privsep_token_t *token,
+					      apr_dir_t **new,
+					      const char *dirname, 
+					      apr_pool_t *pool);
+
+typedef apr_status_t (ap_privsep_dir_read_fn)(privsep_token_t *token,
+					      apr_finfo_t *finfo,
+					      apr_int32_t wanted,
+					      apr_dir_t *thedir);
+
+/* privsep apr file io dispatch hook structure */
+
+typedef struct {
+    ap_privsep_preauth_token_fn   *get_preauth_token;
+    ap_privsep_token_fn           *get_token;
+    ap_privsep_stat_fn            *stat;
+    ap_privsep_file_perms_set_fn  *file_perms_set;
+    ap_privsep_dir_make_fn        *dir_make;
+    ap_privsep_dir_remove_fn      *dir_remove;
+    ap_privsep_file_remove_fn     *file_remove;
+    ap_privsep_file_rename_fn     *file_rename;
+    ap_privsep_file_open_fn       *file_open;
+    ap_privsep_dir_open_fn        *dir_open;
+    ap_privsep_dir_read_fn        *dir_read;
+} ap_privsep_hooks_t;
+
+#endif
Index: include/http_request.h
===================================================================
--- include/http_request.h	(revision 602639)
+++ include/http_request.h	(working copy)
@@ -270,6 +270,14 @@
 AP_DECLARE_HOOK(int,create_request,(request_rec *r))
 
 /**
+ * Gives modules a chance to add any information to a subrequest from the
+ * parent request when it is created.
+ * @param r The current request
+ * @ingroup hooks
+ */
+AP_DECLARE_HOOK(int,create_subrequest,(request_rec *rnew, const request_rec *r))
+
+/**
  * This hook allow modules an opportunity to translate the URI into an
  * actual filename.  If no modules do anything special, the server's default
  * rules will be followed.
Index: server/privsep.c
===================================================================
--- server/privsep.c	(revision 0)
+++ server/privsep.c	(revision 0)
@@ -0,0 +1,155 @@
+/* Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_file_io.h"
+
+#include "httpd.h"
+
+#include "privsep.h"
+
+
+static ap_privsep_hooks_t *hook = NULL;
+
+
+/* set hooks for a privsep module to intercept token requests and apr file io */
+
+APR_DECLARE(void) ap_privsep_set_hooks(ap_privsep_hooks_t *hooks)
+{
+    hook = hooks;
+}
+
+
+/* hookable privsep token functions */
+
+/* returns special preauth stat token for use in ap_directory_walk before
+   any authentication has been performed */
+AP_DECLARE(privsep_token_t*) ap_privsep_preauth_stat_token(const request_rec *r)
+{
+    if(hook && hook->get_preauth_token)
+	return hook->get_preauth_token(r);
+    else
+	return NULL;
+}
+
+/* returns the privileged token associated with the request by using
+   authentication context information from the request */
+AP_DECLARE(privsep_token_t*) ap_privsep_token(const request_rec *r)
+{
+    if(hook && hook->get_token)
+	return hook->get_token(r);
+    else
+	return NULL;
+}
+
+
+/* apr hookable privileged wrapper functions */
+
+APR_DECLARE(apr_status_t) ap_privsep_stat(privsep_token_t *token,
+					  apr_finfo_t *finfo, 
+					  const char *fname, 
+					  apr_int32_t wanted,
+					  apr_pool_t *pool)
+{
+    if(hook && hook->stat)
+	return hook->stat(token, finfo, fname, wanted, pool);
+    else
+	return apr_stat(finfo, fname, wanted, pool);
+}
+
+APR_DECLARE(apr_status_t) ap_privsep_file_perms_set(privsep_token_t *token,
+						    const char *fname, 
+						    apr_fileperms_t perms)
+{
+    if(hook && hook->file_perms_set)
+	return hook->file_perms_set(token, fname, perms);
+    else
+	return apr_file_perms_set(fname, perms);
+}
+
+APR_DECLARE(apr_status_t) ap_privsep_dir_make(privsep_token_t *token,
+					      const char *path,
+					      apr_fileperms_t perm, 
+					      apr_pool_t *pool)
+{
+    if(hook && hook->dir_make)
+	return hook->dir_make(token, path, perm, pool);
+    else
+	return apr_dir_make(path, perm, pool);
+}
+
+APR_DECLARE(apr_status_t) ap_privsep_dir_remove(privsep_token_t *token,
+						const char *path,
+						apr_pool_t *pool)
+{
+    if(hook && hook->dir_remove)
+	return hook->dir_remove(token, path, pool);
+    else
+	return apr_dir_remove(path, pool);
+}
+
+APR_DECLARE(apr_status_t) ap_privsep_file_remove(privsep_token_t *token,
+						 const char *path,
+						 apr_pool_t *pool)
+{
+    if(hook && hook->file_remove)
+	return hook->file_remove(token, path, pool);
+    else
+	return apr_file_remove(path, pool);
+}
+
+APR_DECLARE(apr_status_t) ap_privsep_file_rename(privsep_token_t *token,
+						 const char *from_path, 
+						 const char *to_path,
+						 apr_pool_t *p)
+{
+    if(hook && hook->file_rename)
+	return hook->file_rename(token, from_path, to_path, p);
+    else
+	return apr_file_rename(from_path, to_path, p);  
+}
+
+APR_DECLARE(apr_status_t) ap_privsep_file_open(privsep_token_t *token,
+					       apr_file_t **new, 
+					       const char *fname, 
+					       apr_int32_t flag, 
+					       apr_fileperms_t perm, 
+					       apr_pool_t *pool)
+{
+    if(hook && hook->file_open)
+	return hook->file_open(token, new, fname, flag, perm, pool);
+    else
+	return apr_file_open(new, fname, flag, perm, pool);
+}
+
+APR_DECLARE(apr_status_t) ap_privsep_dir_open(privsep_token_t *token,
+					      apr_dir_t **new,
+					      const char *dirname, 
+					      apr_pool_t *pool)
+{
+    if(hook && hook->dir_open)
+	return hook->dir_open(token, new, dirname, pool);
+    else
+	return apr_dir_open(new, dirname, pool);
+}
+
+APR_DECLARE(apr_status_t) ap_privsep_dir_read(privsep_token_t *token,
+					      apr_finfo_t *finfo,
+					      apr_int32_t wanted,
+					      apr_dir_t *thedir)
+{
+    if(hook && hook->dir_read)
+	return hook->dir_read(token, finfo, wanted, thedir);
+    else
+	return apr_dir_read(finfo, wanted, thedir);
+}
Index: server/core.c
===================================================================
--- server/core.c	(revision 602639)
+++ server/core.c	(working copy)
@@ -3600,7 +3600,9 @@
         }
 
 
-        if ((status = apr_file_open(&fd, r->filename, APR_READ | APR_BINARY
+        if ((status = ap_privsep_file_open(ap_privsep_token(r),
+					   &fd, r->filename,
+					   APR_READ | APR_BINARY
 #if APR_HAS_SENDFILE
                             | ((d->enable_sendfile == ENABLE_SENDFILE_OFF)
                                                 ? 0 : APR_SENDFILE_ENABLED)
Index: server/request.c
===================================================================
--- server/request.c	(revision 602639)
+++ server/request.c	(working copy)
@@ -44,6 +44,7 @@
 #include "util_filter.h"
 #include "util_charset.h"
 #include "util_script.h"
+#include "privsep.h"
 
 #include "mod_core.h"
 
@@ -61,6 +62,7 @@
     APR_HOOK_LINK(auth_checker)
     APR_HOOK_LINK(insert_filter)
     APR_HOOK_LINK(create_request)
+    APR_HOOK_LINK(create_subrequest)
 )
 
 AP_IMPLEMENT_HOOK_RUN_FIRST(int,translate_name,
@@ -80,6 +82,8 @@
 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_ALL(int, create_subrequest,
+                          (request_rec *rnew, const request_rec *r), (rnew, r), OK, DECLINED)
 
 
 static int decl_die(int status, char *phase, request_rec *r)
@@ -318,7 +322,7 @@
  * we start off with an lstat().  Every lstat() must be dereferenced in case
  * it points at a 'nasty' - we must always rerun check_safe_file (or similar.)
  */
-static int resolve_symlink(char *d, apr_finfo_t *lfi, int opts, apr_pool_t *p)
+static int resolve_symlink(const request_rec *r, char *d, apr_finfo_t *lfi, int opts, apr_pool_t *p)
 {
     apr_finfo_t fi;
     int res;
@@ -332,7 +336,8 @@
     savename = (lfi->valid & APR_FINFO_NAME) ? lfi->name : NULL;
 
     if (opts & OPT_SYM_LINKS) {
-        if ((res = apr_stat(&fi, d, lfi->valid & ~(APR_FINFO_NAME
+	if ((res = ap_privsep_stat(ap_privsep_token(r), &fi, d,
+				   lfi->valid & ~(APR_FINFO_NAME
                                                  | APR_FINFO_LINK), p))
                  != APR_SUCCESS) {
             return HTTP_FORBIDDEN;
@@ -353,14 +358,15 @@
      * owner of the symlink, then get the info of the target.
      */
     if (!(lfi->valid & APR_FINFO_OWNER)) {
-        if ((res = apr_stat(&fi, d,
+        if ((res = ap_privsep_stat(ap_privsep_token(r), &fi, d,
                             lfi->valid | APR_FINFO_LINK | APR_FINFO_OWNER, p))
             != APR_SUCCESS) {
             return HTTP_FORBIDDEN;
         }
     }
 
-    if ((res = apr_stat(&fi, d, lfi->valid & ~(APR_FINFO_NAME), p))
+    if ((res = ap_privsep_stat(ap_privsep_token(r), &fi, d,
+			       lfi->valid & ~(APR_FINFO_NAME), p))
         != APR_SUCCESS) {
         return HTTP_FORBIDDEN;
     }
@@ -501,7 +507,8 @@
      * with APR_ENOENT, knowing that the path is good.
      */
     if (!r->finfo.filetype || r->finfo.filetype == APR_LNK) {
-        rv = apr_stat(&r->finfo, r->filename, APR_FINFO_MIN, r->pool);
+        rv = ap_privsep_stat(ap_privsep_preauth_stat_token(r),
+			     &r->finfo, r->filename, APR_FINFO_MIN, r->pool);
 
         /* some OSs will return APR_SUCCESS/APR_REG if we stat
          * a regular file but we have '/' at the end of the name;
@@ -567,9 +574,10 @@
              * check.
              */
             if (!(opts & OPT_SYM_LINKS)) {
-                rv = apr_stat(&thisinfo, r->filename,
+                rv = ap_privsep_stat(ap_privsep_preauth_stat_token(r),
+				     &thisinfo, r->filename,
                               APR_FINFO_MIN | APR_FINFO_NAME | APR_FINFO_LINK,
-                              r->pool);
+				     r->pool);
                 /*
                  * APR_INCOMPLETE is as fine as result as APR_SUCCESS as we
                  * have added APR_FINFO_NAME to the wanted parameter of
@@ -593,7 +601,7 @@
                 }
                 if (thisinfo.filetype == APR_LNK) {
                     /* Is this a possibly acceptable symlink? */
-                    if ((res = resolve_symlink(r->filename, &thisinfo,
+                    if ((res = resolve_symlink(r, r->filename, &thisinfo,
                                                opts, r->pool)) != OK) {
                         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                                       "Symbolic link not allowed "
@@ -977,9 +985,10 @@
              * 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_privsep_stat(ap_privsep_preauth_stat_token(r),
+				 &thisinfo, r->filename,
+				 APR_FINFO_MIN | APR_FINFO_NAME | APR_FINFO_LINK,
+				 r->pool);
 
             if (APR_STATUS_IS_ENOENT(rv)) {
                 /* Nothing?  That could be nice.  But our directory
@@ -1018,7 +1027,7 @@
             if (thisinfo.filetype == APR_LNK) {
                 /* Is this a possibly acceptable symlink?
                  */
-                if ((res = resolve_symlink(r->filename, &thisinfo,
+                if ((res = resolve_symlink(r, r->filename, &thisinfo,
                                            opts.opts, r->pool)) != OK) {
                     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                                   "Symbolic link not allowed "
@@ -1561,6 +1570,7 @@
      * or the r->main pointer won't be setup
      */
     ap_run_create_request(rnew);
+    ap_run_create_subrequest(rnew, r);
 
     /* Begin by presuming any module can make its own path_info assumptions,
      * until some module interjects and changes the value.
@@ -1735,16 +1745,18 @@
          */
         apr_status_t rv;
         if (ap_allow_options(rnew) & OPT_SYM_LINKS) {
-            if (((rv = apr_stat(&rnew->finfo, rnew->filename,
-                                APR_FINFO_MIN, rnew->pool)) != APR_SUCCESS)
+            if (((rv = ap_privsep_stat(ap_privsep_token(r),
+				       &rnew->finfo, rnew->filename,
+				       APR_FINFO_MIN, rnew->pool)) != APR_SUCCESS)
                 && (rv != APR_INCOMPLETE)) {
                 rnew->finfo.filetype = 0;
             }
         }
         else {
-            if (((rv = apr_stat(&rnew->finfo, rnew->filename,
-                                APR_FINFO_LINK | APR_FINFO_MIN,
-                                rnew->pool)) != APR_SUCCESS)
+            if (((rv = ap_privsep_stat(ap_privsep_token(r),
+				       &rnew->finfo, rnew->filename,
+				       APR_FINFO_LINK | APR_FINFO_MIN,
+				       rnew->pool)) != APR_SUCCESS)
                 && (rv != APR_INCOMPLETE)) {
                 rnew->finfo.filetype = 0;
             }
@@ -1758,7 +1770,7 @@
         /*
          * Resolve this symlink.  We should tie this back to dir_walk's cache
          */
-        if ((res = resolve_symlink(rnew->filename, &rnew->finfo,
+        if ((res = resolve_symlink(r, rnew->filename, &rnew->finfo,
                                    ap_allow_options(rnew), rnew->pool))
             != OK) {
             rnew->status = res;
@@ -1841,16 +1853,18 @@
         && ap_strchr_c(rnew->filename + fdirlen, '/') == NULL) {
         apr_status_t rv;
         if (ap_allow_options(rnew) & OPT_SYM_LINKS) {
-            if (((rv = apr_stat(&rnew->finfo, rnew->filename,
-                                APR_FINFO_MIN, rnew->pool)) != APR_SUCCESS)
+            if (((rv = ap_privsep_stat(ap_privsep_token(r),
+				       &rnew->finfo, rnew->filename,
+				       APR_FINFO_MIN, rnew->pool)) != APR_SUCCESS)
                 && (rv != APR_INCOMPLETE)) {
                 rnew->finfo.filetype = 0;
             }
         }
         else {
-            if (((rv = apr_stat(&rnew->finfo, rnew->filename,
-                                APR_FINFO_LINK | APR_FINFO_MIN,
-                                rnew->pool)) != APR_SUCCESS)
+            if (((rv = ap_privsep_stat(ap_privsep_token(r),
+                                       &rnew->finfo, rnew->filename,
+                                       APR_FINFO_LINK | APR_FINFO_MIN,
+                                       rnew->pool)) != APR_SUCCESS)
                 && (rv != APR_INCOMPLETE)) {
                 rnew->finfo.filetype = 0;
             }
Index: modules/generators/mod_autoindex.c
===================================================================
--- modules/generators/mod_autoindex.c	(revision 602639)
+++ modules/generators/mod_autoindex.c	(working copy)
@@ -44,6 +44,7 @@
 #include "util_script.h"
 
 #include "mod_core.h"
+#include "privsep.h"
 
 module AP_MODULE_DECLARE_DATA autoindex_module;
 
@@ -1072,8 +1073,9 @@
                  * the file's contents, any HTML header it had won't end up
                  * where it belongs.
                  */
-                if (apr_file_open(&f, rr->filename, APR_READ,
-                                  APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
+                 if (ap_privsep_file_open(ap_privsep_token(r),
+                                          &f, rr->filename, APR_READ,
+                                          APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
                     emit_preamble(r, emit_xhtml, title);
                     emit_amble = 0;
                     do_emit_plain(r, f);
@@ -1157,8 +1159,9 @@
                 /*
                  * If we can open the file, suppress the signature.
                  */
-                if (apr_file_open(&f, rr->filename, APR_READ,
-                                  APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
+                if (ap_privsep_file_open(ap_privsep_token(r),
+                                         &f, rr->filename, APR_READ,
+                                         APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
                     do_emit_plain(r, f);
                     apr_file_close(f);
                     suppress_sig = 1;
@@ -1194,8 +1197,9 @@
                         "text/html")
             || !strcmp(r->content_type, INCLUDES_MAGIC_TYPE))
         && !r->content_encoding) {
-        if (apr_file_open(&thefile, r->filename, APR_READ,
-                          APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
+        if (ap_privsep_file_open(ap_privsep_token(r),
+                                 &thefile, r->filename, APR_READ,
+                                 APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
             return NULL;
         }
         n = sizeof(char) * (MAX_STRING_LEN - 1);
@@ -1994,7 +1998,8 @@
     char *ctype = "text/html";
     char *charset;
 
-    if ((status = apr_dir_open(&thedir, name, r->pool)) != APR_SUCCESS) {
+    if ((status = ap_privsep_dir_open(ap_privsep_token(r),
+                                      &thedir, name, r->pool)) != APR_SUCCESS) {
         ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
                       "Can't open directory for index: %s", r->filename);
         return HTTP_FORBIDDEN;
@@ -2181,7 +2186,8 @@
     memcpy(fullpath, name, dirpathlen);
 
     do {
-        status = apr_dir_read(&dirent, APR_FINFO_MIN | APR_FINFO_NAME, thedir);
+        status = ap_privsep_dir_read(ap_privsep_token(r), &dirent,
+                                     APR_FINFO_MIN | APR_FINFO_NAME, thedir);
         if (APR_STATUS_IS_INCOMPLETE(status)) {
             continue; /* ignore un-stat()able files */
         }
@@ -2197,8 +2203,8 @@
             savename = dirent.name;
             apr_cpystrn(fullpath + dirpathlen, dirent.name,
                         APR_PATH_MAX - dirpathlen);
-            status = apr_stat(&fi, fullpath,
-                              dirent.valid & ~(APR_FINFO_NAME), r->pool);
+            status = ap_privsep_stat(ap_privsep_token(r), &fi, fullpath,
+                                     dirent.valid & ~(APR_FINFO_NAME), r->pool);
             if (status != APR_SUCCESS) {
                 /* Something bad happened, skip this file. */
                 continue;

