summaryrefslogtreecommitdiff
path: root/util/libreboot-utils/README.md
blob: 6e94035b9e305500295e0b3c3d327f971a939ce7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
Mkhtemp - Hardened mktemp
-------------------------

Just like normal mktemp, but hardened.

Create new files and directories randomly as determined by
the user's TMPDIR, or fallback. These temporary files and
directories can be generated from e.g. shell scripts, running
mkhtemp. There is also a library that you could use in your
program. Portable to Linux and BSD. **WORK IN PROGRESS.
This is a very new project. Expect bugs - a stable release
will be announced, when the code has matured.**

A brief summary of *why* mkhtemp is more secure (more
details provided later in this readme - please also
read the source code):

Detect and mitigate symlink attacks, directory access
race conditions, unsecure TMPDIR (e.g. bad enforce sticky
bit policy on world writeable dirs), implement in user
space a virtual sandbox (block directory escape and resolve
paths by walking from `/` manually instead of relying on
the kernel/system), voluntarily error out (halt all
operation) if accessing files you don't own - that's why
sticky bits are checked for example, even when you're root.

It... blocks symlinks, relative paths, attempts to prevent
directory escape (outside of the directory that the file
you're creating is in), basically implementing an analog
of something like e.g. unveil, but in userspace!

Mkhtemp is designed to be the most secure implementation
possible, of mktemp, offering a heavy amount of hardening
over traditional mktemp. Written in C89, and the plan is
very much to keep this code portable over time - patches
very much welcome.

i.e. please read the source code

```
/*
 * WARNING: WORK IN PROGRESS.
 * Do not use this software in
 * your distro yet. It's ready
 * when it's ready. Read the src.
 *
 * What you see is an early beta.
 *
 * Please do not merge this in
 * your Linux distro package repo
 * yet (unless maybe you're AUR).
 */
```

Supported mktemp flags:

```
mkhtemp: usage: mkhtemp [-d] [-p dir] [template]

 -p DIR       <-- set directory, overriding TMPDIR
 -d           <-- make a directory instead of a file
 -q           <-- silence errors (exit status unchanged)
```

The rest of them will be added later (the same ones
that GNU and BSD mktemp implement). With these options,
you can generate files/directories already.

You can also write a template at the end. e.g.

```
mkhtemp -d -p path/to/directory vickysomething_XXXXXXXXXXX
```

On most sane/normal setups, the program should already
actually work, but please know that it's very different
internally than every other mktemp implementation.

Read the source code if you're interested. As of this
time of writing, mkhtemp is very new, and under
development. A stable release will be announced when ready.

### What does mkhtemp do differently?

This software attempts to provide mitigation against
several TOCTOU-based
attacks e.g. directory rename / symlink / re-mount, and
generally provides much higher strictness than previous
implementations such as mktemp, mkstemp or even mkdtemp.
It uses several modern features by default, e.g. openat2
and `O_TMPFILE` (plus `O_EXCL`) on Linux, with additional
hardening; BSD projects only have openat so the code uses
that there, but some (not all) of the kinds of checks
Openat2 enforces are done manually (in userspace).

File system sandboxing in userspace (pathless discovery,
and operations are done only with FDs). At startup, the
root directory is opened, and then everything is relative
to that.

Many programs rely on mktemp, and they use TMPDIR in a way
that is quite insecure. Mkhtemp intends to change that,
quite dramatically, with: userspace sandbox (and use OS
level options e.g. OBSD pledge where available), constant
identity/ownership checks on files, MUCH stricter ownership
restrictions (e.g. enforce sticky bit policy on world-
writeable tmpdirs), preventing operation on other people's
files (only your own files) - even root is restricted,
depending on how the code is compiled. Please read the code.

Basically, the gist of it is that normal mktemp *trusts*
your system is set up properly. It will just run however
you tell it to, on whatever directory you tell it to, and
if you're able to write to it, it will write to it.
Some implementations (e.g. OpenBSD one) do some checks,
but not all of them do *all* checks. The purpose of
mkhtemp is to be as strict as possible, while still being
reliable enough that people can use it. Instead of catering
to legacy requirements, mkhtemp says that systems should
be secure. So if you're running in an insecure environment,
the goal of mkhtemp is to *exit* when you run it; better
this than files being corrupted.

Security and reliability are the same thing. They both
mean that your computer is behaving as it should, in a
manner that you can predict.

It doesn't matter how many containers you have, or how
memory-safe your programming language is, the same has
been true forever: code equals bugs, and code usually
has the same percentage of bugs, so more code equals
more bugs. Therefore, highly secure systems (such as
OpenBSD) typically try to keep their code as small and
clean as possible, so that they can audit it. Mkhtemp
assumes that your system is hostile, and is designed
accordingly.

What?
-----

This is the utility version, which makes use of the also-
included library. No docs yet - source code are the docs,
and the (ever evolving, and hardening) specification.

This was written from scratch, for use in nvmutil, and
it is designed to be portable (BSD, Linux). Patches
very much welcome.

Caution
-------

This is a new utility. Expect bugs.

```
WARNING: This is MUCH stricter than every other mktemp
         implementation, even more so than mkdtemp or
         the OpenBSD version of mkstemp. It *will* break,
         or more specifically, reveal the flaws in, almost
         every major critical infrastructure, because most
         people already use mktemp extremely insecurely.
```

This tool is written by me, for me, and also Libreboot, but
it will be summitted for review to various Linux distros
and BSD projects once it has reached maturity.

### Why was this written?

Atomic writes were implemented in nvmutil (Libreboot's
Intel GbE NVM editor), but one element remained: the
program mktemp, itself, which has virtually no securitty
checks whatsoever. GNU and BSD implementations use
mkstemp now, which is a bit more secure, and they offer
additional hardening, but I wanted to be reasonably
assured that my GbE files were not being corrupted in
any way, and that naturally led to writing a hardened
tool. It was originally just going to be for nvmutil,
but then it became its own standard utility.

Existing implementations of mktemp just simply do not
have sufficient checks in place to prevent misuse. This
tool, mkhtemp, intentionally focuses on being secure
instead of easy. For individuals just running Linux on
their personal machine, it might not make much difference,
but corporations and projects running computers for lots
of big infrastructure need something reliable, since
mktemp is just one of those things everyone uses.
Every big program needs to make temporary files.

But the real reason I wrote this tool is because, it's
fun, and because I wanted to challenge myself.

Roadmap
-------

Some things that are in the near future for mkhtemp
development:

Thoroughly document every known case of CVEs in the wild,
and major attacks against individuals/projects/corporations
that were made possible by mktemp - that mkhtemp might
have prevented. There are several.

More hardening; still a lot more that can be done, depending
on OS. E.g. integrate FreeBSD capsicum.

Another example: although usually reliable, comparing the
inode and device of a file/directory isn't by itself sufficient.
There are other checks that mkhtemp does; for example I could
implement it so that directories are more aggressively re-
opened by mkhtemp itself, mid-operation. This re-opening
would be quite expensive computationally, but it would then
allow us to re-check everything, since we store state from
when the program starts.

Tidy up the code: the current code was thrown together in
a week, and needs tidying. A proper specification should be
written, to define how it works, and then the code should
be auditted for compliance. A lot of the functions are
also quite complex and do a lot; they could be split up.

Right now, mkhtemp mainly returns a file descriptor and
a path, after operation, ironic given the methods it uses
while opening your file/dir. After it's done, you then have
to handle everything again. Mkhtemp could keep everything
open instead, and continue to provide verification; in
other words, it could provide a completely unified way for
Linux/BSD programs to open files, write to them atomically,
and close. Programs like Vim will do this for example, or
other text editors, but every program has its own way. So
what mkhtemp could do is provide a well-defined API alongside
its mktemp hardening. Efforts would be made to avoid
feature creep, and ensure that the code remains small and
nimble.

Compatibility mode: another thing is that mkhtemp is a bit
too strict for some users, so it may break some setups. What
it could do is provide a compatibility mode, and in this
mode, behave like regular mktemp. That way, it could become
a drop-in replacement on Linux distros (and BSDs if they
want it), while providing a more hardened version and
recommending that where possible.

~~Rewrite it in rust~~ (nothing against it though, I just like C89 for some reason)

Also, generally document the history of mktemp, and how
mkhtemp works in comparison.

Also a manpage.

Once all this is done, and the project is fully polished,
then it will be ready for your Linux distro. For now, I
just use it in nvmutil (and I also use it on my personal
computer).