Skip to content

Processes opened using Unix.open_process* inherit all opened file descriptors (including sockets) #5256

@vicuna

Description

@vicuna

Original bug ID: 5256
Reporter: toots
Status: resolved (set by @xavierleroy on 2017-02-13T17:49:26Z)
Resolution: fixed
Priority: normal
Severity: major
Version: 3.11.2
Target version: 4.05.0 +dev/beta1/beta2/beta3/rc1
Fixed in version: 4.05.0 +dev/beta1/beta2/beta3/rc1
Category: otherlibs
Related to: #5568 #5569 #6947
Monitored by: braibant mehdi @ygrek @glondu @dbuenzli

Bug description

Hi,

Processes opened using Unix.open_process in POSIX systems are spawned using fork(). Therefore, they inherit all file descriptors opened by the calling process.

This leads to many unfortunate minor issues. For instance, if the calling process has opened a port and crashes after calling the external process, then the port remains open until the external process terminates..

More importantly, this is a source of potentially important security issues. By default, processes spawned with Unix.open_process* will have access to any opened file or socket, allowing them to read files' content or sniff network traffic..

I am attaching a simple file that spawns an external process reading a "secret" file.

I do not know whether this is considered as a bug or not for you (or maybe even already known) but I think this may be of sufficent importance to put a Private status until you decide what to do.

Concerning a possible fix, I think the problem is not obvious. In believe that at least this issue should be properly documented in Unix.mli.

I have been reading through different source code and I found the following interesting portable implementation of "closefrom" from openssh's code:
http://anoncvs.mindrot.org/index.cgi/openssh/openbsd-compat/bsd-closefrom.c?view=markup

I believe that a good OCaml solution would consists of the following:

  • A optional hook in Unix.open_process* to execute any given function before spawning a process
  • A default implementation of closefrom
    This way, the programmer could simply pass fun () -> Unix.closefrom 3 to Unix.open_process* and make sure that all file descriptors >= 3 are closed before spawning the external process.

Finally, I have no idea at all whether this issue is present or not under windows. It should be relatively easy to test, though.

I am willing to provide some patches/fixes if you wish so.

File attachments

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions