1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
Description: Fix race condition with chdir
Fix /var/www* being accepted as docroot instead of /var/www/*
(the same for public_html* instead of public_html/* )
Author: Stefan Fritsch <sf@debian.org>
Last-Update: 2014-05-29
Bug: https://issues.apache.org/bugzilla/show_bug.cgi?id=44752
--- 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>
@@ -279,11 +280,12 @@
char *actual_gname; /* actual group name */
char *cmd; /* command to be executed */
char cwd[AP_MAXPATH]; /* current working directory */
- char dwd[AP_MAXPATH]; /* docroot working directory */
+ char dwd[AP_MAXPATH+1]; /* docroot working directory */
struct passwd *pw; /* password entry holder */
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
@@ -529,11 +531,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);
}
@@ -541,12 +548,16 @@
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, "/", 1);
if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
log_err("command not in docroot (%s/%s)\n", cwd, cmd);
exit(114);
|