summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-26 04:06:11 +0000
committerLeah Rowe <leah@libreboot.org>2026-03-26 04:07:39 +0000
commit2bb80f5a3efb376d297e9381cf6c1f95e55835e8 (patch)
treeeff2ca56a9cc74c43fe0e889d277dbeaff698024
parentf9e206c959cce498c8416a79d6c5db9a04067af6 (diff)
mkhtemp readme
Signed-off-by: Leah Rowe <leah@libreboot.org>
-rw-r--r--util/libreboot-utils/README.md223
-rw-r--r--util/libreboot-utils/mkhtemp.c67
2 files changed, 232 insertions, 58 deletions
diff --git a/util/libreboot-utils/README.md b/util/libreboot-utils/README.md
new file mode 100644
index 00000000..135b5dbe
--- /dev/null
+++ b/util/libreboot-utils/README.md
@@ -0,0 +1,223 @@
+Mkhtemp - Hardened mktemp
+-------------------------
+
+Create new files and directories randomly as determined by
+the user's TMPDIR, or fallback. Portable to Linux and BSD.
+
+NOTE: on Linux, it uses openat2 for i/o, which is more
+secure. BSDs only have the older openat for now, so
+mkhtemp uses that there. However, even there, there are
+several ways in which mkhtemp is better than every
+previous mktemp.
+
+```
+/*
+ * 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.
+ */
+```
+
+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-
+mounted by mkhtemp itself, mid-operation. This re-mounting
+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~~ /jk
+
+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).
diff --git a/util/libreboot-utils/mkhtemp.c b/util/libreboot-utils/mkhtemp.c
index 261227cb..7564800a 100644
--- a/util/libreboot-utils/mkhtemp.c
+++ b/util/libreboot-utils/mkhtemp.c
@@ -1,47 +1,17 @@
/* SPDX-License-Identifier: MIT
* Copyright (c) 2026 Leah Rowe <leah@libreboot.org>
*
- * WORK IN PROGRESS (proof of concept), or, v0.0000001
- *
- * Mkhtemp - Hardened mktemp. Create files and directories
- * randomly as determined by user's TMPDIR, or fallback. It
- * attemps to provide mitigation against several TOCTOU-based
- * attacks e.g. directory rename / symlink attacks, and it
- * 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 on Linux, with additional hardening; BSD
- * projects only have openat so the code uses that there.
+ * Hardened mktemp (mkhtemp!)
*
- * 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.
- *
- * 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.
+ * WORK IN PROGRESS (proof of concept), or, v0.0000001
+ * DO NOT PUT THIS IN YOUR LINUX DISTRO YET.
*
- * 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.
+ * I will remove this notice when the code is mature, and
+ * probably contact several of your projects myself.
*
- * 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.
+ * See README. This is an ongoing project; no proper docs
+ * yet, and no manpage (yet!) - the code is documentation,
+ * while the specification that it implements evolves.
*/
#if defined(__linux__) && !defined(_GNU_SOURCE)
@@ -187,25 +157,6 @@ err_usage:
"usage: %s [-d] [-p dir] [template]\n", getnvmprogname());
}/*
-
( >:3 )
/| |\
- / \
-
-
-
-
-
- */
-
-
-
-
-
-
-
-
-
-
-
-
+ / \ */