php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #66884 php://fd/x file descriptors not usable outside CLI mode
Submitted: 2014-03-11 15:55 UTC Modified: 2014-05-13 23:37 UTC
From: dfuhry at gmail dot com Assigned: stas (profile)
Status: Not a bug Package: Streams related
PHP Version: 5.6.0alpha3 OS: Linux 2.6.32-5-amd64
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: dfuhry at gmail dot com
New email:
PHP Version: OS:

 

 [2014-03-11 15:55 UTC] dfuhry at gmail dot com
Description:
------------
Commit df2a38e7f8603f51afa4c2257b3369067817d818 removed the ability to use php://fd/x file descriptors in non-CLI mode. Thus, sometime after PHP 5.3 it became no longer possible to issue parallel async database queries and stream_select on the array of database connection socket file descriptors.
When trying to fopen("php://fd/x") (for some file descriptor number "x") the unhelpful error I receive is: "failed to open stream: operation failed".
Neither the commit nor source comments make clear to me why the change was made, but if it is possible to revert it, or otherwise make alterations to allow the above use case, I would advocate doing so.
I use unexposed pg_socket() method in the below, which returns the file descriptor of the socket of the database connection.

Test script:
---------------
$conn1 = pg_connect("dbname=a user=b host=c");
$conn2 = pg_connect("dbname=a user=b host=c");
// Next two lines should return resources representing file descriptors
// but instead error and return FALSE.
$r1 = fopen("php://fd/" . pg_socket($conn1));
$r2 = fopen("php://fd/" . pg_socket($conn2));
pg_send_query($conn1, "SELECT pg_sleep(random())");
pg_send_query($conn2, "SELECT pg_sleep(random())");
$r = array($r1, r2);
$w = array();
$e = array();
stream_select($r, $w, $e, NULL);  // Would return whichever conn finished first.

Expected result:
----------------
fopen("php://fd/x") calls return a valid stream resource, not FALSE.

Actual result:
--------------
... failed to open stream: operation failed ...
... failed to open stream: operation failed ...

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-03-27 16:59 UTC] ab@php.net
-Assigned To: +Assigned To: stas
 [2014-04-13 01:14 UTC] tyrael@php.net
as far as I know it was changed, because it opened a can op worms from the security point of view, see:
http://www.slideshare.net/phdays/on-secure-application-of-php-wrappers
 [2014-04-13 01:48 UTC] dfuhry at gmail dot com
Thanks for pointing that out, I see slide 4 provides a concrete example of writing directly to the file descriptor of the Apache error log.
A possible solution that comes to mind would be to either whitelist or blacklist descriptors by either:
1) Tracking and whitelisting file descriptors created in user php code, like those created by a user fopen() or pg_connect(), or
2) Blacklisting file descriptors not created in user php code, like file descriptor 2 corresponding to the Apache error log as opened by PHP process code.
I'm not sure if there is a clean way to achieve either, while avoiding leaking any whitelist descriptors or missing any blacklist descriptors, and working across platforms.
 [2014-05-13 23:37 UTC] stas@php.net
-Status: Assigned +Status: Not a bug
 [2014-05-13 23:37 UTC] stas@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

Đ¢his was done deliberately, since in shared environment giving access to FDs would be dangerous as it could include files not even owned by Apache user. I understand the inconvenience this is causing but I don't see a way to allow php://fd on Apache without creating security issues.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Mon Nov 18 21:01:37 2019 UTC