Compare commits

..

63 Commits

Author SHA1 Message Date
Leah Rowe
d5a08963c3 libreboot-utils: add dragonflybsd to arc4random
it supports arc4random since forever

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 12:00:18 +00:00
Leah Rowe
e9cefe81b0 libreboot-utils: usleep 100 on rand failure
it's extremely unlikely that a 2nd call would
also fail. this is fine.

it mitigates DoS attacks (entropy exhaustion)

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 11:37:55 +00:00
Leah Rowe
6db9514c95 libreboot-utils: tidy up the rand code
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 11:28:44 +00:00
Leah Rowe
49cc239884 util/mkhtemp: allow zero as a rand value
yes, zero is a valid response.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 11:13:56 +00:00
Leah Rowe
7bff5712b4 util/libreboot-utils: simplified rand
only use the getrandom syscall on linux,
or arc4random.

the /dev/urandom fallback is removed, and
we use the syscall; failure is almost certainly
unlikely, but if it fails, we abort. this
provides therefore the same guarantee as
bsd arc4random, since it will never return
under fault conditions. it will only ever
return success, or abort.

nobody should be using /dev/urandom in 2026.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 11:08:24 +00:00
Leah Rowe
a6da25ad0b libreboot-utils: remove 1989 rand
added as an academic exercise, but pointless
in the year 2026.

or even the year 1989.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 10:38:37 +00:00
Leah Rowe
f7f1856969 libreboot-utils: move rand to own file
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 10:34:37 +00:00
Leah Rowe
e1ff02f323 util/libreboot-utils: added more string functions
also reset pointer values

because i can

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 07:51:51 +00:00
Leah Rowe
5f93b7faec lib/mkhtemp: fix bad string comparison
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 04:58:23 +00:00
Leah Rowe
7efdc40cab lib/mkhtemp: rename suffix to template
suffix is a gnu term, for its mktemp version.
it goes after the template.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 00:44:13 +00:00
Leah Rowe
1228f7e0e5 util/mkhtemp: require at least 3 X
the GNU one requires 3. we should be compatible
with them. i'm going to work on the compatibility
mode - this is phase one!

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 00:30:39 +00:00
Leah Rowe
f06db344ad mkhtemp: fix err()
calling it indirectly was out of the question.

must call it directly.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-25 00:03:31 +00:00
Leah Rowe
3ddd7a0d36 util/mkhtemp: add -q option (silence errors)
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 23:31:51 +00:00
Leah Rowe
2cee58188c util/nvmutil: make tmp files dotfiles
so that they are hidden. yes.

mkhtemp can take any template now

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 22:44:43 +00:00
Leah Rowe
1ed2ca6b69 util/libreboot-utils: rename err() to b0rk()
it behaves a bit differently than err(), so it's
not good to confuse readers

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 22:44:27 +00:00
Leah Rowe
4fc4946f3c util/nvmutil: fix name size in fs_resolve_at
it's capped at 256 bytes

we need it configurable and in sync with
other limits in the code.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 22:21:22 +00:00
Leah Rowe
f8d9c51a36 util/mkhtemp: template support on util
just add a template like yo uwould on other mktemp.
it works perfectly now.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 22:19:40 +00:00
Leah Rowe
b8a045ef86 util/mkhtemp: allow relative path with -p
but only -p

not inside the library. that way, we retain
security. symlinks resolved with use of -p;
a warning will be added about this to the
manpage, when written.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 21:31:33 +00:00
Leah Rowe
715723c7ce mkhtemp: harden tmpdir access control
faccessat used this way respects uid/gid,
handles ACLs (where used), and matches whatt
many real security tools might do.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 20:18:15 +00:00
Leah Rowe
b16bb6c445 util/mkhtemp: loosen execution restriction
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 20:15:14 +00:00
Leah Rowe
75f03ea696 util/mkhtemp: add directory override (-p) option.
-p dir

to override TMPDIR

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 20:14:47 +00:00
Leah Rowe
88ff5f7380 util/mkhtemp: O_TMPFILE fast path on linux
linux itself provides much of the hardening we need,
and avoids the need for some of our tests. use this
on linux (fall back to openat still, on e.g. bsd)

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 19:57:12 +00:00
Leah Rowe
bf5a3df796 mkhtemp: fix bad comparison
pointers are null, not zero.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 19:57:07 +00:00
Leah Rowe
3522a23587 util/nvmutil: use renameat for atomic write
not rename(). use renameat()

this re-uses the logic added for mkhtemp.

this will later enable more stringent
integrity checks, though we already verify
the integrity of a file after writing it
back, and renameat is always tied to the
descriptor, so it's fine.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 19:19:33 +00:00
Leah Rowe
217ad55bed improve the error message
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 18:56:51 +00:00
Leah Rowe
c1befbcd3e util/nvmutil: never do cross-filesystem moves
make a local TMPDIR instead, where gbe.bin is.
this avoids the EXDEV errno, so we don't have
to handle it, and it's just better performant
for everyone.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 18:46:36 +00:00
Leah Rowe
6593e76c6a TODO: exdev handling still broken on nvmutil
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 17:33:03 +00:00
Leah Rowe
e9c5da1a25 util/nvmutil: use new fs_open functions for gbe
this unifies nvmutil's file handling with the
handling used by mkhtemp. a special function
has been written for this. this allows greater
flexibility since we can more easily check the
integrity of a file at inode/dev level; this
complements nvmutil's existing content-based
verification.

(this also fixes nvmutil, so that gbe files can
be changed again. mkhtemp broke it while i was
writing it, but now everything works again)

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 17:18:47 +00:00
Leah Rowe
56ab5a18fe mkhtemp: show progname on error
i have my own getprogname implementation,
because not every libc is good enough to
include one.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 16:35:40 +00:00
Leah Rowe
9de01208b0 comment
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 09:59:49 +00:00
Leah Rowe
cce396a1ac libreboot-utils: general code cleanup
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 09:48:34 +00:00
Leah Rowe
e7ede0c755 mkhtemp: unified non-error close handling
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 07:06:39 +00:00
Leah Rowe
616099edad util/nvmutil: make it compile again
i was reorganising the state machine (singleton)
used for data, and part of what i wanted lead
to mkhtemp being written.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 04:43:52 +00:00
Leah Rowe
61ee661b88 nvmutil/state: remove unnecessary check
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 04:29:31 +00:00
Leah Rowe
8b8a5635c3 add comment about mkhtemp calling convention
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 03:15:19 +00:00
Leah Rowe
2c21a04741 util/mkhtemp: show path on error accessing it
a bit naughty the way i do it, but it works. without
this, the message gets clobbered by EINVAL due to
a bad call to vprintf in the err function.

in this way, we ensure that there is a path, and
thus the errno does not get clobbered. i also
removed the EPERM setting in the env_tmpdir
function, which also clobbered errno.

with this fix, if TMPDIR is set but invalid,
it should now show the error reliably.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 02:41:53 +00:00
Leah Rowe
a5eed39a76 lib/mkhtemp.c: use standard suffix
it may seem counterintuitive that a shorter suffix is
better, but i think we should ideally look just like
what is made my any other tool, and other mktemp
tools generate:

tmp.XXXXXXXXXX

this is the default, but of course it could be changed.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-24 01:51:59 +00:00
Leah Rowe
f2544d094b 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>
2026-03-24 01:25:53 +00:00
Leah Rowe
afcd535816 mkhtemp: split library into its own file
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 23:31:00 +00:00
Leah Rowe
a9165d2503 mkhtemp: fail if TMPDIR is SET, but set wrong
right now we defer to fallbacks otherwise, which
is wrong.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 10:51:02 +00:00
Leah Rowe
ba80191b78 mkhtemp: PROPER fd leak/overwrite fix
now this code should be stable. no leaks.

yes. hardened mkhtemp. oh yeah mate.

now all i need is a main() and a getopt
loop, and pledge, unveil, and blackjack,
and something dubious of a titilating
nature.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 09:14:41 +00:00
Leah Rowe
8261553818 util/nvmutil: remove bad check in world stick func
yeah, of course we don't bloody own /tmp

duh

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 08:57:04 +00:00
Leah Rowe
7c414b2d84 mkhtemp: fix bad close
the fd in fs_resolve_at is subsequently used

note that in practise, this is not a real fix:
the best fix is to cache all descriptors and
free them at the end, once resolution is done.

not a real fix, because now fd leaks,
but it's dealt with on program close.

not a util yet. just just stubbing this in
main to test various features.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 08:48:34 +00:00
Leah Rowe
024862a152 mkhtemp: fix bad check
where the path is quite short and the number of X
is quite big compared to the rest of it, this
check will actually cause a false overflow
error. the maths are correct, just not the error

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 08:31:41 +00:00
Leah Rowe
c1c1aee695 mkhtemp: fix initialisied fd
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 08:21:18 +00:00
Leah Rowe
f18f995c42 WIP remove xdev from openat2p
causes error on cross mount links
e.g. /tmp tmpfs

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 06:42:57 +00:00
Leah Rowe
186d612ac7 WIP: "finished"
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 05:32:34 +00:00
Leah Rowe
1f7d4c72f4 remove dead code WIP
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 04:59:29 +00:00
Leah Rowe
c87e425442 WIP dir support (also demons)
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-23 04:43:47 +00:00
Leah Rowe
1684f475cd WIP identity check unification
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 23:43:03 +00:00
Leah Rowe
cf4be895f9 WIP verify after lock
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 23:28:40 +00:00
Leah Rowe
79376a900a WIP cleanup
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 23:27:09 +00:00
Leah Rowe
ca92e7831a cleanup WIP
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 21:54:04 +00:00
Leah Rowe
cc7b0a4381 WIP cleanup: split mkhtemp
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 20:38:01 +00:00
Leah Rowe
df99f345dc WIP cleanup
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 20:06:10 +00:00
Leah Rowe
a505cb261a WIP: remove local mode in mkhtemp + cleanup
bloat

unveil can get pledged

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 20:01:11 +00:00
Leah Rowe
b8ababa2be WIP: split out rand fill on mkhtemp
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 19:27:37 +00:00
Leah Rowe
535ab29deb WIP: file system sandboxing
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 19:13:43 +00:00
Leah Rowe
5818ec11bf openat2 WIP
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 17:47:05 +00:00
Leah Rowe
c766c819b3 WIP: fs_resolve_at
yes. mkhtemp is ccoming along nicely

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 16:50:01 +00:00
Leah Rowe
7694b307b8 WIP: always use openat
why would i write a secure mktemp to be used
on linux from 1999?????

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 16:32:52 +00:00
Leah Rowe
825d520575 WIP: pathless resolution
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 15:45:57 +00:00
Leah Rowe
6838db4647 WIP: hardened mktemp
i'm pretty much nearly there. still no dir support,
only files.

i won't keep amending now - will do more, then
squash later.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-22 13:50:44 +00:00
5 changed files with 91 additions and 62 deletions

View File

@@ -384,7 +384,7 @@ int dcat(const char *s, size_t n,
*/
unsigned short hextonum(char ch_s);
void rset(void *buf, size_t n);
size_t rlong(void);
/* Helper functions for command: dump
*/

View File

@@ -634,8 +634,15 @@ mkhtemp(int *fd,
st_dir_initial, fname_copy,
p, xc, fd, st, type);
if (r == 0)
if (r == 0) {
if (retries >= MKHTEMP_SPIN_THRESHOLD) {
/* usleep can return EINTR */
close_errno = errno;
usleep((useconds_t)rlong() & 0x3FF);
errno = close_errno;
}
continue;
}
if (r < 0)
goto err;
@@ -879,32 +886,37 @@ err:
int
mkhtemp_fill_random(char *p, size_t xc)
{
static const char ch[] =
static char ch[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
unsigned char scratch[64];
size_t chx = 0;
size_t r;
size_t off = 0;
size_t i;
/* clamp rand to prevent modulo bias */
size_t limit = 256 - (256 % (sizeof(ch) - 1));
/* clamp rand to prevent modulo bias
*/
size_t limit = ((size_t)-1) - (((size_t)-1) % (sizeof(ch) - 1));
int saved_errno = errno;
if (if_err(p == NULL, EFAULT))
return -1;
retry_rand:
rset(scratch, sizeof(scratch));
for (chx = 0; chx < xc; chx++) {
for (i = 0; i < sizeof(scratch) && off < xc; i++) {
if (scratch[i] < limit)
p[off++] = ch[scratch[i] % (sizeof(ch) - 1)];
retry_rand:
/* on bsd: uses arc4random
on linux: uses getrandom
*never returns error*
*/
r = rlong(); /* always returns successful */
if (r >= limit)
goto retry_rand;
p[chx] = ch[r % (sizeof(ch) - 1)];
}
if (off < xc)
goto retry_rand;
errno = saved_errno;
return 0;
}
/* WARNING: **ONCE** per file.

View File

@@ -84,7 +84,7 @@ hextonum(char ch_s)
if (ch == '?' || ch == 'x') {
rset(&rval, sizeof(rval));
rval = rlong();
if (errno > 0)
goto err_hextonum;

View File

@@ -12,80 +12,103 @@
#endif
#include <sys/types.h>
#ifndef USE_URANDOM
#define USE_URANDOM 0
#endif
#include <errno.h>
#if defined(USE_URANDOM) && \
((USE_URANDOM) > 0)
#if !((defined(__OpenBSD__) && (OpenBSD) >= 201) || \
defined(__FreeBSD__) || \
defined(__NetBSD__) || defined(__APPLE__))
#include <fcntl.h> /* if not arc4random: /dev/urandom */
#endif
#include <fcntl.h>
#include <limits.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "../include/common.h"
void
rset(void *buf, size_t n)
/* Random numbers
*/
/* when calling this: save errno
* first, then set errno to zero.
* on error, this function will
* set errno and possibly return
*
* rlong also preserves errno
* and leaves it unchanged on
* success, so if you do it
* right, you can detect error.
* this is because it uses
* /dev/urandom which can err.
* ditto getrandom (EINTR),
* theoretically.
*/
/* for the linux version: we use only the
* syscall, because we cannot trust /dev/urandom
* to be as robust, and some libc implementations
* may default to /dev/urandom under fault conditions.
*
* for general high reliability, we must abort on
* failure. in practise, it will likely never fail.
* the arc4random call on bsd never returns error.
*/
size_t
rlong(void)
{
size_t rval;
int saved_errno = errno;
errno = 0;
#if (defined(__OpenBSD__) || defined(__FreeBSD__) || \
defined(__NetBSD__) || defined(__APPLE__) || \
defined(__DragonFly__)) && !(defined(USE_URANDOM) && \
((USE_URANDOM) > 0))
defined(__DragonFly__))
arc4random_buf(buf, n);
arc4random_buf(&rval, sizeof(size_t));
goto out;
#else
size_t off = 0;
ssize_t rc = 0;
#if defined(USE_URANDOM) && \
((USE_URANDOM) > 0)
int fd = -1;
if ((fd = open("/dev/urandom", O_RDONLY)) < 0)
goto err;
retry_rand:
if ((rc = read(fd, buf + off, n - off)) < 0) {
#elif defined(__linux__)
size_t off = 0;
size_t len = sizeof(rval);
ssize_t rc;
retry_rand:
if ((rc = (ssize_t)syscall(SYS_getrandom,
buf + off, n - off, 0)) < 0) {
#else
#error Unsupported operating system (possibly unsecure randomisation)
#endif
if (errno == EINTR ||
errno == EAGAIN)
rc = (ssize_t)syscall(SYS_getrandom,
(char *)&rval + off, len - off, 0);
if (rc < 0) {
if (errno == EINTR || errno == EAGAIN) {
usleep(100);
goto retry_rand;
}
goto err; /* possibly unsupported by kernel */
}
if ((off += (size_t)rc) < n)
if ((off += (size_t)rc) < len)
goto retry_rand;
#if defined(USE_URANDOM) && \
((USE_URANDOM) > 0)
close_no_err(&fd);
#endif
goto out;
err:
/*
* getrandom can return with error, butt arc4random
* doesn't. generally, getrandom will be reliably,
* but we of course have to maintain parity with
* BSD. So a rand failure is to be interpreted as
* a major systems failure, and we act accordingly.
*/
err_no_cleanup(1, ECANCELED,
"Randomisation failure, possibly unsupported in your kernel.");
exit(EXIT_FAILURE);
#else
#error Unsupported operating system (possibly unsecure randomisation)
#endif
out:
errno = saved_errno;
return rval;
}
#endif

View File

@@ -44,14 +44,8 @@ main(int argc, char *argv[])
#if (OpenBSD) >= 604
if (pledge("stdio flock rpath wpath cpath unveil", NULL) == -1)
err_no_cleanup(0, errno, "pledge plus unveil, main");
#if defined(USE_URANDOM) && \
((USE_URANDOM) > 0)
if (unveil("/dev/null", "r") == -1)
err_no_cleanup(0, errno, "unveil r: /dev/null");
#else
if (unveil("/dev/urandom", "r") == -1)
err_no_cleanup(0, errno, "unveil r: /dev/urandom");
#endif
#elif (OpenBSD) >= 509
if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
err_no_cleanup(0, errno, "pledge, main");