]>
Commit | Line | Data |
---|---|---|
b04d8490 LP |
1 | --- |
2 | title: Using /tmp/ And /var/tmp/ Safely | |
4cdca0af | 3 | category: Interfaces |
b04d8490 LP |
4 | --- |
5 | ||
6 | # Using `/tmp/` And `/var/tmp/` Safely | |
7 | ||
8 | `/tmp/` and `/var/tmp/` are two world-writable directories Linux systems | |
9 | provide for temporary files. The former is typically on `tmpfs` and thus | |
10 | backed by RAM/swap, and flushed out on each reboot. The latter is typically a | |
11 | proper, persistent file system, and thus backed by physical storage. This | |
12 | means: | |
13 | ||
14 | 1. `/tmp/` should be used for smaller, size-bounded files only; `/var/tmp/` | |
15 | should be used for everything else. | |
16 | ||
17 | 2. Data that shall survive a boot cycle shouldn't be placed in `/tmp/`. | |
18 | ||
19 | If the `$TMPDIR` environment variable is set, use that path, and neither use | |
20 | `/tmp/` nor `/var/tmp/` directly. | |
21 | ||
22 | See | |
23 | [file-hierarchy(7)](https://www.freedesktop.org/software/systemd/man/file-hierarchy.html) | |
24 | for details about these two (and most other) directories of a Linux system. | |
25 | ||
26 | ## Common Namespace | |
27 | ||
28 | Note that `/tmp/` and `/var/tmp/` each define a common namespace shared by all | |
29 | local software. This means guessable file or directory names below either | |
30 | directory directly translate into a 🚨 Denial-of-Service (DoS) 🚨 vulnerability | |
31 | or worse: if some software creates a file or directory `/tmp/foo` then any | |
32 | other software that wants to create the same file or directory `/tmp/foo` | |
33 | either will fail (as the file already exists) or might be tricked into using | |
56ee4d70 | 34 | untrusted files. Hence: do not use guessable names in `/tmp/` or `/var/tmp/` — |
b04d8490 LP |
35 | if you do you open yourself up to a local DoS exploit or worse. (You can get |
36 | away with using guessable names, if you pre-create subdirectories below `/tmp/` | |
37 | for them, like X11 does with `/tmp/.X11-unix/` through `tmpfiles.d/` | |
38 | drop-ins. However this is not recommended, as it is fully safe only if these | |
39 | directories are pre-created during early boot, and thus problematic if package | |
40 | installation during runtime is permitted.) | |
41 | ||
42 | To protect yourself against these kinds of attacks Linux provides a couple of | |
43 | APIs that help you avoiding guessable names. Specifically: | |
44 | ||
45 | 1. Use [`mkstemp()`](http://man7.org/linux/man-pages/man3/mkstemp.3.html) | |
46 | (POSIX), `mkostemp()` (glibc), | |
47 | [`mkdtemp()`](http://man7.org/linux/man-pages/man3/mkdtemp.3.html) (POSIX), | |
48 | [`tmpfile()`](http://man7.org/linux/man-pages/man3/tmpfile.3.html) (C89) | |
49 | ||
50 | 2. Use [`open()`](http://man7.org/linux/man-pages/man2/open.2.html) with | |
51 | `O_TMPFILE` (Linux) | |
52 | ||
53 | 3. [`memfd_create()`](http://man7.org/linux/man-pages/man2/memfd_create.2.html) | |
54 | (Linux; this doesn't bother with `/tmp/` or `/var/tmp/` at all, but uses the | |
55 | same RAM/swap backing as `tmpfs` uses, hence is very similar to `/tmp/` | |
56 | semantics.) | |
57 | ||
58 | For system services systemd provides the `PrivateTmp=` boolean setting. If | |
59 | turned on for a service (👍 which is highly recommended), `/tmp/` and | |
60 | `/var/tmp/` are replaced by private sub-directories, implemented through Linux | |
61 | file system namespacing and bind mounts. This means from the service's point of | |
62 | view `/tmp/` and `/var/tmp/` look and behave like they normally do, but in | |
63 | reality they are private sub-directories of the host's real `/tmp/` and | |
64 | `/var/tmp/`, and thus not system-wide locations anymore, but service-specific | |
65 | ones. This reduces the surface for local DoS attacks substantially. While it is | |
66 | recommended to turn this option on, it's highly recommended for applications | |
67 | not to rely on this solely to avoid DoS vulnerabilities, because this option is | |
68 | not available in environments where file system namespaces are prohibited, for | |
69 | example in certain container environments. This option is hence an extra line | |
70 | of defense, but should not be used as an excuse to rely on guessable names in | |
71 | `/tmp/` and `/var/tmp/`. When this option is used, the per-service temporary | |
72 | directories are removed whenever the service shuts down, hence the lifecycle of | |
73 | temporary files stored in it is substantially different from the case where | |
74 | this option is not used. Also note that some applications use `/tmp/` and | |
75 | `/var/tmp/` for sharing files and directories. If this option is turned on this | |
76 | is not possible anymore as after all each service gets its own instances of | |
77 | both directories. | |
78 | ||
79 | ## Automatic Clean-Up | |
80 | ||
81 | By default, `systemd-tmpfiles` will apply a concept of ⚠️ "ageing" to all files | |
82 | and directories stored in `/tmp/` and `/var/tmp/`. This means that files that | |
83 | have neither been changed nor read within a specific time frame are | |
84 | automatically removed in regular intervals. (This concept is not new to | |
85 | `systemd-tmpfiles` btw, it's inherited from previous subsystems such as | |
86 | `tmpwatch`.) By default files in `/tmp/` are cleaned up after 10 days, and | |
87 | those in `/var/tmp` after 30 days. | |
88 | ||
89 | This automatic clean-up is important to ensure disk usage of these temporary | |
90 | directories doesn't grow without bounds, even when programs abort unexpectedly | |
91 | or otherwise don't clean up the temporary files/directories they create. On the | |
92 | other hand it creates problems for long-running software that does not expect | |
93 | temporary files it operates on to be suddenly removed. There are a couple of | |
94 | strategies to avoid these issues: | |
95 | ||
96 | 1. Make sure to always keep a file descriptor to the temporary files you | |
97 | operate on open, and only access the files through them. This way it doesn't | |
98 | matter whether the files have been unlinked from the file system: as long as | |
99 | you have the file descriptor open you can still access the file for both | |
100 | reading and writing. When operating this way it is recommended to delete the | |
101 | files right after creating them to ensure that on unexpected program | |
102 | termination the files or directories are implicitly released by the kernel. | |
103 | ||
104 | 2. 🥇 Use `memfd_create()` or `O_TMPFILE`. This is an extension of the | |
105 | suggestion above: files created this way are never linked under a filename | |
106 | in the file system. This means they are not subject to ageing (as they come | |
107 | unlinked out of the box), and there's no time window where a directory entry | |
108 | for the file exists in the file system, and thus behaviour is fully robust | |
109 | towards unexpected program termination as there are never files on disk that | |
110 | need to be explicitly deleted. | |
111 | ||
112 | 3. 🥇 Operate below a sub-directory of `/tmp/` and `/var/tmp/` you created, and | |
113 | take a BSD file lock ([`flock(dir_fd, | |
114 | LOCK_SH)`](http://man7.org/linux/man-pages/man2/flock.2.html)) on that | |
115 | sub-directory. This is particularly interesting when operating on more than | |
116 | a single file, or on file nodes that are not plain regular files, for | |
117 | example when extracting a tarball to a temporary directory. The ageing | |
118 | algorithm will skip all directories (and everything below them) that are | |
119 | locked through a BSD file lock. As BSD file locks are automatically released | |
120 | when the file descriptor they are taken on is closed, and all file | |
121 | descriptors opened by a process are implicitly closed when it exits, this is | |
122 | a robust mechanism that ensures all temporary files are subject to ageing | |
123 | when the program that owns them dies, but not while it is still running. Use | |
124 | this when decompressing tarballs that contain files with old | |
125 | modification/access times, as extracted files are otherwise immediately | |
126 | candidates for deletion by the ageing algorithm. The | |
127 | [`flock`](http://man7.org/linux/man-pages/man1/flock.1.html) tool of the | |
128 | `util-linux` packages makes this concept available to shell scripts. Note | |
129 | that `systemd-tmpfiles` only checks for BSD file locks on directories, locks | |
130 | on other types of file nodes (including regular files) are not considered. | |
131 | ||
132 | 4. Keep the access time of all temporary files created current. In regular | |
133 | intervals, use `utimensat()` or a related call to update the access time | |
134 | ("atime") of all files that shall be kept around. Since the ageing algorithm | |
135 | looks at the access time of files when deciding whether to delete them, it's | |
136 | sufficient to update their access times in sufficiently frequent intervals to | |
137 | ensure the files are not deleted. Since most applications (and tools such as | |
138 | `ls`) primarily care for the modification time (rather than the access time) | |
139 | using the access time for this purpose should be acceptable. | |
140 | ||
141 | 5. Set the "sticky" bit on regular files. The ageing logic skips deletion of | |
142 | all regular files that have the sticky bit (`chmod +t`) set. This is | |
143 | honoured for regular files only however, and has no effect on directories as | |
144 | the sticky bit has a different meaning for them. | |
145 | ||
146 | 6. Don't use `/tmp/` or `/var/tmp/`, but use your own sub-directory under | |
147 | `/run/` or `$XDG_RUNTIME_DIRECTORY` (the former if privileged, the latter if | |
148 | unprivileged), or `/var/lib/` and `~/.config/` (similar, but with | |
149 | persistency and suitable for larger data). The two temporary directories | |
150 | `/tmp/` and `/var/tmp/` come with the implicit clean-up semantics described | |
151 | above. When this is not desired, it's possible to create private per-package | |
152 | runtime or state directories, and place all temporary files there. However, | |
153 | do note that this means opting out of any kind of automatic clean-up, and it | |
154 | is hence particularly essential that the program cleans up generated files | |
155 | in these directories when they are no longer needed, in particular when the | |
156 | program dies unexpectedly. Note: this strategy is only really suitable for | |
157 | packages that operate in a "system wide singleton" fashion with "long" | |
5238e957 | 158 | persistence of its data or state, i.e. as opposed to programs that run in |
b04d8490 LP |
159 | multiple parallel or short-living instances. This is because a private |
160 | directory under `/run` (and the other mentioned directories) is itself | |
161 | system and package specific singleton with greater longevity. | |
162 | ||
163 | 5. Exclude your temporary files from clean-ups via a `tmpfiles.d/` drop-in | |
164 | (which includes drop-ins in the runtime-only directory | |
165 | `/run/tmpfiles.d/`). The `x`/`X` line types may be used to exclude files | |
166 | matching the specified globbing patterns from the ageing logic. If this is | |
167 | used, automatic clean-up is not done for matching files and directory, and | |
168 | much like with the previous option it's hence essential that the program | |
169 | generating these temporary files carefully removes the temporary files it | |
170 | creates again, and in particular so if it dies unexpectedly. | |
171 | ||
172 | 🥇 The semantics of options 2 (in case you only deal with temporary files, not | |
173 | directories) and 3 (in case you deal with both) in the list above are in most | |
174 | cases the most preferable. It is thus recommended to stick to these two | |
175 | options. | |
176 | ||
177 | While the ageing logic is very useful as a safety concept to ensure unused | |
178 | files and directories are eventually removed a well written program avoids even | |
179 | creating files that need such a clean-up. In particular: | |
180 | ||
181 | 1. Use `memfd_create()` or `O_TMPFILE` when creating temporary files. | |
182 | ||
183 | 2. `unlink()` temporary files right after creating them. This is very similar | |
184 | to `O_TMPFILE` behaviour: consider deleting temporary files right after | |
185 | creating them, while keeping open a file descriptor to them. Unlike | |
186 | `O_TMPFILE` this method also works on older Linux systems and other OSes | |
187 | that do not implement `O_TMPFILE`. | |
188 | ||
189 | ## Disk Quota | |
190 | ||
191 | Generally, files allocated from `/tmp/` and `/var/tmp/` are allocated from a | |
192 | pool shared by all local users. Moreover the space available in `/tmp/` is | |
193 | generally more restricted than `/var/tmp/`. This means, that in particular in | |
194 | `/tmp/` space should be considered scarce, and programs need to be prepared | |
195 | that no space is available. Essential programs might require a fallback logic | |
196 | using a different location for storing temporary files hence. Non-essential | |
197 | programs at least need to be prepared for `ENOSPC` errors and generate useful, | |
198 | actionable error messages. | |
199 | ||
200 | Some setups employ per-user quota on `/var/tmp/` and possibly `/tmp/`, to make | |
201 | `ENOSPC` situations less likely, and harder to trigger from unprivileged | |
202 | users. However, in the general case no such per-user quota is implemented | |
203 | though, in particular not when `tmpfs` is used as backing file system, because | |
204 | — even today — `tmpfs` still provides no native quota support in the kernel. | |
205 | ||
206 | ## Early Boot Considerations | |
207 | ||
208 | Both `/tmp/` and `/var/tmp/` are not necessarily available during early boot, | |
209 | or — if they are available early — are not writable. This means software that | |
210 | is intended to run during early boot (i.e. before `basic.target` — or more | |
211 | specifically `local-fs.target` — is up) should not attempt to make use of | |
212 | either. Interfaces such as `memfd_create()` or files below a package-specific | |
213 | directory in `/run/` are much better options in this case. (Note that some | |
214 | packages instead use `/dev/shm/` for temporary files during early boot; this is | |
215 | not advisable however, as it offers no benefits over a private directory in | |
216 | `/run/` as both are backed by the same concept: `tmpfs`. The directory | |
217 | `/dev/shm/` exists to back POSIX shared memory (see | |
218 | [`shm_open()`](http://man7.org/linux/man-pages/man3/shm_open.3.html) and | |
219 | related calls), and not as a place for temporary files. `/dev/shm` is | |
220 | problematic as it is world-writable and there's no automatic clean-up logic in | |
221 | place.) |