Running PHP on NFS: new version of turbo_realpath extension

More than a month has passed since I published my PHP extension fixing the performance issues with NFS and PHP. Since then, turbo_realpath has become quite popular among Web administrators. Unfortunately, despite my warnings, many of them don’t disable the PHP functions responsible for creating links and symlinks, or do it wrong way.

For this reason I decided to publish a new version of the turbo_realpath extension, which adds the ability to automatically disable dangerous functions in PHP.

How to install turbo_realpath?

You can download this extension from this link.

In order to use this extension, you have to compile it first:

cd realpath_turbo
cp modules/ /usr/lib/php/modules

Please, remember to change /usr/lib/php/modules to the path used by your PHP installation.

Next, you have to configure this PHP extension in php.ini file, like so:

; you have to load the extension first
; set this to 1 in order to disable dangerous PHP functions (link,symlink), or set to 0 in order to ignore potential security issues
realpath_cache_security = 1
; then copy the value of open_basedir into realpath_cache_basedir parameter
realpath_cache_basedir = /var/www/html/drupal
; and finally DISABLE the open_basedir setting,
; it will be changed automatically to the value of a realpath_cache_basedir setting.
; open_basedir=""

As you can see, in order to use this extension, you have to move the value of open_basedir setting into realpath_cache_basedir and then disable open_basedir itself. After this, PHP will reenable open_basedir restrictions automatically.


12 Responses to “Running PHP on NFS: new version of turbo_realpath extension”

  1. Mark says:

    Could this work with suphp?

  2. Artur Graniszewski says:

    Yes, it’s 100% safe_mode/open_basedir compatible.

    So, if you use suphp with open_basedir on, then this module will also work for you.

  3. Benoit says:

    Hi !

    That’s looks very interesting :)

    I have some questions.
    Can you explain a little bit more “to automatically disable dangerous functions in PHP” ?

    for example, in my case, i would like to try this extension on a shared system hosting.
    We allow some php function but they are only on the base_dir directory.
    If i enable your extension, what can be the security problem? I don’t fully understand.

    Is there some “more standard” option to improve php over NFS ?

    Our infrastructure slowest by NFS.. not the network.. and a little bit by mysql.
    I will appreciate your knowledge about that !


  4. Artur Graniszewski says:

    Well, in fact this module was created with shared hostings in mind.

    The security problem is quite simple: PHP uses open_basedir setting to control, whetever the user can traverse to the selected directory/file. Unfortunately, this is a major performance problem on NFS because PHP checks not only open_basedir permissions for the given path, but also tries to resolve it and see if it isn’t a symlink pointing to other, probably restricted locations in a file system.

    This module forces PHP to check for symlink only once, then cache the result of this operation, and open every file which passed this test and is placed in the open_basedir location. Now, assuming I was a hacker and my PHP script could open only files in /home/testuser/, I could fool that open_basedir restriction by doing something like this:

    a) create regular file in /home/testuser/hackfile location.
    b) open the file, just to make it cached by PHP. Now PHP thinks that the hackfile is a regular file.
    a) delete the file and create a symlink in /home/testuser/hackfile, pointing to the /etc/passwd file (using the link() function)
    b) then use file_get_contents(“/home/testuser/hackfile”); to read restriced file. PHP will read the file stats from cache and assume, that it’s still a regular file (unaware that it has been changed).

    My module can disable functions, which can create symlinks in PHP. This however is not required, you can disable this functionality in the php.ini file.

    There is no standard options that I’m aware of. The only thing you can do is to disable “atime” and “mtime updates” in the filesystem, but I’m not sure if the first one isn’t disabled by default in case of NFS. This however does not boost NFS so much.

  5. Sydney says:

    it didn’t compile on my system (CentOS) until I changed one line in config.m4 :

    if test “$PHP_TURBO_REALPATH” = “yes”; then

    is changed to :

    if test “$PHP_TURBO_REALPATH” != “no”; then

    The configure script returns this line :
    checking whether to enable turbo realpath module… yes, shared
    which is obviously not equal to “yes”.

    In the hope this will help someone else.

  6. Ricardo says:

    Hi there,
    I wasn’t able to compile it on Windows + PHP 5.4 (although I created the config.w32).

    ** CONFIG.w32 **
    ARG_ENABLE(“turbo_realpath”, “enable turbo realpath module”, “no”);

    if (PHP_TURBO_REALPATH == “yes”) {
    EXTENSION(“turbo_realpath”, “turbo_realpath.c”);

    AC_DEFINE(“HAVE_TURBO_REALPATH”, 1, “Have turbo_realpath Support”);



    Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
    Copyright (C) Microsoft Corporation. All rights reserved.

    Recreating build dirs
    ext\realpath_turbo\turbo_realpath.c(12) : error C2061: syntax error : identifier
    ext\realpath_turbo\turbo_realpath.c(12) : error C2059: syntax error : ‘;’
    ext\realpath_turbo\turbo_realpath.c(12) : error C3409: empty attribute block is
    not allowed
    ext\realpath_turbo\turbo_realpath.c(12) : error C2513: ‘/*global*/ ‘ : no variab
    le declared before ‘=’
    ext\realpath_turbo\turbo_realpath.c(21) : error C2065: ‘turbo_realpath_functions
    ‘ : undeclared identifier
    ext\realpath_turbo\turbo_realpath.c(21) : error C2099: initializer is not a cons
    ext\realpath_turbo\turbo_realpath.c(22) : warning C4047: ‘initializing’ : ‘const
    _zend_function_entry *’ differs in levels of indirection from ‘int (__cdecl *)(
    int,int,void ***)’
    ext\realpath_turbo\turbo_realpath.c(26) : warning C4113: ‘void (__cdecl *)(zend_
    module_entry *,void ***)’ differs in parameter lists from ‘int (__cdecl *)(int,i
    nt,void ***)’
    ext\realpath_turbo\turbo_realpath.c(26) : warning C4133: ‘initializing’ : incomp
    atible types – from ‘void (__cdecl *)(zend_module_entry *,void ***)’ to ‘int (__
    cdecl *)(int,int,void ***)’
    ext\realpath_turbo\turbo_realpath.c(28) : warning C4047: ‘initializing’ : ‘void
    (__cdecl *)(zend_module_entry *,void ***)’ differs in levels of indirection from
    ‘char [4]‘
    ext\realpath_turbo\turbo_realpath.c(30) : warning C4047: ‘initializing’ : ‘size_
    t’ differs in levels of indirection from ‘void *’
    ext\realpath_turbo\turbo_realpath.c(30) : warning C4047: ‘initializing’ : ‘unsig
    ned char’ differs in levels of indirection from ‘void *’
    ext\realpath_turbo\turbo_realpath.c(31) : warning C4047: ‘initializing’ : ‘int’
    differs in levels of indirection from ‘char [19]‘
    ext\realpath_turbo\turbo_realpath.c(88) : warning C4013: ‘php_info_print_table_s
    tart’ undefined; assuming extern returning int
    ext\realpath_turbo\turbo_realpath.c(89) : warning C4013: ‘php_info_print_table_h
    eader’ undefined; assuming extern returning int
    ext\realpath_turbo\turbo_realpath.c(90) : warning C4013: ‘php_info_print_table_r
    ow’ undefined; assuming extern returning int
    ext\realpath_turbo\turbo_realpath.c(94) : warning C4013: ‘php_info_print_table_e
    nd’ undefined; assuming extern returning int
    NMAKE : fatal error U1077: ‘”c:\Program Files\Microsoft Visual Studio 9.0\VC\Bin
    \cl.exe”‘ : return code ’0×2′

  7. Artur Graniszewski says:

    Are you able to compile other modules from different vendors? I ask abou this because maybe you have a misconfigured VC9 environment

  8. server: Linux alpha3 2.6.32-41-server #88-Ubuntu SMP Thu Mar 29 14:32:47 UTC 2012 x86_64 GNU/Linux
    APACHE: apache2 2.2.14-5ubuntu8.9
    other apache modules installed
    * mod_security
    * mod_itk2
    PHP: PHP 5.3.2-1ubuntu4.15 with Suhosin-Patch (cli) (built: May 4 2012 00:38:26)

    when I compiled and used the turbo real path, my colleagues and I saw a significant improvement on lstat that were required in order for a Drupal CMS to function. The problem is that when I try to see the page, I only get a white page on the browser and lots of
    ==> /var/log/apache2/error.log <==
    [Mon Jun 18 13:55:56 2012] [error] child died with signal 11
    [Mon Jun 18 13:55:56 2012] [error] child died with signal 11
    [Mon Jun 18 13:55:56 2012] [error] child died with signal 11
    [Mon Jun 18 13:55:59 2012] [error] child died with signal 11
    [Mon Jun 18 13:55:59 2012] [error] child died with signal 11

    I disabled the realpath_cache_basedir instruction and reverted back to open_basedir
    (in apache vhost configuration) and all errors dissapeared:
    php_admin_value open_basedir /var/www/httpdocs/:/var/tmp/
    #php_admin_value realpath_cache_basedir /var/www/httpdocs/:/var/tmp/

    lot's of thatnks to kostas katsamakas
    for debuging the apache process – core dump, to find the culprit.

  9. Bryan says:

    This is a great work around, thank you. Is the open_basedir value suppose to be “no value” in phpinfo()? Also, open_basedir restrictions are not in effect. I have confirmed that open_basedir is not being set and I am setting realpath_cache_basedir with a value /home/ But still I am able to access resources outside those paths.

    I am using PHP 5.3.2.

    Any ideas?

  10. Artur Graniszewski says:

    Hi Bryan, looks like the module is disabled in your PHP. Either you forgot to load it in php.ini by using the extension=”filename” directive or you put a wrong path to the module in php.ini. Please check the server logs during HTTPD startup. It should tell you if there were any configuration errors present.

    What’s more. You should find the turbo_realpath module mentioned in phpinfo() report (its a separate HTML table just like in case of other extensions).

  11. Bryan says:

    Thank you, it is working now. I had a typo in my ini file, it said Was missing the “e”.

  12. Nedd says:

    Great work, I use the extension on ubuntu and it works perfectly. realpath cache is back again :)

Leave a Reply