]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Allow mod_dav_fs to tolerate race conditions between PROPFIND and an
authorJoe Orton <jorton@apache.org>
Thu, 6 Jul 2023 08:28:08 +0000 (08:28 +0000)
committerJoe Orton <jorton@apache.org>
Thu, 6 Jul 2023 08:28:08 +0000 (08:28 +0000)
operation which removes a directory/file between apr_dir_read() and
apr_stat(). Current behaviour is to abort the connection which seems
inferior to tolerating (and logging) the error.

* modules/dav/fs/repos.c (dav_fs_walker): If DAV_WALKTYPE_TOLERANT is
  set, ignore ENOENT from stat() rather than aborting the response.
  Log the error from stat either way.

* modules/dav/main/mod_dav.c (dav_method_propfind): Set
  DAV_WALKTYPE_TOLERANT.

* modules/dav/main/mod_dav.h: Add DAV_WALKTYPE_TOLERANT.

Github: closes #369

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1910811 13f79535-47bb-0310-9956-ffa450edef68

modules/dav/fs/repos.c
modules/dav/main/mod_dav.c
modules/dav/main/mod_dav.h

index 889d728a1b7c8112cc65ecfb8ab21e10fe1585b8..701b4425e0630506643e98e9db7117dcab3b7fe1 100644 (file)
@@ -35,6 +35,7 @@
 #include "mod_dav.h"
 #include "repos.h"
 
+APLOG_USE_MODULE(dav_fs);
 
 /* to assist in debugging mod_dav's GET handling */
 #define DEBUG_GET_HANDLER       0
@@ -1613,6 +1614,19 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
         status = apr_stat(&fsctx->info1.finfo, fsctx->path1.buf,
                           DAV_FINFO_MASK, pool);
         if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
+            dav_resource_private *ctx = params->root->info;
+
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, ctx->r,
+                          APLOGNO(10472) "could not access file (%s) during directory walk",
+                          fsctx->path1.buf);
+
+            /* If being tolerant, ignore failure due to losing a race
+             * with some other process deleting files out from under
+             * the directory walk. */
+            if ((params->walk_type & DAV_WALKTYPE_TOLERANT)
+                && APR_STATUS_IS_ENOENT(status)) {
+                continue;
+            }
             /* woah! where'd it go? */
             /* ### should have a better error here */
             err = dav_new_error(pool, HTTP_NOT_FOUND, 0, status, NULL);
index 4f8d748a13a153a0c1b5d4a7a336dca9209eafff..69e068807f8c17624a0ed8c5fe6d4551e44d7c68 100644 (file)
@@ -2269,7 +2269,7 @@ static int dav_method_propfind(request_rec *r)
         return HTTP_BAD_REQUEST;
     }
 
-    ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_AUTH;
+    ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_AUTH | DAV_WALKTYPE_TOLERANT;
     ctx.w.func = dav_propfind_walker;
     ctx.w.walk_ctx = &ctx;
     ctx.w.pool = r->pool;
index fcf146c694ce7001d3ca9dcddcc9fa293081de92..2bfec337573feb1efd7f81e81bf99367c36d31f3 100644 (file)
@@ -1834,6 +1834,7 @@ typedef struct
 #define DAV_WALKTYPE_AUTH       0x0001  /* limit to authorized files */
 #define DAV_WALKTYPE_NORMAL     0x0002  /* walk normal files */
 #define DAV_WALKTYPE_LOCKNULL   0x0004  /* walk locknull resources */
+#define DAV_WALKTYPE_TOLERANT   0x0008  /* tolerate non-fatal errors */
 
     /* callback function and a client context for the walk */
     dav_error * (*func)(dav_walk_resource *wres, int calltype);