views:

2844

answers:

4

How can you create a temporary FIFO (named pipe) in Python? This should work:

import tempfile

temp_file_name = mktemp()

os.mkfifo(temp_file_name)

open(temp_file_name, os.O_WRONLY)

# ... some process, somewhere, will read it ...

However, I'm hesitant because of the big warning in Python Docs 11.6 and potential removal because it's deprecated.

Thanks for reading.

Brian

EDIT: It's noteworthy that I've tried tempfile.NamedTemporaryFile (and by extension tempfile.mkstemp), but os.mkfifo throws OSError -17: File already exists when you run it on the files that mkstemp/NamedTemporaryFile have created.

+2  A: 

How about using

d = mkdtemp()
t = os.path.join(d, 'fifo')
brendan
That suffers the same security issues as mktemp. Thanks though, Brendan.
Brian M. Hunt
It only has the same security issue if the user has already compromised the account running the script (the directory is 0700). In which case, they can probably do much worse.
Joe
Oop - I was wrong. This doesn't have the same security issue as mktemp because mkfifo() balks if the file exists (i.e. there's no chance for a MiM attack). This would work.
Brian M. Hunt
A: 

Why not just use mkstemp()?

For example:

import tempfile
import os

handle, filename = tempfile.mkstemp()
os.mkfifo(filename)
writer = open(filename, os.O_WRONLY)
reader = open(filename, os.O_RDONLY)
os.close(handle)
Daniel Pryden
os.mkfifo throws an OSError 17: File Exists. Thanks though.
Brian M. Hunt
+1  A: 

If it's for use within your program, and not with any externals, have a look at the Queue module. As an added benefit, python queues are thread-safe.

nilamo
Thanks Nilamo. Unfortunately it's not for internal communication. I'm using Queues elsewhere, though. Thanks for the suggestion.
Brian M. Hunt
Not a problem, just throwing the 'use the simplest possible thing that could work' flag. If you actually need the fifo, then this answer doesn't help at all.
nilamo
+3  A: 

os.mkfifo() will fail with exception OSError: [Errno 17] File exists if the file already exists, so there is no security issue here. The security issue with using tempfile.mktemp() is the race condition where it is possible for an attacker to create a file with the same name before you open it yourself, but since os.mkfifo() fails if the file already exists this is not a problem.

However, since mktemp() is deprecated you shouldn't use it. You can use tempfile.mkdtemp() instead:

import os, tempfile

tmpdir = tempfile.mkdtemp()
filename = os.path.join(tmpdir, 'myfifo')
print filename
try:
    os.mkfifo(filename)
except OSError, e:
    print "Failed to create FIFO: %s" % e
else:
    fifo = open(filename, 'w')
    # write stuff to fifo
    print >> fifo, "hello"
    fifo.close()
    os.remove(filename)
    os.rmdir(tmpdir)

EDIT: I should make it clear that, just because the mktmp() vulnerabitly is averted by this, there are still the other usual security issues that need to be considered, e.g. an attacker could create the fifo (if they had suitable permissions) before your program did which could cause your program to crash if errors/exceptions are not properly handled.

mhawke
Well said. Thanks mhawke.
Brian M. Hunt
Should the `os.rmdir(tmpdir)` not be outside the the try-else block?
Artelius