diff -up httpd-2.2.15/configure.in.suexec-safe httpd-2.2.15/configure.in --- httpd-2.2.15/configure.in.suexec-safe 2012-01-23 15:45:50.000000000 +0200 +++ httpd-2.2.15/configure.in 2012-01-23 15:58:30.863352802 +0200 @@ -605,6 +605,10 @@ AC_ARG_WITH(suexec-umask, APACHE_HELP_STRING(--with-suexec-umask,umask for suexec'd process),[ AC_DEFINE_UNQUOTED(AP_SUEXEC_UMASK, 0$withval, [umask for suexec'd process] ) ] ) +AC_ARG_WITH(suexec-safedir, +APACHE_HELP_STRING(--with-suexec-safedir,Set safe dir),[ + AC_DEFINE_UNQUOTED(AP_SAFE_DIRECTORY, "$withval", [safe dir] ) ] ) + dnl APR should go after the other libs, so the right symbols can be picked up apulinklibs="`$apu_config --link-libtool`" AP_LIBS="$AP_LIBS $apulinklibs `$apr_config --link-libtool`" diff -up httpd-2.2.15/support/suexec.c.suexec-safe httpd-2.2.15/support/suexec.c --- httpd-2.2.15/support/suexec.c.suexec-safe 2012-01-23 15:45:50.179188786 +0200 +++ httpd-2.2.15/support/suexec.c 2012-01-23 15:45:50.184187935 +0200 @@ -319,6 +319,9 @@ int main(int argc, char *argv[]) #ifdef AP_USERDIR_SUFFIX fprintf(stderr, " -D AP_USERDIR_SUFFIX=\"%s\"\n", AP_USERDIR_SUFFIX); #endif +#ifdef AP_SAFE_DIRECTORY + fprintf(stderr, " -D AP_SAFE_DIRECTORY=\"%s\"\n", AP_SAFE_DIRECTORY); +#endif exit(0); } /* @@ -512,11 +515,32 @@ int main(int argc, char *argv[]) * Use chdir()s and getcwd()s to avoid problems with symlinked * directories. Yuck. */ + if (getcwd(cwd, AP_MAXPATH) == NULL) { log_err("cannot get current working directory\n"); exit(111); } + /* Check for safe directory existence */ +#ifdef AP_SAFE_DIRECTORY + char safe_dr[AP_MAXPATH]; + int is_safe_dir_present = 0; + struct stat safe_dir_info; + if (((lstat(AP_SAFE_DIRECTORY, &safe_dir_info)) == 0) && (S_ISDIR(safe_dir_info.st_mode))) { + is_safe_dir_present = 1; + } + + if(is_safe_dir_present){ + if (((chdir(AP_SAFE_DIRECTORY)) != 0) || + ((getcwd(safe_dr, AP_MAXPATH)) == NULL) || + ((chdir(cwd)) != 0)) { + log_err("cannot get safe directory information (%s)\n", AP_SAFE_DIRECTORY); + exit(200); + } + } +#endif + + if (userdir) { if (((chdir(target_homedir)) != 0) || ((chdir(AP_USERDIR_SUFFIX)) != 0) || @@ -535,10 +559,28 @@ int main(int argc, char *argv[]) } } - if ((strncmp(cwd, dwd, strlen(dwd))) != 0) { - log_err("command not in docroot (%s/%s)\n", cwd, cmd); - exit(114); +#ifdef AP_SAFE_DIRECTORY + int safe_work = 0; + if(is_safe_dir_present){ + if ((strncmp(cwd, safe_dr, strlen(safe_dr))) != 0){ + if ((strncmp(cwd, dwd, strlen(dwd))) != 0) { + log_err("command not in docroot (%s/%s)\n", cwd, cmd); + exit(114); + } + } else { + safe_work = 1; + } + } else { +#endif + if ((strncmp(cwd, dwd, strlen(dwd))) != 0) { + log_err("command not in docroot (%s/%s)\n", cwd, cmd); + exit(114); + } +#ifdef AP_SAFE_DIRECTORY } +#endif + + /* * Stat the cwd and verify it is a directory, or error out. @@ -584,6 +626,9 @@ int main(int argc, char *argv[]) * Error out if the target name/group is different from * the name/group of the cwd or the program. */ +#ifdef AP_SAFE_DIRECTORY + if (!safe_work){ +#endif if ((uid != dir_info.st_uid) || (gid != dir_info.st_gid) || (uid != prg_info.st_uid) || @@ -595,6 +640,9 @@ int main(int argc, char *argv[]) prg_info.st_uid, prg_info.st_gid); exit(120); } +#ifdef AP_SAFE_DIRECTORY + } +#endif /* * Error out if the program is not executable for the user. * Otherwise, she won't find any error in the logs except for