#40535 [NEW]: is_readable and file_exists give false negatives when euid != uid

Ask a Question related to PHP Bugs, Design and Development.

  1. #1

    Default #40535 [NEW]: is_readable and file_exists give false negatives when euid != uid

    From: php dot user at jeremy dot smallinfinity dot net
    Operating system: MacOS and RedHat Linux
    PHP version: 5.2.1
    PHP Bug Type: *Directory/Filesystem functions
    Bug description: is_readable and file_exists give false negatives when euid != uid

    Description:
    ------------
    is_readable() and file_exists(), when called from a PHP 4.3.2 (Linux),
    4.4.0 (Mac OS) and 5.2.1 (Mac OS) script that is executed with
    posix_euid() != posix_uid() does not recognize files that are owned and
    readable only by the effective uid. Instead is_readable() and
    file_exists() return "false" even though functions like fileperms, fopen
    and readfile work as expected.

    Reproduce code:
    ---------------
    #!/usr/bin/php
    <?php
    echo "My effective UID is ".posix_geteuid()." but my UID is really
    ".posix_getuid()."\n";

    chdir($curdir = dirname(__FILE__)) or die("Unable to enter the private
    directory");
    echo "The current directory is owned by ".fileowner($curdir)." and has
    permissions ".sprintf('%o', fileperms($curdir))."\n";

    touch("test.dat");
    chmod("test.dat", 0600); // readable only by the effective user

    echo "is_readable should give TRUE, and gives ".(is_readable("test.dat") ?
    "TRUE" : "FALSE")."\n";

    echo "file_exists should give TRUE, and gives ".(file_exists("test.dat") ?
    "TRUE" : "FALSE")."\n";

    echo "The file has permissions ".sprintf('%o', fileperms("test.dat")).",
    is owned by ".fileowner("test.dat")." and is in the
    ".filegroup("test.dat")." group.\n";

    unlink("test.dat"); // no error because the file really does exist!

    ?>

    Expected result:
    ----------------
    My effective UID is 501 but my UID is really [uid]
    The current directory is owned by 501 and has permissions 40700
    is_readable should give TRUE, and gives TRUE
    file_exists should give TRUE, and gives TRUE
    The file has permissions 100600, is owned by 501 and is in the 501 group.

    Actual result:
    --------------
    When run as its owner, gives the expected result, with [uid]=501.

    When run from a different account using the executable obtained from
    #include <unistd.h>

    int main(int argc, char **argv) {
    execl("/path/to/reproduce_code.php", "/path/to/reproduce_code.php",
    NULL);

    }
    which is then chmod 04711 or 06711, gives

    My effective UID is 501 but my UID is really 503
    The current directory is owned by 501 and has permissions 40700
    is_readable should give TRUE, and gives FALSE
    file_exists should give TRUE, and gives FALSE
    The file has permissions 100600, is owned by 501 and is in the 501 group.

    These tests are done on Mac OS X 10.4.8 with both PHP 4.4.4 and 5.2.1, but
    I first noticed this behaviour with PHP 4.3.2 under Red Hat Linux for which
    I do not have root privileges.

    --
    Edit bug report at [url]http://bugs.php.net/?id=40535&edit=1[/url]
    --
    Try a CVS snapshot (PHP 4.4): [url]http://bugs.php.net/fix.php?id=40535&r=trysnapshot44[/url]
    Try a CVS snapshot (PHP 5.2): [url]http://bugs.php.net/fix.php?id=40535&r=trysnapshot52[/url]
    Try a CVS snapshot (PHP 6.0): [url]http://bugs.php.net/fix.php?id=40535&r=trysnapshot60[/url]
    Fixed in CVS: [url]http://bugs.php.net/fix.php?id=40535&r=fixedcvs[/url]
    Fixed in release: [url]http://bugs.php.net/fix.php?id=40535&r=alreadyfixed[/url]
    Need backtrace: [url]http://bugs.php.net/fix.php?id=40535&r=needtrace[/url]
    Need Reproduce Script: [url]http://bugs.php.net/fix.php?id=40535&r=needscript[/url]
    Try newer version: [url]http://bugs.php.net/fix.php?id=40535&r=oldversion[/url]
    Not developer issue: [url]http://bugs.php.net/fix.php?id=40535&r=support[/url]
    Expected behavior: [url]http://bugs.php.net/fix.php?id=40535&r=notwrong[/url]
    Not enough info: [url]http://bugs.php.net/fix.php?id=40535&r=notenoughinfo[/url]
    Submitted twice: [url]http://bugs.php.net/fix.php?id=40535&r=submittedtwice[/url]
    register_globals: [url]http://bugs.php.net/fix.php?id=40535&r=globals[/url]
    PHP 3 support discontinued: [url]http://bugs.php.net/fix.php?id=40535&r=php3[/url]
    Daylight Savings: [url]http://bugs.php.net/fix.php?id=40535&r=dst[/url]
    IIS Stability: [url]http://bugs.php.net/fix.php?id=40535&r=isapi[/url]
    Install GNU Sed: [url]http://bugs.php.net/fix.php?id=40535&r=gnused[/url]
    Floating point limitations: [url]http://bugs.php.net/fix.php?id=40535&r=float[/url]
    No Zend Extensions: [url]http://bugs.php.net/fix.php?id=40535&r=nozend[/url]
    MySQL Configuration Error: [url]http://bugs.php.net/fix.php?id=40535&r=mysqlcfg[/url]
    php dot user at jeremy dot smallinfinity dot net Guest

  2. Similar Questions and Discussions

    1. #40231 [NEW]: file_exists incorrectly reports false
      From: RQuadling@php.net Operating system: Windows XP SP2 PHP version: 5CVS-2007-01-25 (snap) PHP Bug Type: Scripting Engine...
    2. #39063 [NEW]: is_file() and file_exists() returning false on high load
      From: nherdananto at gmail dot com Operating system: FreeBSD 5.5 PHP version: 4.4.4 PHP Bug Type: Filesystem function related...
    3. #39063 [Fbk->Opn]: is_file() and file_exists() returning false on high load
      ID: 39063 User updated by: nherdananto at gmail dot com Reported By: nherdananto at gmail dot com -Status: Feedback...
    4. #39063 [Opn->Fbk]: is_file() and file_exists() returning false on high load
      ID: 39063 Updated by: tony2001@php.net Reported By: nherdananto at gmail dot com -Status: Open +Status: ...
    5. #39063 [Opn]: is_file() and file_exists() returning false on high load
      ID: 39063 User updated by: nherdananto at gmail dot com Reported By: nherdananto at gmail dot com Status: Open Bug...
  3. #2

    Default #40535 [Opn->Bgs]: is_readable and file_exists give false negatives when euid != uid

    ID: 40535
    Updated by: [email]tony2001@php.net[/email]
    Reported By: php dot user at jeremy dot smallinfinity dot net
    -Status: Open
    +Status: Bogus
    Bug Type: *Directory/Filesystem functions
    Operating System: MacOS and RedHat Linux
    PHP Version: 5.2.1
    New Comment:

    PHP uses access() function.

    man access:
    The check is done with the process's real UID and GID, rather than with
    the effective IDs as is done when actually attempting an operation.
    This is to allow set-UID programs to easily determine the invoking
    user's authority.



    Previous Comments:
    ------------------------------------------------------------------------

    [2007-02-18 17:35:44] php dot user at jeremy dot smallinfinity dot net

    Description:
    ------------
    is_readable() and file_exists(), when called from a PHP 4.3.2 (Linux),
    4.4.0 (Mac OS) and 5.2.1 (Mac OS) script that is executed with
    posix_euid() != posix_uid() does not recognize files that are owned and
    readable only by the effective uid. Instead is_readable() and
    file_exists() return "false" even though functions like fileperms,
    fopen and readfile work as expected.

    Reproduce code:
    ---------------
    #!/usr/bin/php
    <?php
    echo "My effective UID is ".posix_geteuid()." but my UID is really
    ".posix_getuid()."\n";

    chdir($curdir = dirname(__FILE__)) or die("Unable to enter the private
    directory");
    echo "The current directory is owned by ".fileowner($curdir)." and has
    permissions ".sprintf('%o', fileperms($curdir))."\n";

    touch("test.dat");
    chmod("test.dat", 0600); // readable only by the effective user

    echo "is_readable should give TRUE, and gives
    ".(is_readable("test.dat") ? "TRUE" : "FALSE")."\n";

    echo "file_exists should give TRUE, and gives
    ".(file_exists("test.dat") ? "TRUE" : "FALSE")."\n";

    echo "The file has permissions ".sprintf('%o',
    fileperms("test.dat")).", is owned by ".fileowner("test.dat")." and is
    in the ".filegroup("test.dat")." group.\n";

    unlink("test.dat"); // no error because the file really does exist!

    ?>

    Expected result:
    ----------------
    My effective UID is 501 but my UID is really [uid]
    The current directory is owned by 501 and has permissions 40700
    is_readable should give TRUE, and gives TRUE
    file_exists should give TRUE, and gives TRUE
    The file has permissions 100600, is owned by 501 and is in the 501
    group.

    Actual result:
    --------------
    When run as its owner, gives the expected result, with [uid]=501.

    When run from a different account using the executable obtained from
    #include <unistd.h>

    int main(int argc, char **argv) {
    execl("/path/to/reproduce_code.php", "/path/to/reproduce_code.php",
    NULL);

    }
    which is then chmod 04711 or 06711, gives

    My effective UID is 501 but my UID is really 503
    The current directory is owned by 501 and has permissions 40700
    is_readable should give TRUE, and gives FALSE
    file_exists should give TRUE, and gives FALSE
    The file has permissions 100600, is owned by 501 and is in the 501
    group.

    These tests are done on Mac OS X 10.4.8 with both PHP 4.4.4 and 5.2.1,
    but I first noticed this behaviour with PHP 4.3.2 under Red Hat Linux
    for which I do not have root privileges.


    ------------------------------------------------------------------------


    --
    Edit this bug report at [url]http://bugs.php.net/?id=40535&edit=1[/url]
    tony2001@php.net Guest

  4. #3

    Default #40535 [Bgs]: is_readable and file_exists give false negatives when euid != uid

    ID: 40535
    User updated by: php dot user at jeremy dot smallinfinity dot net
    Reported By: php dot user at jeremy dot smallinfinity dot net
    Status: Bogus
    Bug Type: *Directory/Filesystem functions
    Operating System: MacOS and RedHat Linux
    PHP Version: 5.2.1
    New Comment:

    Thanks.

    I understand that PHP uses access() and that access() behaves as per
    its man page. I also understand that this is one way of fixing e.g.
    Bug#30931. But I don't understand why that implies that is_readable()
    and file_exists() are *supposed to* behave according to the access()
    man page. Aren't is_readable() and file_exists() supposed to behave as
    described in the PHP manual? Nowhere therein does it specify that the
    check is done using the real UID/GID instead of the effective one. And
    I'm afraid I don't understand why checking the real UID/GID is the
    desired behaviour.

    Thanks,
    Jeremy


    Previous Comments:
    ------------------------------------------------------------------------

    [2007-02-27 13:40:36] [email]tony2001@php.net[/email]

    PHP uses access() function.

    man access:
    The check is done with the process's real UID and GID, rather than with
    the effective IDs as is done when actually attempting an operation.
    This is to allow set-UID programs to easily determine the invoking
    user's authority.


    ------------------------------------------------------------------------

    [2007-02-18 17:35:44] php dot user at jeremy dot smallinfinity dot net

    Description:
    ------------
    is_readable() and file_exists(), when called from a PHP 4.3.2 (Linux),
    4.4.0 (Mac OS) and 5.2.1 (Mac OS) script that is executed with
    posix_euid() != posix_uid() does not recognize files that are owned and
    readable only by the effective uid. Instead is_readable() and
    file_exists() return "false" even though functions like fileperms,
    fopen and readfile work as expected.

    Reproduce code:
    ---------------
    #!/usr/bin/php
    <?php
    echo "My effective UID is ".posix_geteuid()." but my UID is really
    ".posix_getuid()."\n";

    chdir($curdir = dirname(__FILE__)) or die("Unable to enter the private
    directory");
    echo "The current directory is owned by ".fileowner($curdir)." and has
    permissions ".sprintf('%o', fileperms($curdir))."\n";

    touch("test.dat");
    chmod("test.dat", 0600); // readable only by the effective user

    echo "is_readable should give TRUE, and gives
    ".(is_readable("test.dat") ? "TRUE" : "FALSE")."\n";

    echo "file_exists should give TRUE, and gives
    ".(file_exists("test.dat") ? "TRUE" : "FALSE")."\n";

    echo "The file has permissions ".sprintf('%o',
    fileperms("test.dat")).", is owned by ".fileowner("test.dat")." and is
    in the ".filegroup("test.dat")." group.\n";

    unlink("test.dat"); // no error because the file really does exist!

    ?>

    Expected result:
    ----------------
    My effective UID is 501 but my UID is really [uid]
    The current directory is owned by 501 and has permissions 40700
    is_readable should give TRUE, and gives TRUE
    file_exists should give TRUE, and gives TRUE
    The file has permissions 100600, is owned by 501 and is in the 501
    group.

    Actual result:
    --------------
    When run as its owner, gives the expected result, with [uid]=501.

    When run from a different account using the executable obtained from
    #include <unistd.h>

    int main(int argc, char **argv) {
    execl("/path/to/reproduce_code.php", "/path/to/reproduce_code.php",
    NULL);

    }
    which is then chmod 04711 or 06711, gives

    My effective UID is 501 but my UID is really 503
    The current directory is owned by 501 and has permissions 40700
    is_readable should give TRUE, and gives FALSE
    file_exists should give TRUE, and gives FALSE
    The file has permissions 100600, is owned by 501 and is in the 501
    group.

    These tests are done on Mac OS X 10.4.8 with both PHP 4.4.4 and 5.2.1,
    but I first noticed this behaviour with PHP 4.3.2 under Red Hat Linux
    for which I do not have root privileges.


    ------------------------------------------------------------------------


    --
    Edit this bug report at [url]http://bugs.php.net/?id=40535&edit=1[/url]
    php dot user at jeremy dot smallinfinity dot net Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139