diff -aur php-5.2.2.orig/ext/standard/exec.c php-5.2.2/ext/standard/exec.c --- php-5.2.2.orig/ext/standard/exec.c 2007-01-01 10:36:08.000000000 +0100 +++ php-5.2.2/ext/standard/exec.c 2007-05-09 09:41:15.000000000 +0200 @@ -86,6 +86,23 @@ cmd_p = php_escape_shell_cmd(d); efree(d); d = cmd_p; + } else if (PG(exec_dir) && strlen(PG(exec_dir))) { + if ((c = strchr(cmd, ' '))) { + *c = '\0'; + c++; + } + if (strstr(cmd, "..")) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No '..' components allowed in path"); + goto err; + } + b = strrchr(cmd, PHP_DIR_SEPARATOR); + spprintf(&d, 0, "%s%s%s%s%s", PG(exec_dir), (b ? "" : "/"), (b ? b : cmd), (c ? " " : ""), (c ? c : "")); + if (c) { + *(c - 1) = ' '; + } + cmd_p = php_escape_shell_cmd(d); + efree(d); + d = cmd_p; } else { cmd_p = cmd; } @@ -428,13 +445,44 @@ } convert_to_string_ex(cmd); + + if (PG(exec_dir) && strlen(PG(exec_dir))) { + char *cmd_value=Z_STRVAL_PP(cmd); + char *cmd_p, *b, *c, *d=NULL; + if ((c = strchr(cmd_value, ' '))) { + *c = '\0'; + c++; + } + if (strstr(cmd_value, "..")) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No '..' components allowed in path"); + RETURN_FALSE; + } + b = strrchr(cmd_value, PHP_DIR_SEPARATOR); + spprintf(&d, 0, "%s%s%s%s%s", PG(exec_dir), (b ? "" : "/"), (b ? b : cmd_value), (c ? " " : ""), (c ? c : "")); + if (c) { + *(c - 1) = ' '; + } + cmd_p = php_escape_shell_cmd(d); + efree(d); + d = cmd_p; + #ifdef PHP_WIN32 - if ((in=VCWD_POPEN(Z_STRVAL_PP(cmd), "rt"))==NULL) { + if ((in=VCWD_POPEN(cmd_p, "rt"))==NULL) { #else - if ((in=VCWD_POPEN(Z_STRVAL_PP(cmd), "r"))==NULL) { + if ((in=VCWD_POPEN(cmd_p, "r"))==NULL) { #endif - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to execute '%s'", Z_STRVAL_PP(cmd)); - RETURN_FALSE; + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to execute '%s'", Z_STRVAL_PP(cmd)); + RETURN_FALSE; + } + } else { +#ifdef PHP_WIN32 + if ((in=VCWD_POPEN(Z_STRVAL_PP(cmd), "rt"))==NULL) { +#else + if ((in=VCWD_POPEN(Z_STRVAL_PP(cmd), "r"))==NULL) { +#endif + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to execute '%s'", Z_STRVAL_PP(cmd)); + RETURN_FALSE; + } } stream = php_stream_fopen_from_pipe(in, "rb"); diff -aur php-5.2.2.orig/ext/standard/file.c php-5.2.2/ext/standard/file.c --- php-5.2.2.orig/ext/standard/file.c 2007-02-23 17:22:20.000000000 +0100 +++ php-5.2.2/ext/standard/file.c 2007-05-09 09:41:15.000000000 +0200 @@ -963,6 +963,39 @@ efree(buf); + } else if (PG(exec_dir) && strlen(PG(exec_dir))) { + b = strchr(Z_STRVAL_PP(arg1), ' '); + if (!b) { + b = strrchr(Z_STRVAL_PP(arg1), '/'); + } else { + char *c; + c = Z_STRVAL_PP(arg1); + while((*b != '/') && (b != c)) { + b--; + } + if (b == c) { + b = NULL; + } + } + if (b) { + spprintf(&buf, 0, "%s%s", PG(exec_dir), b); + } else { + spprintf(&buf, 0, "%s/%s", PG(exec_dir), Z_STRVAL_PP(arg1)); + } + + tmp = php_escape_shell_cmd(buf); + fp = VCWD_POPEN(tmp, p); + efree(tmp); + + if (!fp) { + php_error_docref2(NULL TSRMLS_CC, buf, p, E_WARNING, "%s", strerror(errno)); + efree(p); + efree(buf); + RETURN_FALSE; + } + + efree(buf); + } else { fp = VCWD_POPEN(Z_STRVAL_PP(arg1), p); if (!fp) { Only in php-5.2.2/ext/standard: file.c.orig diff -aur php-5.2.2.orig/main/main.c php-5.2.2/main/main.c --- php-5.2.2.orig/main/main.c 2007-04-18 11:38:56.000000000 +0200 +++ php-5.2.2/main/main.c 2007-05-09 09:41:15.000000000 +0200 @@ -301,6 +301,7 @@ PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout) STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_SYSTEM, OnUpdateString, open_basedir, php_core_globals, core_globals) STD_PHP_INI_ENTRY("safe_mode_exec_dir", PHP_SAFE_MODE_EXEC_DIR, PHP_INI_SYSTEM, OnUpdateString, safe_mode_exec_dir, php_core_globals, core_globals) + STD_PHP_INI_ENTRY("exec_dir", NULL, PHP_INI_SYSTEM, OnUpdateString, exec_dir, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals) STD_PHP_INI_ENTRY("upload_max_filesize", "2M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, upload_max_filesize, php_core_globals, core_globals) Only in php-5.2.2/main: main.c.orig diff -aur php-5.2.2.orig/main/php_globals.h php-5.2.2/main/php_globals.h --- php-5.2.2.orig/main/php_globals.h 2007-03-02 22:58:05.000000000 +0100 +++ php-5.2.2/main/php_globals.h 2007-05-09 09:41:15.000000000 +0200 @@ -72,6 +72,7 @@ long serialize_precision; char *safe_mode_exec_dir; + char *exec_dir; long memory_limit; long max_input_time; diff -aur php-5.2.2.orig/php.ini-dist php-5.2.2/php.ini-dist --- php-5.2.2.orig/php.ini-dist 2007-04-12 14:31:39.000000000 +0200 +++ php-5.2.2/php.ini-dist 2007-05-09 09:41:15.000000000 +0200 @@ -512,6 +512,11 @@ ; Default is zero. ;cgi.rfc2616_headers = 0 +; Only executables located in the exec_dir will be allowed to be executed +; via the exec family of functions. If safe_mode is enabled, this directive +; is forgotten and safe_mode_exec_dir takes the ride +exec_dir = + ;;;;;;;;;;;;;;;; ; File Uploads ; diff -aur php-5.2.2.orig/php.ini-recommended php-5.2.2/php.ini-recommended --- php-5.2.2.orig/php.ini-recommended 2007-04-12 14:31:39.000000000 +0200 +++ php-5.2.2/php.ini-recommended 2007-05-09 09:41:15.000000000 +0200 @@ -557,6 +557,11 @@ ; Default is zero. ;cgi.rfc2616_headers = 0 +; Only executables located in the exec_dir will be allowed to be executed +; via the exec family of functions. If safe_mode is enabled, this directive +; is forgotten and safe_mode_exec_dir takes the ride +exec_dir = + ;;;;;;;;;;;;;;;; ; File Uploads ;