php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67383 exec() leaks file and socket descriptors to called program
Submitted: 2014-06-05 11:25 UTC Modified: 2014-08-04 19:35 UTC
Votes:17
Avg. Score:4.5 ± 0.8
Reproduced:15 of 15 (100.0%)
Same Version:10 (66.7%)
Same OS:12 (80.0%)
From: langemeijer@php.net Assigned:
Status: Open Package: *General Issues
PHP Version: Irrelevant OS: linux
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: langemeijer@php.net
New email:
PHP Version: OS:

 

 [2014-06-05 11:25 UTC] langemeijer@php.net
Description:
------------
PHP doesn't sanitize opened file descriptors opened by PHP itself before executing a program.

This should be fixed by opening all sockets with SOCK_CLOEXEC and all run a fcntl(file, F_SETFD, FD_CLOEXEC); on all newly opened filedescriptors

SOCK_CLOEXEC and FD_CLOEXEC cause exec() to close the descriptors in the fork()ed child process.

Note that this is similar, but not identical to bug #38915, bug #15529 and  bug #20302 which are about file descriptors and sockets opened by Apache.

Note that my patch also sets SOCK_CLOEXEC on the fastcgi listening socket and other similar usages of sockets.

The patch was generated on php-src master branch. I'm happy to do some more work on it if any of you feel this is required.


Patches

SOCK_CLOEXEC-and-FD_CLOEXEC (last revision 2014-06-05 11:26 UTC by casper at langemeijer dot eu)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-07-21 11:54 UTC] langemeijer@php.net
-Status: Open +Status: Duplicate
 [2014-07-21 11:54 UTC] langemeijer@php.net
This is a duplicate of bug #67383 (Which contains a patch that should be merged by someone!)
 [2014-08-04 19:35 UTC] langemeijer@php.net
-Status: Duplicate +Status: Open
 [2014-08-04 19:35 UTC] langemeijer@php.net
Obviously, this bug is not a duplicate of itself. Previous comment was a clerical error.
 [2016-01-26 16:41 UTC] brak at gameservers dot com
This issue can cause you to be unable to restart PHP-FPM.  Specifically, this leaks the webserver -> php-fpm socket to any process you execute.  This prevents PHP-FPM from cleanly restarting until the process exits, because the socket will already be in use.

Quick example:
<?php
        $p = popen('/bin/bash -c "sleep 60"','w');
        pclose($p);
?>

Now find the child process (ps aux | grep sleep) and lsof -p XXX -n:

sleep   13443 nobody    0r  FIFO      0,8      0t0 10237775 pipe
sleep   13443 nobody    1u   CHR      1,3      0t0     3920 /dev/null
sleep   13443 nobody    2u   CHR      1,3      0t0     3920 /dev/null
sleep   13443 nobody    4u  IPv4 10236693      0t0      TCP 127.0.0.1:cslistener->127.0.0.1:53151 (ESTABLISHED)
sleep   13443 nobody    9u   REG      0,9        0     3918 [eventpoll]


FD 4 there is the TCP connection from the PHP worker process to the web server.
 [2017-10-11 08:29 UTC] daverandom@php.net
It is, in my opinion, not desirable to do this blindly for all fds.

It should be possible to specify this on a per-fd basis. For streams this can be done with a context option (or multiple context options for sockets vs files), but for e.g. mysqlnd it's trickier - most likely these should default to not being inheritable, but this will need to be taken care of by the extension.

A stream context option would cover 99% of cases where it's relevant, though. I would be fine with having the context option default to setting the flag, and needing to explicitly make an fd heritable, but this would be a BC break.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Dec 04 08:01:29 2024 UTC