Giter Site home page Giter Site logo

mod_execdir's Introduction

PHP execdir extension

PHP license GitHub download GitHub last release GitHub closed issues GitHub closed pull requests

1. License

Copyright 2022. JoungKyun.Kim <http://oops.org> All rights reserved.

This program is under PHP License.

2. Description

If you use mod_execdir extension, you can run only the shell command in the specified directory. And this means that possible to fundamentally protect the web shell and system shell injection attacks.

This feature is an implementation to improve safe_mode_exec_dir before PHP 5.4.

safe_mode_exec_dir function can be used only in SAFE MODE state, and it was removed from PHP 5.4. Also, the parser of safe_mode_exec_dir was written too simple and it has many restrictions in order to use.

The execdir exntesion is to complement the such disadvantages of safe_mode_exec_dir, and support non SAFE MODE and over PHP 5.4.

This feature was made for highlight syntax security hole of PHPBB in May 2005. Also, it has been applied to large business site and AnNyung LInux distribution and verified more than 10 years.

This feature is provided as the source patch or php dynamic extension, and affects follow PHP functions:

  • exec
  • system
  • passthru
  • shell_exec
  • popen
  • proc_open
  • pcntl_exec
  • shell_exec
  • backtick operator

3. Installation

3.1. Requirement

Over PHP 5, PHP 7 and PHP 8. But, it is tested on PHP 5.1 and after.

For this features, we support 2 building method.

  1. build with direct patch on PHP source code
    • support from PHP 4.3 and later
    • better performance than mod_execdir.
  2. build with mod_execdir extension
    • support PHP 5 and later
    • verified test on PHP 5.5 and later
    • if failed call pcntl_exec, can not use pcntl_get_last_error function. Need to modify your code.

3.2. PHP source patch

This feature can be used as a PHP extension, or you can patch it directly to the PHP source. If you prefer to patch your PHP directly rather than using it as an extension, see the description of the patch file.

3.3. mod_execdir dynamic extension

[root@host mod_execdir]$ phpize
[root@host mod_execdir]$ ./configure --with-execdir=/var/lib/php/bin
[root@host mod_execdir]$ make test PHP_EXECUTABLE=/usr/bin/php
[root@host mod_execdir]$ make install

At configure time, you can use the --with-execdir option to specify the default directory for jail

4. Usage

4.1. Configuraions

4.1.1 module loading

If build with PHP dynamic extension, you will need to load execdir.so file in php.ini. Add follow configuration in th php.ini.

; for php 7.1 and before
extension = execdir.so

; for php 7.2 and after
; default extension dir
extension = execdir
; use absolute path
extension = /path/execdir.so

; if you use with opcache, follow option is set false
; When used with opcache, the proc_close function does not work properly.
; opcache.fast_shutdown = 0

This extension replaces the existing functions, so it is recommended that you last loaded.

4.1.2 ini settings

Add directory for restricted shell command.

; only executables located in the exec_dir will be allowed to be executed
; via the exec family of functions. This is only AnNyung LInux patch
; see also https://github.com/OOPS-ORG-PHP/mod_execdir/
exec_dir = /var/lib/php/bin

If the exec_dir option is not set as follows, the --with-execdir value that specified at the configure time is used. If you did not provied the --with-execdir option at the configure time, then tme value of exec_dir will be empty.

; only executables located in the exec_dir will be allowed to be executed
; via the exec family of functions. This is only AnNyung LInux patch
; see also https://github.com/OOPS-ORG-PHP/mod_execdir/
;exec_dir =

If you do not want to restrict, you have to specify an empty value like this:

; only executables located in the exec_dir will be allowed to be executed
; via the exec family of functions. This is only AnNyung LInux patch
; see also https://github.com/OOPS-ORG-PHP/mod_execdir/
exec_dir =

4.1.3 Settings per Apache VirtualHost

If you use PHP as an apache module, you can use the php_admin_value directive to make different settings for each virtual host.

<VirtualHost *:80>
    ServerName domain.com
    DocumentRoot /var/www/domain.com

    <IfModule php8_module>
        php_admin_flag exec_dir /var/php/domain.com/bin
    </IfModule>
</VirtualHost>

<VirtualHost *:80>
    ServerName domain-other.com
    DocumentRoot /var/www/domain-other.com

    <IfModule php8_module>
        php_admin_flag exec_dir /var/php/domain-other.com/bin
    </IfModule>
</VirtualHost>

This setting can be applied in <Directory>, <Location> and other blocks.

The exec_dir option is assigned to PHP_INI_SYSTEM, so it can not be used with .htaccess.

4.1.4 Settgins per PHP FPM pool

If you use PHP as fpm mode, you can set different for each FPM pool.

[www]
php_admin_flag[exec_dir] = /var/php/pool/www/bin

[www1]
php_admin_flag[exec_dir] = /var/php/pool/www1/bin

4.2. Command parser format

Supported formats are as follows:

command
$(command)
`command`
command; command
command $(command)
command $(command $(command))
command $(command `command`)
command `command`
command | command
command && command
command || command

Example of applied parser is follows:

exec ('ls -al /etc/hosts', $o, $r);
exec ('ls -al /etc/ | grep hosts', $o, $r);
exec ('/bin/ls /etc/ | grep hosts', $o, $r);
exec ('cat $(echo "/etc/passwd") | grep root; ls -al', $o, $r);
exec ('cat `echo "/etc/passwd"` | grep root; ls -al', $o, $r);
exec ("echo '$(ls -l | grep abc)' | grep abc");
exec ('echo "$(ls -l | grep abc)" | grep abc');

If execdir is set, The above code will actually be run in the following manner:

exec ('/var/lib/php/bin/ls -al /etc/hosts', $o, $r);
exec ('/var/lib/php/bin/ls -al /etc/ | /var/lib/php/bin/grep hosts', $o, $r);
exec ('/var/lib/php/bin/ls -al /etc/ | /var/lib/php/bin/grep hosts', $o, $r);
exec ('/var/lib/php/bin/cat $(/var/lib/php/bin/echo "/etc/passwd") | /var/lib/php/bin/grep root; /var/lib/php/bin/ls -al', $o, $r);
exec ('/var/lib/php/bin/cat $(/var/lib/php/bin/echo "/etc/passwd") | /var/lib/php/bin/grep root; /var/lib/php/bin/ls -al', $o, $r);
exec ("/var/lib/php/bin/echo '$(ls -l | grep abc)' | /var/lib/php/bin/grep abc");
exec ('/var/lib/php/bin/echo "$(/var/lib/php/bin/ls -l | /var/lib/php/bin/grep abc)" | /var/lib/php/bin/grep abc');

4.3. APIs

The following case is applied with building in mod_execdir as PHP dynamic extension.

4.3.1. Original functions

You can call original functions with _orig postfix.

<?php
exec_orig ('ls /etc/hosts', $o, $r);
var_dump ($o);
?>

The list of original functions is follow:

  • exec_orig
  • system_orig
  • passthru_orig
  • shell_exec_orig
  • popen_orig
  • proc_open_orig
  • proc_close_orig
  • proc_terminate_orig
  • proc_get_status_orig

These functions can be called from 1.0.2 only by giving --enable-execdir-addon option at configure.

4.3.2. mod_execdir APIs

  • exec_re : mapping exec function

  • system_re : mapping system function

  • passthru_re : mapping passthru function

  • shell_exec_re : mapping shell_exec function

  • popen_re : mapping popen function

  • popen_re : mapping popen function

  • proc_open_re : mapping proc_open function

  • proc_close_re : mapping proc_close function

  • proc_terminate_re : mapping proc_terminate function

  • proc_get_status_re : mapping proc_get_status function

  • pcntl_exec_re : mapping pcntl_exec function
    Can not use pcntl_get_last_error() fucntion, if call failed pcntl_exec, so Need to modify your code as follows:
    Before:

    <?php
    if ( ($r = @pcntl_exec ('/bin/cat', array ('/etc/hosts')) === false ) {
        echo pcntl_strerror (pcntl_get_last_error ()) . "\n"
    }
    ?>

    After:

    ini_set ('track_errors', true);
    if ( ($r = @pcntl_exec ('/bin/cat', array ('/etc/hosts')) === false ) {
        echo $php_errormsg . "\n";
    }
  • jailed_shellcmd : return jailed shell command strings

    Prototype: (string) jailed_shellcmd (string path)
    
    <?php
    # Follow codes has same operation with "system(command)"
    $jcmd = jailed_shellcmd ('/bin/ls');
    system_orig ($jcmd);
    ?>

5. Contributors

JoungKyun.Kim

mod_execdir's People

Contributors

joungkyun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

theraw

mod_execdir's Issues

Problems with wordpress (even installation of wordpress)

Hello....

When used extension along with wordpress (installing it), with PHP 7.4.15 (even php 7.3 and 7.2 last versions)...

Fatal error: Cannot redeclare wp_get_server_protocol() (previously declared in herwise. */:1685339145) in /home/xxxx/public_html/test-php74/wp-includes/load.php on line 15

Wordpress success first time... then the next requests to the same FPM thread will crash with the previous error.

Is this wonderful project active?

Regards and thanks!

Is mod_exedir compatible with PHP 7.1

This is my current setup:
rpm -qa|grep php71
php71-php-pecl-apcu-5.1.8-1.el7.remi.x86_64
php71-php-fpm-7.1.9-1.el7.remi.x86_64
php71-php-imap-7.1.9-1.el7.remi.x86_64
php71-php-pecl-redis-3.1.2-1.el7.remi.x86_64
php71-php-xml-7.1.9-1.el7.remi.x86_64
php71-php-cli-7.1.9-1.el7.remi.x86_64
php71-php-mysqlnd-7.1.9-1.el7.remi.x86_64
php71-php-process-7.1.9-1.el7.remi.x86_64
php71-runtime-1.0-1.el7.remi.x86_64
php71-php-pecl-igbinary-2.0.4-1.el7.remi.x86_64
php71-php-pecl-memcache-3.0.9-0.7.20161124gitdf7735e.el7.remi.x86_64
php71-php-common-7.1.9-1.el7.remi.x86_64
php71-php-soap-7.1.9-1.el7.remi.x86_64
php71-php-pecl-geoip-1.1.1-3.el7.remi.x86_64
php71-php-pecl-memcached-3.0.3-1.el7.remi.x86_64
php71-php-json-7.1.9-1.el7.remi.x86_64
php71-php-7.1.9-1.el7.remi.x86_64
php71-php-mcrypt-7.1.9-1.el7.remi.x86_64
php71-php-tidy-7.1.9-1.el7.remi.x86_64
php71-php-pecl-sphinx-1.4.0-0.2.20170203git201eb00.el7.remi.x86_64
php71-php-pdo-7.1.9-1.el7.remi.x86_64
php71-php-devel-7.1.9-1.el7.remi.x86_64
php71-php-xmlrpc-7.1.9-1.el7.remi.x86_64
php71-php-bcmath-7.1.9-1.el7.remi.x86_64
php71-php-pecl-apcu-bc-1.0.3-6.el7.remi.x86_64
php71-php-pecl-msgpack-2.0.2-1.el7.remi.x86_64
php71-php-opcache-7.1.9-1.el7.remi.x86_64
php71-php-pear-1.10.5-2.el7.remi.noarch
php71-php-pecl-zip-1.15.1-1.el7.remi.x86_64
php71-php-pecl-imagick-3.4.3-5.el7.remi.x86_64
php71-php-gd-7.1.9-1.el7.remi.x86_64
php71-php-snmp-7.1.9-1.el7.remi.x86_64
php71-php-mbstring-7.1.9-1.el7.remi.x86_64

This is my current setup for php-exec:
cd /root/php
rm /root/php/mod_execdir -rf
git clone https://github.com/OOPS-ORG-PHP/mod_execdir/
cd /root/php/mod_execdir
/opt/remi/php71/root/usr/bin/phpize
./configure --with-execdir= --with-php-config=/opt/remi/php71/root/usr/bin/php-config
make test PHP_EXECUTABLE=/usr/bin/php71
make install

Test fails:
PHP : /usr/bin/php71
PHP_SAPI : cli
PHP_VERSION : 7.1.9
ZEND_VERSION: 3.1.0
PHP_OS : Linux - Linux f100.test.com 3.10.0-693.1.1.el7.x86_64 #1 SMP Wed Aug 23 13:08:16 UTC 2017 x86_64
INI actual : /root/setupSync/php/mod_execdir/tmp-php.ini
More .INIs :
CWD : /root/setupSync/php/mod_execdir
Extra dirs :
VALGRIND : Not used
TIME START 2017-09-18 15:22:30
PASS Check for jailed_shellcmd function [tests/000-jailed_shellcmd.phpt]
PASS Check for exec_re function that has command not found [tests/001-exec-failed.phpt]
PASS Check for exec_re function that return success [tests/001-exec-normal.phpt]
PASS Check for system_re function that has command not found [tests/002-system-failed.phpt]
PASS Check for system_re function that return success [tests/002-system-normal.phpt]
PASS Check for passthru_re function that has command not found [tests/003-passthru-failed.phpt]
PASS Check for passthru_re function that return success [tests/003-passthru-normal.phpt]
PASS Check for shell_exec_re function that return success [tests/004-shell_exec-failed.phpt]
PASS Check for shell_exec_re function that return success [tests/004-shell_exec-normal.phpt]
PASS Check for popen_re function that return success [tests/005-popen-failed.phpt]
PASS Check for popen_re function that return success [tests/005-popen-normal.phpt]
PASS Check for proc_open_re function that has command not found [tests/006-proc_open-failed.phpt]
PASS Check for proc_open_re function that return success [tests/006-proc_open-normal.phpt]
PASS Check for pcntl_exec_re function that has command not found [tests/007-pcntl_exec-failed.phpt]
PASS Check for pcntl_exec_re function that return success [tests/007-pcntl_exec-normal.phpt]
PASS Check for shell redirection [tests/008-redirection.phpt]
PASS Check for NULL byte detected error [tests/009-twice_same_command.phpt]
TIME END 2017-09-18 15:22:31

TEST RESULT SUMMARY
Exts skipped : 0
Exts tested : 15

Number of tests : 17 17
Tests skipped : 0 ( 0.0%) --------
Tests warned : 0 ( 0.0%) ( 0.0%)
Tests failed : 0 ( 0.0%) ( 0.0%)
Expected fail : 0 ( 0.0%) ( 0.0%)
Tests passed : 17 (100.0%) (100.0%)
Time taken : 1 seconds

This report can be automatically sent to the PHP QA team at
http://qa.php.net/reports and http://news.php.net/php.qa.reports
This gives us a better understanding of PHP's behavior.
If you don't want to send the report immediately you can choose
option "s" to save it. You can then email it to [email protected] later.
Do you want to send this report now? [Yns]:

Real world tests:
exec seems to limit exec to the selected directly properly, however
I am seeing random segfault when using execdir extension with exec() and ffmpeg
Also, exec_orig works on PHP 5.6 but doesn't seem to work on php 7.1

Everything works okay when disabling execdir, and all php coredumps go away.

safe_hook_execdir buffer overflow

diff -urNp php_execdir.c.orig php_execdir.c
--- php_execdir.c.orig  2016-06-20 01:54:41.000000000 +0900
+++ php_execdir.c       2016-06-20 01:54:59.000000000 +0900
@@ -221,7 +221,7 @@ static int safe_hook_execdir (void) {
                 * Rename original function gets postfie '_orig'
                 */
                {
-                       char            func_re[16] = { 0 };
+                       char            func_re[32] = { 0 };
                        int             func_relen;
                        zend_function * zf;
 #if PHP_VERSION_ID < 60000

zend_mm_heap corrupted problem

--- execdirapi.c.orig   2016-06-20 01:48:23.000000000 +0900
+++ execdirapi.c        2016-06-20 01:48:41.000000000 +0900
@@ -238,8 +238,8 @@ static char * php_jailed_shell_cmd (char
        else
                b = 0;

-       _path= emalloc (sizeof (char *) * (cmd_len + 2));
-       memset (_path, 0, sizeof (char *) * (cmd_len + 2));
+       _path= emalloc (sizeof (char) * (cmd_len + path_len + 4));
+       memset (_path, 0, sizeof (char) * (cmd_len + path_len + 4));
        sprintf (_path, "%s%s", _tpath, !b ? "" : "/");
        path_len = strlen (_path);
        efree (_tpath);

failed run-test 000-jailed_shellcmd.phpt

[root@an3 mod_execdir]$ make PHP_EXECUTABLE=/usr/bin/php test
...
=====================================================================
FAILED TEST SUMMARY
---------------------------------------------------------------------
Check for jailed_shellcmd function [tests/000-jailed_shellcmd.phpt]
=====================================================================
...

support proc_open 7.4 new features

According to the PHP Proc_Open documentation:

As of PHP 7.4.0, cmd may be passed as array of command parameters. In this case the process will be opened directly (without going through a shell) and PHP will take care of any necessary argument escaping.

add new jailed_shellcmd function

_code_:

<?php
echo jailed_shellcmd ('/bin/ls');
?>

_Expected result_:

/var/lib/php/bin/ls

_Actual result_:

Fatal error: Call to undefined function jailed_shellcmd() in /dev/shm/a.php on line 2

error "NULL byte detected."

If run the same command twice, occurs the error "NULL byte detected."

<?php
system ('ls -al');
system ('ls -al');
?>

Expected:

[root@an3 php-7.0.23]$ php -d exec_dir=/asdf test.php
sh: /asdf/ls: No such file or directory
sh: /asdf/ls: No such file or directory
[root@an3 php-7.0.23]$

Actually:

[root@an3 php-7.0.23]$ php -d exec_dir=/asdf test.php
sh: /asdf/ls: No such file or directory
PHP Warning:  system(): NULL byte detected. Possible attack in /root/rpmbuild/BUILD/php-7.0.23RC1/z.php on line 3

Warning: system(): NULL byte detected. Possible attack in /root/rpmbuild/BUILD/php-7.0.23RC1/z.php on line 3
[root@an3 php-7.0.23]$

Removing support for original system function with '_orig' suffix

mod_execdir extension support original system function with '_orig' postfix. For examples:

<?php
exec_orig('ls -al');
?>

However, this could be a vulnerability. So, this function is changed sub function for debugging or confirmation of operation of wrapping function.

To use this feature, you must specify the --enable-execdir-addon option at configure time.

[root@host mod_execdir]$ ./configure --with-execdir=/var/php/bin --enable-execdir-addon

Build test error on 1.0.5

Bug Environments

  • Product Version : 1.0.5 (no problem 1.0.4 and before)
  • PHP Version: PHP 5.0.0 ~ 5.0.3
  • PHP SAPI: all

Describe the bug

FAIL Check for pcntl_exec_re function that has command not found [tests/007-pcntl_exec-failed.phpt]
FAIL Check for pcntl_exec_re function that return success [tests/007-pcntl_exec-normal.phpt]

To Reproduce

  1. build as extension of PHP 5.3
  2. phpize
  3. make tests PHP_EXECUTABLE=/usr/bin/php

Expected behavior

check result to PASS

Additional context

Parse error: syntax error, unexpected '[' in /root/work/github/php/mod_execdir/tests/007-pcntl_exec-failed.php on line 12
Parse error: syntax error, unexpected '[' in /root/work/github/php/mod_execdir/tests/007-pcntl_exec-normal.php on line 12

Perhaps, it is a problem of test code, not the functional problem of extension.

When safe_mode enabled, wrong operation shell_exec function in php 5.3 and before

In php 5.3 and before, safe_mode does not work in shell_exec, even if safe_mode setting is enabled.

Test Code:

<?php
if ( ini_get ('safe_mode') > 0 ) {
    shell_exec('ls -al');
}
?>

Expected Result:

Warning: Cannot execute using backquotes in Safe Mode in test.php on line 3

Actual Result:

Total 232
drwxr-xr-x  5 root root  4096 2017-01-10 04:21 .
drwxr-xr-x 12 root root  4096 2017-01-10 04:21 ..
drwxr-xr-x  8 root root  4096 2017-01-10 04:02 .git
-rw-r--r--  1 root root   292 2016-06-19 22:56 .gitignore
-rw-r--r--  1 root root  8273 2016-06-23 04:21 README.ko.md
-rw-r--r--  1 root root  7215 2017-01-10 00:50 README.md
-rw-r--r--  1 root root    39 2017-01-10 04:21 a.php
-rw-r--r--  1 root root   749 2017-01-10 00:50 config.m4
-rw-r--r--  1 root root 12525 2017-01-10 01:59 execdirapi.c
-rw-r--r--  1 root root  1580 2017-01-10 00:50 execdirapi.h
-rw-r--r--  1 root root   313 2016-06-19 22:56 init.sh
-rw-r--r--  1 root root  3396 2017-01-10 04:01 package.xml
drwxr-xr-x  2 root root  4096 2017-01-10 00:50 patches
-rw-r--r--  1 root root 23415 2017-01-10 03:59 php_execdir.c
-rw-r--r--  1 root root  3026 2017-01-10 00:50 php_execdir.h
-rw-r--r--  1 root root 26721 2016-06-19 22:56 proc_open.c
-rw-r--r--  1 root root 27951 2016-06-20 02:22 proc_open5.c
-rw-r--r--  1 root root 29271 2016-06-20 04:01 proc_open53.c
-rw-r--r--  1 root root 34410 2017-01-10 02:32 tags
drwxr-xr-x  2 root root  4096 2017-01-10 03:16 tests

can't print debug message

If the command contains a slash, the DEBUG mark is ignored.

for example:

<?php
system ('DEBUG:ls -al');
system ('DEBUG:/bin/ls -al');
?>

Expected messages:

[root@host ~]$ php test.php
p **> ls -al
p ==> /var/lib/php/bin/ls -al
--
sh: /var/lib/php/bin/ls: No such file or directory
p **> ls -al
p ==> /var/lib/php/bin/ls -al
--
sh: /var/lib/php71/bin/ls: No such file or directory

Current messages:

[user@host ~]$ php test.php
p **> ls -al
p ==> /var/lib/php/bin/ls -al
--
sh: /var/lib/php/bin/ls: No such file or directory
sh: /var/lib/php/bin/ls: No such file or directory
[user@host ~]$

proc_open_re :: argument string duplicate check

In the function "get_command_from_array" in proc_open.c, argument string check is performed in get_valid_arg_string, but there is a problem of duplicating once more.

    ZEND_HASH_FOREACH_VAL(array, arg_zv) {
        zend_string *arg_str = get_valid_arg_string(arg_zv, i + 1);
        if (!arg_str) {
            /* Terminate with NULL so exit_fail code knows how many entries to free */
            (*argv)[i] = NULL;
            if (command != NULL) {
                efree(command);
            }
            return NULL;
        }

        if (i == 0) {
#ifdef HAVE_EXECDIR
            if (strlen(ZSTR_VAL(arg_str)) != ZSTR_LEN(arg_str)) {
                php_error_docref(NULL, E_WARNING, "NULL byte detected. Possible attack");
                return NULL;
            }
            {
                char * jcommand = get_jailed_shell_cmd (ZSTR_VAL(arg_str));
                if (jcommand == NULL)
                    return NULL;
                command = estrdup(jcommand);
                efree (jcommand);
            }
#else
            command = estrdup(ZSTR_VAL(arg_str));
#endif
        }

        (*argv)[i++] = estrdup(ZSTR_VAL(arg_str));
        zend_string_release(arg_str);
    } ZEND_HASH_FOREACH_END();

Error due to the 3rd argument of pnctl_exe.

Bug Environments

  • Product Version : 1.0.6
  • PHP Version: < 7.0.0
  • PHP SAPI: ALL

Describe the bug

There is a bug in the PHP bug #79182 patch modified in 1.0.6.

In an environment less than PHP 7, when the third env_var arrangement factor of the pcntl_exec function is given, an error occurs unconditionally as follows.

$r = pcntl_exec ("/bin/cat", array ($datafile), array ('ABC' => 'TEST'));

Results of execution:

Fatal error: pcntl_exec(): The element length or key length is greater than -1. in /root/work/github/php/mod_execdir/tests/007-pcntl_exec-normal.php on line 10

This error occurs due to the following code (patch 3257a2d):

mod_execdir/php_execdir.c

Lines 809 to 817 in 3257a2d

/* Length of element + equal sign + length of key + null */
ZEND_ASSERT(Z_STRLEN_PP(element) < SIZE_MAX && key_length < SIZE_MAX);
if ( Z_STRLEN_PP(element) < SIZE_MAX && key_length < SIZE_MAX ) {
#if PHP_VERSION_ID < 50200
php_error_docref (NULL TSRMLS_CC, E_ERROR, "pcntl_exec(): The element length or key length is greater than %ld.", SIZE_MAX);
#else
php_error_docref (NULL TSRMLS_CC, E_ERROR, "The element length or key length is greater than %ld.", SIZE_MAX);
#endif
}

To Reproduce

Steps to reproduce the behavior:

[root@host ~]# ./configure && make
[root@host ~]# php -n -d 'track_errors=1' -d 'extension_dir=./modules/' -d 'extension=execdir.so' <<-EOL
<?php
$r = pcntl_exec ("/bin/cat", array ($datafile), array ('ABC' => 'TEST'));
?>
EOL

Expected behavior

No failure on result of upper reproduced action

Build failure on PHP 5.x

Bug Environments

  • Product Version : 1.0.5
  • PHP Version: PHP 5.x (all minor version)
  • PHP SAPI: all

Describe the bug

Occurs build failure with follow error on PHP 5.x

/root/work/github/php/mod_execdir/php_execdir.c: In function ‘safe_hook_execdir’:
/root/work/github/php/mod_execdir/php_execdir.c:204:70: error: macro "zend_hash_del" requires 3 arguments, but only 2 given
   zend_hash_del (CG (function_table), EXEC_STRING (p->orig_func)  + 1);
                                                                      ^
/root/work/github/php/mod_execdir/php_execdir.c:204:3: error: ‘zend_hash_del’ undeclared (first use in this function)
   zend_hash_del (CG (function_table), EXEC_STRING (p->orig_func)  + 1);
   ^
/root/work/github/php/mod_execdir/php_execdir.c:204:3: note: each undeclared identifier is reported only once for each function it appears in
make: *** [php_execdir.lo] Error 1

To Reproduce

Steps to reproduce the behavior:

  1. phpize (for php 5.x)
  2. make

Expected behavior

no build error

Additional context

EXEC_STRING constant does not extend because end_hash_del is constant.

But when using "2>&1" in exec command

Problem:
When adding "2>&1" to exec argument, it causes commands to fail

How to reproduce problem:
execdir.ini setting:
extension = execdir.so
exec_dir = /etc/run

php code:
$a = "/etc/run/pngquant '--force' '--ext=.png' '--' '/testimage/a.png' 2>&1";
print exec($a);

error:
fails with
sh: /etc/run/: ambiguous redirect

workaround:
currently must delete "2>&1"
$a = "/etc/run/pngquant '--force' '--ext=.png' '--' '/testimage/a.png'";
print exec($a);
will work

The value of exec_dir ini option can't change with php_admin_value

In apache virtual host, can't change value of the exec_dir option with php_admin_value directive.

<VirtualHost *:80>
    ServerName domain.com
    blah blah~~~~

    php_admin_value exec_dir /var/lib/php/domain.com/bin
</VirtualHost>

Current, the value of exec_dir option only can be changed with php ini configuration.

PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/execdir.so' - /usr/lib64/php/modules/execdir.so: undefined symbol: zend_hash_str_del in Unknown on line 0

No problem with php 7.1.11-1

However when trying to use with php 5.6.32-1
The most recent version shows the following error when running php:

PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/execdir.so' - /usr/lib64/php/modules/execdir.so: undefined symbol: zend_hash_str_del in Unknown on line 0

절대 경로 문의 드립니다.

확장 모듈 유용하게 잘 사용하고 있습니다.
사용중 절대 경로 문제가 발견 되어 문의 드립니다.

서버 설정

  <IfModule php5_module>
    php_admin_value exec_dir /home/user/bin
  </IfModule>

php 실행

echo exec('DEBUG:/testbin/command1');

php 실행 결과

-- make_cmdargv ------
Origianl : DEBUG:/testbin/command1
cmd      : /testbin/command1 (16)
argv     :  (0)
----------------------

Orig Cmd ==> command1
Conv Cmd ==> /home/user/bin/command1
--

exec_dir 경로로 지정한 디렉토리 이하의 서브디렉토리에 있는 command를 실행 하려고 합니다.
디버깅을 해보니 /testbin/ 서브디렉토리명이 삭제된 상태로 명령어가 실행이 됩니다.
Conv Cmd가 /home/user/bin/testbin/command1 로 실행을 할 수 있는 방법은 없을까요?

감사합니다.

not yet apply pcntl_exec

_Expected result:
The hooking of pcntl extension is not possible on mod_execdir because of static global variable (_le_pcntl
).

So, apart Create the mod_jailed_pcntl extension.

_Actual result_:
return string "pcntl_exec"

PHP 7.3 patch

Execution Environments:

  • PHP Version : 7.3
  • PHP SAPI: All

Issue description:

Supprot patch for PHP 7.3 (It does not matter mod_execdir).

This patch does not use the mod_execdir function as an extension, but rather a direct patch to PHP.

proc_close() fails cause errors.

Hello:

First of all, thanks so much for your efforts at building up this perfectly useful extension... Highly appreciated.

I have errors along with my config:

  • php 7.1 FPM

  • php config maybe related: disable_functions: exec,passthru,shell_exec,system,show_source,popen,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals

  • opcache on.

  • mod_execdir built up and configured as dynamic extension for php.

  • We are using "wkhtmltopdf" to build up pdfs.

  • Also "/vendor/mikehaertl/phpwkhtmltopdf" libraries to call it and execute from PHP.

Problem is:

  • First execution, pdf is generated and downloaded perfectly... feels like if there is no problem at all.
  • Following executions always give error:
<b>Fatal error</b>:  Uncaught Error: Call to undefined function mikehaertl\shellcommand\proc_close() in /home/xxxxxxxxx/public_html/vendor/mikehaertl/php-shellcommand/src/Command.php:322
Stack trace:
#0 /home/xxxxxxxxx/public_html/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php(270): mikehaertl\shellcommand\Command-&gt;execute()
#1 /home/xxxxxxxxx/public_html/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php(178): mikehaertl\wkhtmlto\Pdf-&gt;createPdf()
#2 /home/xxxxxxxxx/public_html/test.php(21): mikehaertl\wkhtmlto\Pdf-&gt;send()
#3 {main}
  thrown in <b>/home/xxxxxxxxx/public_html/vendor/mikehaertl/php-shellcommand/src/Command.php</b> on line <b>322</b><br />

Then some testing....

  • if just current php thread process die, the next execution will run ok.
  • if you try it and it creates a new php thread, the execution will be ok same way.
  • if you reload or restart php, the php thread will be of course new, and the execution will be fine.

It just appears to cause error only when re-using a php-fpm existing thread.

Piece of code around the path /home/xxxxxxxxx/public_html/vendor/mikehaertl/php-shellcommand/src/Command.php:322 is:

            $descriptors = array(
                1   => array('pipe','w'),
                2   => array('pipe', $this->getIsWindows() ? 'a' : 'w'),
            );
            $process = proc_open($command, $descriptors, $pipes, $this->procCwd, $this->procEnv, $this->procOptions);

            if (is_resource($process)) {

                $this->_stdOut = stream_get_contents($pipes[1]);
                $this->_stdErr = stream_get_contents($pipes[2]);
                fclose($pipes[1]);
                fclose($pipes[2]);

                $this->_exitCode = proc_close($process);

                if ($this->_exitCode!==0) {
                    $this->_error = $this->_stdErr ? $this->_stdErr : "Failed without error message: $command";
                    return false;
                }
            } else {
                $this->_error = "Could not run command $command";
                return false;
            }

The line causing error is:

$this->_exitCode = proc_close($process);

Uncaught Error: Call to undefined function mikehaertl\shellcommand\proc_close()

Well.....

If I disable, dynamic exec_dir extension, no problem appears at all... will be fine.

Thanks so much for your interest!

--

Gino

PHP 8.1 support

Bug Environments

  • Product Version : 1.0.5
  • PHP Version: 8.1.1
  • PHP SAPI: cli

Describe the bug

Intermittent error of proc_open_re function:
The data type of the "command" member of the "php_process_handle" structure changes from (char *) to (zend_string *) from 8.1.0 and later, resulting in intermittent malfunctions.

8.0.0:

typedef struct _php_process_handle {
    php_process_id_t    child;
#ifdef PHP_WIN32
    HANDLE childHandle;
#endif
    int npipes;
    zend_resource **pipes;
    char *command;
    php_process_env env;
} php_process_handle;

8.1.0:

typedef struct _php_process_handle {
    php_process_id_t    child;
#ifdef PHP_WIN32
    HANDLE childHandle;
#endif
    int npipes;
    zend_resource **pipes;
    zend_string *command;
    php_process_env env;
} php_process_handle;

To Reproduce

Steps to reproduce the behavior:

  1. phpize81 && ./configure && make
    /root/work/php/ext/zzz/proc_open.c: In function 'zif_proc_get_status_re':
    /root/work/php/ext/zzz/proc_open.c:390:2: warning: passing argument 4 of 'add_assoc_string_ex' from incompatible pointer type [enabled by default]
      add_assoc_string(return_value, "command", proc->command);
      ^
    In file included from /opt/php-qa/php81/include/php/main/php.h:35:0,
                     from /root/work/php/ext/zzz/proc_open.c:23:
    /opt/php-qa/php81/include/php/Zend/zend_API.h:502:15: note: expected 'const char *' but argument is of type 'struct zend_string *'
     ZEND_API void add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str);
                   ^
    /root/work/php/ext/zzz/proc_open.c: In function 'zif_proc_open_re':
    /root/work/php/ext/zzz/proc_open.c:1282:16: warning: assignment from incompatible pointer type [enabled by default]
      proc->command = command;
                    ^
  2. make test PHP_EXECUTABLE=/usr/bin/php81

Expected behavior

No build warning and always success make test

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.