#! /bin/sh /usr/share/dpatch/dpatch-run
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Fix race condition with chdir
## DP: Fix /var/www* being accepted as docroot instead of /var/www/*
## DP: (the same for public_html* instead of public_html/* )

@DPATCH@
--- a/support/suexec.c
+++ b/support/suexec.c
@@ -42,6 +42,7 @@
 #if APR_HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#include <fcntl.h>
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -264,6 +265,7 @@
     struct group *gr;       /* group entry holder        */
     struct stat dir_info;   /* directory info holder     */
     struct stat prg_info;   /* program info holder       */
+    int cwdh;               /* handle to cwd             */
 
     /*
      * Start with a "clean" environment
@@ -499,11 +501,16 @@
         exit(111);
     }
 
+    if ( (cwdh = open(".", O_RDONLY)) == -1 ) {
+        log_err("cannot open current working directory\n");
+	exit(111);
+    }
+
     if (userdir) {
         if (((chdir(target_homedir)) != 0) ||
             ((chdir(AP_USERDIR_SUFFIX)) != 0) ||
             ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
-            ((chdir(cwd)) != 0)) {
+            ((fchdir(cwdh)) != 0)) {
             log_err("cannot get docroot information (%s)\n", target_homedir);
             exit(112);
         }
@@ -511,12 +518,18 @@
     else {
         if (((chdir(AP_DOC_ROOT)) != 0) ||
             ((getcwd(dwd, AP_MAXPATH)) == NULL) ||
-            ((chdir(cwd)) != 0)) {
+            ((fchdir(cwdh)) != 0)) {
             log_err("cannot get docroot information (%s)\n", AP_DOC_ROOT);
             exit(113);
         }
     }
 
+    close(cwdh);
+
+    if (strlen(cwd) > strlen(dwd)) {
+        strncat(dwd, "/", AP_MAXPATH);
+        dwd[AP_MAXPATH-1] = '\0';
+    }
     if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
         log_err("command not in docroot (%s/%s)\n", cwd, cmd);
         exit(114);
