Shell Script mktemp, what's the best method to create temporary named pipe?
Solution 1
tmppipe=$(mktemp -u)
mkfifo -m 600 "$tmppipe"
Unlike regular file creation, which is prone to being hijacked by an existing file or a symbolic link, the creation of a name pipe through mkfifo
or the underlying function either creates a new file in the specified place or fails. Something like : >foo
is unsafe because if the attacker can predict the output of mktemp
then the attacker can create the target file for himself. But mkfifo foo
would fail in such a scenario.
If you need full POSIX portability, mkfifo -m 600 /tmp/myfifo
is safe against hijacking but prone to a denial of service; without access to a strong random file name generator, you would need to manage retry attempts.
If you don't care for the subtle security problems around temporary files, you can follow a simple rule: create a private directory, and keep everything in there.
tmpdir=
cleanup () {
trap - EXIT
if [ -n "$tmpdir" ] ; then rm -rf "$tmpdir"; fi
if [ -n "$1" ]; then trap - $1; kill -$1 $$; fi
}
tmpdir=$(mktemp -d)
trap 'cleanup' EXIT
trap 'cleanup HUP' HUP
trap 'cleanup TERM' TERM
trap 'cleanup INT' INT
mkfifo "$tmpdir/pipe"
Solution 2
Use the "dry-run" option:
mkfifo $(mktemp -ut pipe.XXX)
Solution 3
You can use mktemp
to create a temporary file, then delete it and create a named pipe with the same name.
For example:
TMPPIPE=$(mktemp -t pipe.XXX) && {
rm -f $TMPPIPE
mkfifo $TMPPIPE
}
Related videos on Youtube
J. M. Becker
Updated on September 18, 2022Comments
-
J. M. Becker over 1 year
I'm aware its best to create temporary files with
mktemp
, but what about named pipes?I prefer things to be as POSIX compliant as possible, but Linux only is acceptable. Avoiding Bashisms is my only hard criteria, as I write in
dash
. -
Nikhil Mulley over 12 yearsoh ok, best is to create them under /tmp, they are temporary files by definition and will clear off once the system reboots. Or better yet, have a shell function which will create the namedpipe out of the
mktemp
result itself (ofcourse by deleting the temp file first and then runningmkfifo
on the same).mktemp
can also be used to create a temporary directory, try with-t -d
switch. -
J. M. Becker over 12 yearsDoes deleting the
$TMPPIPE
before themkfifo
avoid the 'unsafe' problem associated from doingTMPPIPE=`mktemp -u` ; mkfifo $TMPPIPE
? -
CurtainDog over 12 yearsAccording to the man pages, the use of the
-u
option "is not encouraged". -
polemon over 12 years@dogbane So is the use of
-t
, but as long as it works reliably, I'd go with it. -
CurtainDog over 12 yearssorry, where does it say that
-t
is discouraged? -
polemon over 12 years@dogbane If it is in any way critical, I'd make a tiny C application, calling the
mkstemp()
function (linux.die.net/man/3/mkstemp). The-t
switch isn't discouraged, it is-p
, my bad. -
Gilles 'SO- stop being evil' over 12 years@TechZilla
mkfifo
is actually safe, unlike usual regular file creation from the shell. If it wasn't, creating a file then deleting it would not help at all (in fact it would greatly facilitate the attacker's job by not requiring him to guess the file name). So dogbane's answer works, but the intermediate file creation is a useless complication. -
J. M. Becker over 12 years@Gilles, Do you know in what regard the
mktemp
man page called the-u
option 'unsafe'? -
J. M. Becker over 12 years@dogbane, I voted up on your answer, and your comments which I felt were solid. Although, I already completed this yesterday.. I was just waiting to see when someone posted either my solution, or hopefully a better one. So even though I used
mktemp -d
you still got some points for your input. Thank you for all your help, I really appreciate it! -
J. M. Becker over 12 yearsI actually already chose this as my solution earlier yesterday, I was waiting to see if someone posted it, or a better one. I also felt the dir was the way to go, in my case. Regardless... Thanks for the help, I appreciate it.
-
Gilles 'SO- stop being evil' over 12 years@TechZilla
mktemp -u
is unsafe when creating a regular file, because it provides the protection against denial of service (if the name it generates is sufficiently unpredictable) but does not prevent an attacker from creating the file under the program's nose. Creating a fifo instead of a regular file is a rare use case that the man page doesn't address. -
Chris Wolfe about 9 yearsShouldn't the trap command be
trap "rm -rf '$tempdir'" EXIT HUP INT TERM
? Can trap do it's own variable expansion? -
Gilles 'SO- stop being evil' about 9 years@Six Your command would expand
$tempdir
at the time thetrap
command is evaluated, not at the time the trap is triggered. In this case, it doesn't make any difference, except that your code breaks horribly if the value oftempdir
contains a single quote, whereas my code always works. -
Chris Wolfe about 9 years@Gilles That's a nice feature. I had tried your single quote example without luck, so I thought trap was unable to evaluate variables at runtime. It turned out that my
$tempdir
was declared locally and it must be defined globally for trap to have access to it. Makes sense now... -
MestreLion over 8 years@Gilles ... as long as
$tempdir
value does not change either, which is acceptable for basically all purposes. Just be careful not to use the same name to create multiple temp files/dirs... -
Sukima over 6 years@gilles Why do you trap
INT HUP TERM
? Doesn'tEXIT
cover all of those? -
Robin A. Meade about 4 yearsWould
readonly tmpdir=$(mktemp -d)
protect against the problem MestreLion mentioned, namely that tmpdir might be accidentally redefined later in the script? -
Gilles 'SO- stop being evil' about 4 years@RobinA.Meade Yes, if the shell has
readonly
. But if that's an issue, you have bigger problems. If your script is so complex that you can't keep track of all the variables that it uses, you should probably use a different language.