Linux temp file name

Option 1) /tmp/foobar.$$

The $$ variable is a read-only variable, from which a shell script can find its own Process Identifier, or PID. For example, here, my Bash shell’s Process ID (PID) is 6046 . So echo $$ gives 6046 , and ps -fp 6046 shows the process via the ps command. Further the ps -fp $$ command shows the same result, but without ever having to hard-code the PID itself.

[email protected]:~$ echo $$ 6046 [email protected]:~$ ps -fp 6046 UID PID PPID C STIME TTY TIME CMD steve 6046 2651 0 Mar20 pts/3 00:00:00 bash [email protected]:~$ ps -fp $$ UID PID PPID C STIME TTY TIME CMD steve 6046 2651 0 Mar20 pts/3 00:00:00 bash [email protected]:~$

If we create a file using a pattern like /tmp/foobar.$$ , then it can easily be associated with this particular process. If you know that the foobar script uses files named /tmp/foobar.$$ , then even if there are multiple instances of foobar running on the system, and multiple /tmp/foobar.nnnn files (where nnnn represents an integer PID), then you can correlate each file to the same instance of foobar .

This could be very good, or it could be very bad.

For example, consider this foobar script, which asks you some questions, comments on them, and stores your answers:

A sample run of the script might look like this:

[email protected]:~$ ./foobar.sh What is your favourite colour? red That's nice. I like red too. What is your favourite number? 27 Oh, I don't really like 27 very much. Each to their own. What is your favourite movie? The Blues Brothers That's a good one, isn't it? I do like The Blues Brothers so much. Your answer number 1 was: red Your answer number 2 was: 27 Your answer number 3 was: The Blues Brothers [email protected]:~$

Although this script is quite small, if it was to start creating large amounts of data, then knowing which process the large file (eg, /tmp/foobar.8404 ) was associated with would be useful in identifying what was going on.

However, if someone could write to the file while you were typing in an answer, they could get other data intermingled with the genuine data:

[email protected]:~$ ./foobar.sh What is your favourite colour? yellow That's nice. I like yellow too. What is your favourite number? 93 Oh, I don't really like 93 very much. Each to their own. What is your favourite movie? Star Wars That's a good one, isn't it? I do like Star Wars so much. Your answer number 1 was: yellow Your answer number 2 was: 93 Your answer number 3 was: Extra, unexpected answer here! Your answer number 4 was: Star Wars [email protected]:~$

What happened here was that in another shell the attacker inserted some extra data into the file which was about to be emailed, like this:

[email protected]:~$ ps -eaf|grep foobar.sh steve 8404 19523 0 22:47 pts/1 00:00:00 /bin/bash ./foobar.sh steve 8409 17559 0 22:47 pts/7 00:00:00 grep foobar.sh [email protected]:~$ cat /tmp/foobar.8404 yellow 93 [email protected]:~$ echo "Extra, unexpected answer here!" >> /tmp/foobar.8404 

This is a bit of an artificial example, but you can see the principle. If a bad player knows your PID, they can create or edit files which you will be reading from, writing to, or both. This is quite commonly used in real-world exploits.

Читайте также:  Linux show what is using port

Of course, the attacker would have to be able to get on to your system, but if they have «read» permissions on the file, they can steal your data; if they have «write» permissions, they can edit the data as shown above.

See https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=predictable+filename for just a few examples of vulnerabilities in real-world software related to the ability to predict the name of a temporary file used by a process.

Option 2) /tmp/foobar.$RANDOM

The Bash shell, and others, have a $RANDOM variable, which usually creates an integer between 0 and 32767 (aka 2^^15-1). If the script above used TMPFILE=/tmp/foobar.$RANDOM then nobody would be able to associate the process with the file (it would show up in the /proc/$$/fd/ directory whilst reading/writing the file, but that is a much less reliable way of working out the association).

Probably the biggest problem with this approach is that two instances of the script could run at the same time, and come up with exactly the same filename to use for their own «personal» use.

Option 3) mktemp

A problem with both /tmp/foobar.$$ and /tmp/foobar.$RANDOM is that you can’t be certain that the filename is unique. In the first case, it is likely to be unique, but only because nobody is likely to want to create a file of that name. For example, it is entirely possible that a previous instance of foobar had the same PID (they do get recycled, eventually) and crashed before it could clean up its temporary files. Or that somebody is deliberately trying to manipulate your script. If they know that a long-running process will occasionally try to read from /tmp/foobar.$$ if it exists, then they can create that file any time, and cause your script to read from it.

Читайте также:  Nginx net core linux

In the second case ( /tmp/foobar.$RANDOM ), you could try a loop, like this:

#!/bin/bash TMPFILE=/tmp/foobar.$RANDOM while [ -f $TMPFILE ]; do TMPFILE=/tmp/foobar.$RANDOM done

This would keep on proposing a random filename, until it found one which did not exist, at which point it would create the actual file.

There is still the possibility of a race condition, but it would be better than blindly assuming that the name you’ve come up with is definitely available for your use.

A third and — for most situations — the best way is to use the mktemp utility. It deals with the looping condition above, and actually checks properly for race conditions.

mktemp deals with these situations, ensures that it has created a uniquely-named file, and tells you the name of it.

Running mktemp in an interactive shell shows what it does:

[email protected]:~$ mktemp /tmp/tmp.MgfkDneFhR [email protected]:~$ ls -l /tmp/tmp.MgfkDneFhR -rw------- 1 steve steve 0 Mar 21 23:06 /tmp/tmp.MgfkDneFhR [email protected]:~$ rm -f /tmp/tmp.MgfkDneFhR [email protected]:~$

mktemp determined that /tmp/tmp.MgfkDneFhR was a valid and non-existant filename, created it, and displayed its name to its standard output. We can then list it via ls , and see that it is a zero-length file, owned by steve (the user who called mktemp ).

mktemp ‘s default pattern is tmp.XXXXXXXXXX . You can call it with another pattern; here, mktemp /tmp/foobar.XXXXXXXX resulted in /tmp/foobar.7iFw5vi1 being created; a second run created /tmp/foobar.l2KCpH2J :

[email protected]:~$ mktemp /tmp/foobar.XXXXXXXX /tmp/foobar.7iFw5vi1 [email protected]:~$ rm foobar.yCMTC5RS [email protected]:~$ mktemp /tmp/foobar.XXXXXXXX /tmp/foobar.l2KCpH2J [email protected]:~$ rm /tmp/foobar.l2KCpH2J 

Strictly, to provide a directory as well as a pattern, you should use this method, although the end result is the same:

[email protected]:~$ mktemp -p /tmp foobar.XXXXXXXX /tmp/foobar.spa1kuK6 [email protected]:~$ rm /tmp/foobar.spa1kuK6 

mktemp in use

Notice that I have been careful to delete these temporary files; otherwise, you will end up with a load of randomly-named files, with no idea what they are for!

Of course, mktemp creates a new file each time you call it. Whilst $$ will always return your PID, and therefore will be the same every time you call it, $RANDOM will give a random number each time, and mktemp is guaranteed to give a different file each time. So the way to use mktemp in a shell script is to grab its output as you run mktemp . That way, you always have the file’s actual name — there is no other way to get the name once it has been created. So grab the output from mktemp in one move. Here is the foobar script above (shortened), showing how mktemp is used:

#!/bin/bash TMPFILE=`mktemp` # Now write to the file. read -p "What is your favourite colour? " ANSWER echo "That's nice. I like $ANSWER too." echo $ANSWER > $TMPFILE # And read from the file. cat $TMPFILE | mailx -s "Answers for process $$" [email protected] # Finally, delete this temporary file: rm $TMPFILE

Summary

/tmp/foobar.$$ gives a nice, reasonably unique but predictable filename, which can easily be associated with the running process (which could be good, bad, neither or both, depending on the situation).

Читайте также:  Linux get file encoding

/tmp/foobar.$RANDOM gives a filename which cannot easily be associated with the running process.

mktemp -p /tmp foobar.XXXXXXXX gives a guaranteed-unique filename, which cannot easily be associated with the running process. It also caters for creation of directories.

Check the documentation for mktemp; it has a few other useful switches, such as creating a directory instead of a file.

Источник

mktemp(3) — Linux man page

Feature Test Macro Requirements for glibc (see feature_test_macros(7)): mktemp(): Since glibc 2.12: _BSD_SOURCE || _SVID_SOURCE || (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) Before glibc 2.12: _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED

Description

The mktemp() function generates a unique temporary filename from template. The last six characters of template must be XXXXXX and these are replaced with a string that makes the filename unique. Since it will be modified, template must not be a string constant, but should be declared as a character array.

Return Value

The mktemp() function always returns template. If a unique name was created, the last six bytes of template will have been modified in such a way that the resulting name is unique (i.e., does not exist already) If a unique name could not be created, template is made an empty string.

Errors

The last six characters of template were not XXXXXX.

Conforming To

4.3BSD, POSIX.1-2001. POSIX.1-2008 removes the specification of mktemp().

Notes

The prototype is in for libc4, libc5, glibc1; glibc2 follows the Single UNIX Specification and has the prototype in .

Bugs

Never use mktemp(). Some implementations follow 4.3BSD and replace XXXXXX by the current process ID and a single letter, so that at most 26 different names can be returned. Since on the one hand the names are easy to guess, and on the other hand there is a race between testing whether the name exists and opening the file, every use of mktemp() is a security risk. The race is avoided by mkstemp(3).

Источник

Оцените статью
Adblock
detector