diff -Naur php-5.3.18.orig/ext/standard/exec.c php-5.3.18/ext/standard/exec.c --- php-5.3.18.orig/ext/standard/exec.c 2012-10-25 16:59:06.000000000 +0200 +++ php-5.3.18/ext/standard/exec.c 2012-10-25 17:00:44.000000000 +0200 @@ -70,6 +70,7 @@ void (*sig_handler)() = NULL; #endif char *safe_dir = NULL; + zval suexec_user, suexec_group; if (PG(safe_mode)) { safe_dir = PG(safe_mode_exec_dir); @@ -107,6 +108,32 @@ cmd_p = cmd; } + if (PG(suexec_path) && strlen(PG(suexec_path))) { + if (!zend_get_constant("SUEXEC_USER", sizeof("SUEXEC_USER") - 1, &suexec_user TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fetch suexec user"); + goto err; + } + if (!zend_get_constant("SUEXEC_GROUP", sizeof("SUEXEC_GROUP") - 1, &suexec_group TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fetch suexec group"); + zval_dtor(&suexec_user); + goto err; + } + if (Z_TYPE(suexec_user) != IS_STRING || Z_STRLEN(suexec_user) <= 0 || + Z_TYPE(suexec_group) != IS_STRING || Z_STRLEN(suexec_group) <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for suexec user or group"); + zval_dtor(&suexec_user); + zval_dtor(&suexec_group); + goto err; + } + spprintf(&b, 0, "%s %s %s %s", PG(suexec_path), Z_STRVAL(suexec_user), Z_STRVAL(suexec_group), cmd_p); + if (d) { + efree(d); + } + cmd_p = d = b; + zval_dtor(&suexec_user); + zval_dtor(&suexec_group); + } + #if PHP_SIGCHILD sig_handler = signal (SIGCHLD, SIG_DFL); #endif @@ -487,6 +514,7 @@ char *ret; php_stream *stream; char *command_p; + zval suexec_user, suexec_group; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &command, &command_len) == FAILURE) { return; @@ -523,6 +551,35 @@ command_p = estrdup(command); } + if (PG(suexec_path) && strlen(PG(suexec_path))) { + if (!zend_get_constant("SUEXEC_USER", sizeof("SUEXEC_USER") - 1, &suexec_user TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fetch suexec user"); + efree(command_p); + RETURN_FALSE; + } + if (!zend_get_constant("SUEXEC_GROUP", sizeof("SUEXEC_GROUP") - 1, &suexec_group TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fetch suexec group"); + zval_dtor(&suexec_user); + efree(command_p); + RETURN_FALSE; + } + if (Z_TYPE(suexec_user) != IS_STRING || Z_STRLEN(suexec_user) <= 0 || + Z_TYPE(suexec_group) != IS_STRING || Z_STRLEN(suexec_group) <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for suexec user or group"); + zval_dtor(&suexec_user); + zval_dtor(&suexec_group); + efree(command_p); + RETURN_FALSE; + } + + char *b; + spprintf(&b, 0, "%s %s %s %s", PG(suexec_path), Z_STRVAL(suexec_user), Z_STRVAL(suexec_group), command_p); + efree(command_p); + command_p = b; + zval_dtor(&suexec_user); + zval_dtor(&suexec_group); + } + #ifdef PHP_WIN32 if ((in=VCWD_POPEN(command_p, "rt"))==NULL) { #else diff -Naur php-5.3.18.orig/ext/standard/file.c php-5.3.18/ext/standard/file.c --- php-5.3.18.orig/ext/standard/file.c 2012-10-25 16:59:06.000000000 +0200 +++ php-5.3.18/ext/standard/file.c 2012-10-25 17:00:44.000000000 +0200 @@ -974,6 +974,7 @@ php_stream *stream; char *posix_mode, *b, *buf = 0, *tmp; char *safe_dir = NULL; + zval suexec_user, suexec_group; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &command, &command_len, &mode, &mode_len) == FAILURE) { return; @@ -989,6 +990,28 @@ } #endif + if (PG(suexec_path) && strlen(PG(suexec_path))) { + if (!zend_get_constant("SUEXEC_USER", sizeof("SUEXEC_USER") - 1, &suexec_user TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fetch suexec user"); + efree(posix_mode); + RETURN_FALSE; + } + if (!zend_get_constant("SUEXEC_GROUP", sizeof("SUEXEC_GROUP") - 1, &suexec_group TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fetch suexec group"); + zval_dtor(&suexec_user); + efree(posix_mode); + RETURN_FALSE; + } + if (Z_TYPE(suexec_user) != IS_STRING || Z_STRLEN(suexec_user) <= 0 || + Z_TYPE(suexec_group) != IS_STRING || Z_STRLEN(suexec_group) <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for suexec user or group"); + zval_dtor(&suexec_user); + zval_dtor(&suexec_group); + efree(posix_mode); + RETURN_FALSE; + } + } + if (PG(safe_mode)) { safe_dir = PG(safe_mode_exec_dir); } else if (PG(exec_dir) && strlen(PG(exec_dir))) { @@ -1015,6 +1038,15 @@ } tmp = php_escape_shell_cmd(buf); + + if (PG(suexec_path) && strlen(PG(suexec_path))) { + spprintf(&b, 0, "%s %s %s %s", PG(suexec_path), Z_STRVAL(suexec_user), Z_STRVAL(suexec_group), tmp); + efree(tmp); + tmp = b; + zval_dtor(&suexec_user); + zval_dtor(&suexec_group); + } + fp = VCWD_POPEN(tmp, posix_mode); efree(tmp); @@ -1028,7 +1060,17 @@ efree(buf); } else { - fp = VCWD_POPEN(command, posix_mode); + if (PG(suexec_path) && strlen(PG(suexec_path))) { + spprintf(&tmp, 0, "%s %s %s %s", PG(suexec_path), Z_STRVAL(suexec_user), Z_STRVAL(suexec_group), command); + zval_dtor(&suexec_user); + zval_dtor(&suexec_group); + } else { + tmp = estrdup(command); + } + + fp = VCWD_POPEN(tmp, posix_mode); + efree(tmp); + if (!fp) { php_error_docref2(NULL TSRMLS_CC, command, posix_mode, E_WARNING, "%s", strerror(errno)); efree(posix_mode); diff -Naur php-5.3.18.orig/main/main.c php-5.3.18/main/main.c --- php-5.3.18.orig/main/main.c 2012-10-25 16:59:06.000000000 +0200 +++ php-5.3.18/main/main.c 2012-10-25 17:01:34.000000000 +0200 @@ -550,6 +550,7 @@ STD_PHP_INI_BOOLEAN("windows.show_crt_warning", "0", PHP_INI_ALL, OnUpdateBool, windows_show_crt_warning, php_core_globals, core_globals) #endif STD_PHP_INI_ENTRY("exec_dir", NULL, PHP_INI_SYSTEM, OnUpdateString, exec_dir, php_core_globals, core_globals) + STD_PHP_INI_ENTRY("suexec_path", NULL, PHP_INI_SYSTEM, OnUpdateString, suexec_path, php_core_globals, core_globals) PHP_INI_END() /* }}} */ diff -Naur php-5.3.18.orig/main/php_globals.h php-5.3.18/main/php_globals.h --- php-5.3.18.orig/main/php_globals.h 2012-10-25 16:59:06.000000000 +0200 +++ php-5.3.18/main/php_globals.h 2012-10-25 17:02:20.000000000 +0200 @@ -177,6 +177,7 @@ long max_input_vars; char *exec_dir; + char *suexec_path; }; diff -Naur php-5.3.18.orig/php.ini-development php-5.3.18/php.ini-development --- php-5.3.18.orig/php.ini-development 2012-10-25 16:59:06.000000000 +0200 +++ php-5.3.18/php.ini-development 2012-10-25 17:00:44.000000000 +0200 @@ -878,6 +878,10 @@ ; http://php.net/cgi.rfc2616-headers ;cgi.rfc2616_headers = 0 +; suEXEC-like-wrapper for the exec-family. Only useful for mod_php. +; Used only if nonempty. +suexec_path = + ;;;;;;;;;;;;;;;; ; File Uploads ; ;;;;;;;;;;;;;;;; diff -Naur php-5.3.18.orig/php.ini-production php-5.3.18/php.ini-production --- php-5.3.18.orig/php.ini-production 2012-10-25 16:59:06.000000000 +0200 +++ php-5.3.18/php.ini-production 2012-10-25 17:00:44.000000000 +0200 @@ -878,6 +878,10 @@ ; http://php.net/cgi.rfc2616-headers ;cgi.rfc2616_headers = 0 +; suEXEC-like-wrapper for the exec-family. Only useful for mod_php. +; Used only if nonempty. +suexec_path = + ;;;;;;;;;;;;;;;; ; File Uploads ; ;;;;;;;;;;;;;;;;