php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #37619 proc_open() closes stdin on fork() failure
Submitted: 2006-05-28 20:30 UTC Modified: 2007-01-02 15:38 UTC
From: jdolecek at NetBSD dot org Assigned: wez (profile)
Status: Closed Package: Program Execution
PHP Version: 5.1.4 OS: Any UNIX-like, Netware
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 you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: jdolecek at NetBSD dot org
New email:
PHP Version: OS:

 

 [2006-05-28 20:30 UTC] jdolecek at NetBSD dot org
Description:
------------
The block spawning the child process for both Netware and UNIX-like OS contains this block in failure case:

    if (child < 0) {
        /* failed to fork() */
        /* clean up all the descriptors */
        for (i = 0; i < ndesc; i++) {
            close(descriptors[i].childend);
            close(descriptors[i].parentend);
        }

        ...
    }

parentend is filled only for pipes, for 'file'
handles it's not filled, and left '0' as initialized
by memset() in proc_open.c line 537.

So, if proc_open() was called with descriptorspec
using 'file' and the fork() call fails, this results
in closing descriptor 0.

Quick fix is to only close parentend if it's non-zero, such as:

--- ext/standard/proc_open.c.orig       2006-05-28 21:51:09.000000000 +0200
+++ ext/standard/proc_open.c
@@ -796,7 +796,8 @@ PHP_FUNCTION(proc_open)
                /* clean up all the descriptors */
                for (i = 0; i < ndesc; i++) {
                        close(descriptors[i].childend);
-                       close(descriptors[i].parentend);
+                       if (descriptors[i].parentend)
+                               close(descriptors[i].parentend);
                }
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "procve failed - %s", strerror(errno));
                goto exit_fail;
@@ -863,7 +864,8 @@ PHP_FUNCTION(proc_open)
                /* clean up all the descriptors */
                for (i = 0; i < ndesc; i++) {
                        close(descriptors[i].childend);
-                       close(descriptors[i].parentend);
+                       if (descriptors[i].parentend)
+                               close(descriptors[i].parentend);
                }

                php_error_docref(NULL TSRMLS_CC, E_WARNING, "fork failed - %s", strerror(errno));



Reproduce code:
---------------
It's necessary to setup process limit via ulimit so that running the php script gets last allowed slot:

> echo test > tst
> ulimit -p `pgrep -u "\`id -u\`" | wc -l`
> php script.php < tst

script.php:
<?php

$p = proc_open("echo hello", array(0 => array('file', '/dev/null', 'r'), 1 =>
array('pipe', 'r')), $pipes1);

echo file_get_contents("php://stdin")."\n";


Expected result:
----------------
PHP Warning:  proc_open(): fork failed - Resource temporarily unavailable in /usr/home/dolecek/tmp/proc3.php on line 4
test

Actual result:
--------------
PHP Warning:  proc_open(): fork failed - Resource temporarily unavailable in /usr/home/dolecek/tmp/proc3.php on line 4



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-05-31 18:26 UTC] mike@php.net
Could you please provide a more portable reproduce case?

mike@honeybadger:~/build/php-5.2-debug$ bash /tmp/run.sh
/tmp/run.sh: line 1: ulimit: pipe size: cannot modify limit: Invalid argument
sh: line 0: echo: write error: Bad file descriptor
test

 [2006-05-31 21:34 UTC] jdolecek at NetBSD dot org
I think bash uses ulimit -u rathern then ulimit -p for max user processes (I've used ksh).
 [2007-01-02 15:38 UTC] nlopess@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sun Feb 02 09:01:29 2025 UTC