diff -rupN httpd-2.2.22-old/support/Makefile.in httpd-2.2.22-new/support/Makefile.in --- httpd-2.2.22-old/support/Makefile.in 2011-04-16 15:09:47.000000000 -0400 +++ httpd-2.2.22-new/support/Makefile.in 2012-03-06 04:50:51.000000000 -0500 @@ -60,7 +60,7 @@ checkgid: $(checkgid_OBJECTS) suexec_OBJECTS = suexec.lo suexec: $(suexec_OBJECTS) - $(LINK) $(suexec_OBJECTS) + $(LINK) $(suexec_OBJECTS) -llve -ldl htcacheclean_OBJECTS = htcacheclean.lo htcacheclean: $(htcacheclean_OBJECTS) diff -rupN httpd-2.2.22-old/support/suexec.c httpd-2.2.22-new/support/suexec.c --- httpd-2.2.22-old/support/suexec.c 2011-02-14 15:36:12.000000000 -0500 +++ httpd-2.2.22-new/support/suexec.c 2012-02-14 09:19:00.000000000 -0500 @@ -55,6 +55,8 @@ #include #endif +#include + /* *********************************************************************** * There is no initgroups() in QNX, so I believe this is safe :-) @@ -317,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); } /* @@ -466,6 +471,23 @@ int main(int argc, char *argv[]) exit(108); } + void *lib_handle; + lib_handle = dlopen("liblve.so.0", RTLD_LAZY); + if (lib_handle) { + char *error; + char error_msg[8192]; + int (*jail)(struct passwd *, char*) = dlsym(lib_handle, "jail"); + if ((error = dlerror()) != NULL) { + log_err("failed to init LVE library %s\n", error); + exit(130); + } + int result = jail(pw, error_msg); + if (result < 0) { + log_err("SecureLVE jail error %s\n", error_msg); + exit(131); + } + } + /* * Change UID/GID here so that the following tests work over NFS. * @@ -493,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) || @@ -516,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. @@ -565,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) || @@ -576,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