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 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 #endif +#include #include #include @@ -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);