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