diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-24 00:28:15 +0000 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-24 01:25:53 +0000 |
| commit | f2544d094ba88e1cfbb7993ad67444852cfd5efd (patch) | |
| tree | 252172594a1284e59e88c73c22f0201508809022 /util/libreboot-utils/mkhtemp.c | |
| parent | afcd535816b45fd7b0e0d07c1a8580f6f462f5e4 (diff) | |
util/mkhtemp: new utility (hardened mktemp)
part of the same code library as nvmutil.
as part of this, i renamed util/nvmutil
to util/libreboot-utils/ because it is
now a multi-utility codebase.
this is more efficient, since i also wish
to use mkhtemp (function) in nvmutil.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/libreboot-utils/mkhtemp.c')
| -rw-r--r-- | util/libreboot-utils/mkhtemp.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/util/libreboot-utils/mkhtemp.c b/util/libreboot-utils/mkhtemp.c new file mode 100644 index 00000000..5e7fcc0f --- /dev/null +++ b/util/libreboot-utils/mkhtemp.c @@ -0,0 +1,139 @@ +/* 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. + * + * 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. + * + * 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. + */ + +#if defined(__linux__) && !defined(_GNU_SOURCE) +/* for openat2 on linux */ +#define _GNU_SOURCE 1 +#endif + +#ifdef __OpenBSD__ +#include <sys/param.h> /* pledge(2) */ +#endif + +#include <sys/types.h> +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "include/common.h" + +int +main(int argc, char *argv[]) +{ + char *s = NULL; + int fd = -1; + char c; + int type = MKHTEMP_FILE; + size_t len; + +#if defined (PATH_LEN) && \ + (PATH_LEN) >= 256 + size_t maxlen = PATH_LEN; +#else + size_t maxlen = 4096; +#endif + +/* https://man.openbsd.org/pledge.2 */ +#if defined(__OpenBSD__) && defined(OpenBSD) +#if (OpenBSD) >= 509 + if (pledge("stdio flock rpath wpath cpath", NULL) == -1) + err_no_cleanup(errno, "pledge, main"); +#endif +#endif + + while ((c = + getopt(argc, argv, "d")) != -1) { + + switch(c) { + case 'd': + + type = MKHTEMP_DIR; + break; + default: + + err_no_cleanup(EINVAL, + "usage: mkhtemp [-d]\n"); + } + } + + if (new_tmp_common(&fd, &s, type) < 0) + err_no_cleanup(errno, NULL); + +#if defined(__OpenBSD__) && defined(OpenBSD) +#if (OpenBSD) >= 509 + if (pledge("stdio", NULL) == -1) + err_no_cleanup(errno, "pledge, exit"); +#endif +#endif + + if (s == NULL) + err_no_cleanup(EFAULT, "bad string initialisation"); + + if (*s == '\0') + err_no_cleanup(EFAULT, "empty string initialisation"); + + if (slen(s, maxlen, &len) < 0) + err_no_cleanup(EFAULT, "unterminated string initialisation"); + + printf("%s\n", s); + + return EXIT_SUCCESS; +}/* + + + ( >:3 ) + /| |\ + / \ + + + + + + */ |
