Commit Graph

33 Commits

Author SHA1 Message Date
Leah Rowe c48a962eaf lbutils/file: fix overflow check
clang -Weverything:

lib/file.c:165:49: warning: implicit conversion changes signedness: 'ssize_t' (aka 'long') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
  165 |                 if (if_err(rval >= 0 && (size_t)rval > (nrw - rc), EOVERFLOW))

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-04-01 17:29:28 +01:00
Leah Rowe ae5e74554a lbutils/file: remove unused macro
not needed here (detected with clang -Weverything)

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-04-01 16:49:19 +01:00
Leah Rowe fb81b7b736 lbutils/file: rename rw_file_exact
call it rw_exact, so that it's closer to
the name rw. it matches naming more closely;
the alternative was to call rw rw_file

but read/write can handle more than just files!

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-04-01 16:20:12 +01:00
Leah Rowe f68cedf202 libreboot-utils/file: never retry file rw on zero
even with a timer, it's possible that on a buggy system,
we may keep writing even though the outcome is zero. if
a system comes back with zero bytes written, that is a
fatal bug and we should stop.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-04-01 16:19:46 +01:00
Leah Rowe a879114734 lbutils: remove rw on_eintr functions. just use rw
rw is enough. i unified everything there.

next commit will remove rw_type and instead
run positional i/o depending on whether the
offset is zero. i'm simplifying the API a lot.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-04-01 14:29:39 +01:00
Leah Rowe 44004191cb lbutils: don't set USE_OPENAT and USE_URANDOM
these can be set explicitly in the compiler flags,
e.g.

make CC="cc -DUSE_OPENAT=1 -DUSE_URANDOM=1"

these options, if set to 1, will cause you to use
the code as if it were running on non-linux systems
such as openbsd. of course, some differences will
still exist, but this is useful for portability
testing when compiling on linux.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-04-01 12:30:55 +01:00
Leah Rowe 2c40ad7816 lbutils: only use GNU SOURCE for syscall
and remove manual prototypes; fchmod, realpath
and so on rely on the _XOPEN_SOURCE macro.

the POSIX macro wasn't needed: _XOPEN_SOURCE
is sufficient.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-04-01 11:52:53 +01:00
Leah Rowe 716140b80f libreboot-utils: don't use the GNU SOURCE macro
use the POSIX one

declare prototypes where necessary.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-04-01 11:00:58 +01:00
Leah Rowe 861f56375a libreboot-utils: fix ALL compiler warnings
i wasn't using strict mode enough in make:

make strict

now it compiles cleanly. mostly removing
unused variables, fixing implicit conversions,
etc.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-04-01 10:03:41 +01:00
Leah Rowe f90af15502 safer macro
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-04-01 06:10:57 +01:00
Leah Rowe d2abde5303 libreboot-utils: stricter errno handling
where possible, try not to clobber sys errno. override
it only when relatively safe.

also: when a syscall succeeds, it may set errno. this
is rare, but permitted (nothing specified against it
in specs, and the specs say that errno is undefined
on success).

i'm not libc, but i'm wrapping around it, so i need
to be careful in how i handle the errno value.

also:

i removed the requirement for directories to be
executable, in mkhtemp.c, because this isn't required
and will only break certain setups.

in world_writeable and sticky, i made the checks stricter:
the faccessat check was being skipped on some paths, so
i've closed that loophole now.

i also generally cleaned up some code, as part of the errno
handling refactoring, where it made sense to do so, plus a
few other bits of code cleanup.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-31 17:49:23 +01:00
Leah Rowe 6d9f162f5b lbutils/file: only support real pread/pwrite
the portable version was written for fun, but
it's bloat, and makes the code hard to read.

every unix since about 2005 has these functions.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-31 12:22:42 +01:00
Leah Rowe a769537554 lbutils/file: don't alllow EAGAIN/EWOULDBLOCK
a non-blocking file descriptor could be used while
errno is set to these. this would create an infinite
loop. it's better that we only allow EINTR.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-31 12:06:33 +01:00
Leah Rowe bca09eebf3 lbutils/file: remove ETXTBSY from exemption on io
obsolete. ripe for abuse. do not permit this error.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-31 12:04:37 +01:00
Leah Rowe 277c0c8e87 lbutils/file: don't reset errno on successful io
some io syscalls may set errno on success. this patch
honours that. we try to preserve caller errno, but it
is important for debugging not to clobber it.

if fs_err_retry errs, then we don't reset errno.
if fs_err is successful but errno wasn't set, we
restore caller errno. this is done by setting errno
to zero in callers, which also restore caller errno.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-31 12:03:46 +01:00
Leah Rowe aacf9fb6c9 libreboot-utils: unified EINTR loop handling
absolutely unified.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-31 11:45:21 +01:00
Leah Rowe f2dd830c7b TODO
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-31 07:47:15 +01:00
Leah Rowe 2f7623ff06 libreboot-utils: unified max path lengths
just use PATH_MAX like a normal person

with additional safety

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-31 07:42:40 +01:00
Leah Rowe da20b75bea libreboot-utils: more flexible string usage
i previously used error status and set return values
indirectly. i still do that, but where possible, i
also now return the real value.

this is because these string functions can no longer
return with error status; on error, they all abort.
this forces the program maintainer to keep their code
reliable, and removes the need to check the error status
after using syscalls, because these libc wrappers mitigate
that and make use of libc for you, including errors.

this is part of a general effort to promote safe use
of the C programming language, especially in libreboot!

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-30 06:25:52 +01:00
Leah Rowe ac04a5f50a libreboot-utils/lib: loop eintr on [p]read/[p]write
i forgot to do this!

with this, I/O should be bullet proof now.
i already loop this on other I/O commands.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-29 14:15:34 +01:00
Leah Rowe c2a70b7de0 libreboot-utils: simplify random tmpdir namegen
generalise it in rand.c because this logic will
be useful for other programs in the future.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-29 09:18:36 +01:00
Leah Rowe 93ecd26306 TODO
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-28 09:12:15 +00:00
Leah Rowe 6643d9c1fa lbutils: unify xopen and open_on_eintr
use open_on_eintr for gbe files

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-28 09:03:18 +00:00
Leah Rowe 4ecdadb7a6 libreboot-utils: unified errno handling on returns
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-28 08:32:27 +00:00
Leah Rowe 49cac232d8 libreboot-utils: much stricter open() handling
abort on error, and do EINTR looping

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-28 08:09:14 +00:00
Leah Rowe 03dd3c2894 lbutils/file ffree_and_set_null: err if null
free can take a null, that's fine, but my pointer
to the pointer being freed should not be null. that
is a bug.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-28 07:47:31 +00:00
Leah Rowe 63984a4a6a libreboot-utils: much stricter close() handling
remove close_warn and close_no_err

make close_on_eintr a void, and abort
on error instead of returning -1.

a failed file closure is a world-ending
event. burn accordingly.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-28 07:30:55 +00:00
Leah Rowe 0f1a22174f libreboot-utils: unified error handling
i now use a singleton hook function per program:
nvmutil, mkhtemp and lottery

call this at the startup of your program:

(void) errhook(exit_cleanup);

then provide that function. make it static,
so that each program has its own version.

if you're writing a program that handles lots
of files for example, and you want to do certain
cleanup on exit (including error exit), this can
be quite useful.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-28 06:53:37 +00:00
Leah Rowe 7f39ce5f9b libreboot-utils: extremely safe(ish) malloc usage
yes, a common thing in C programs is one or all
of the following:

* use after frees
* double free (on non-NULL pointer)
* over-writing currently used pointer (mem leak)

i try to reduce the chance of this in my software,
by running free() through a filter function,
free_if_not_null, that returns if a function
is being freed twice - because it sets NULL
after freeing, but will only free if it's not
null already.

this patch adds two functions: smalloc and vmalloc,
for strings and voids. using these makes the program
abort if:

* non-null pointer given for initialisation
* pointer to pointer is null (of course)
* size of zero given, for malloc (zero bytes)

i myself was caught out by this change, prompting
me to make the following fix in fs_dirname_basename()
inside lib/file.c:

-       char *buf;
+       char *buf = NULL;

Yes.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-28 04:25:14 +00:00
Leah Rowe db6e817ded util/libreboot-utils: finish implementing hell
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-27 16:56:40 +00:00
Leah Rowe 5ea7fe22b2 cleanup
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-26 06:59:42 +00:00
Leah Rowe c2c24b7a24 nvmutil: fix lseek call when read pos i/o enabled
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-26 06:59:42 +00:00
Leah Rowe 718095b0fe util/mkhtemp: extremely hardened mkhtemp
This will also be used in lbmk itself at some point,
which currently just uses regular mktemp, for tmpdir
handling during the build process.

Renamed util/nvmutil to util/libreboot-utils, which
now contains two tools. The new tool, mkhtemp, is a
hardened implementation of mktemp, which nvmutil
also uses now. Still experimental, but good enough
for nvmutil.

Mkhtemp attempts to provide TOCTOU resistance on
Linux, by using modern features in Linux such as
Openat2 (syscall) with O_EXCL and O_TMPFILE,
and many various security checks e.g.
inode/dev during creation. Checks are done constantly,
to try to detect race conditions. The code is very
strict about things like sticky bits in world writeable
directories, also ownership (it can be made to bar even
root access on files and directories it doesn't own).

It's a security-first implementation of mktemp, likely
even more secure than the OpenBSD mkstemp, but more
auditing and testing is needed - more features are
also planned, including a compatibility mode to make
it also work like traditional mktemp/mkstemp. The
intention, once this becomes stable, is that it will
become a modern drop-in replacement for mkstemp on
Linux and BSD systems.

Some legacy code has been removed, and in general
cleaned up. I wrote mkhtemp for nvmutil, as part of
its atomic write behaviour, but mktemp was the last
remaining liability, so I rewrote that too!

Docs/manpage/website will be made for mkhtemp once
the code is mature.

Other changes have also been made. This is from another
experimental branch of Libreboot, that I'm pushing
early. For example, nvmutil's state machine has been
tidied up, moving more logic back into main.

Mktemp is historically prone to race conditions,
e.g. symlink attacks, directory replacement, remounting
during operation, all sorts of things. Mkhtemp has
been written to solve, or otherwise mitigate, that
problem. Mkhtemp is currently experimental and will
require a major cleanup at some point, but it
already works well enough, and you can in fact use
it; at this time, the -d, -p and -q flags are
supported, and you can add a custom template at
the end, e.g.

mkhtemp -p test -d

Eventually, I will make this have complete parity
with the GNU and BSD implementations, so that it is
fully useable on existing setups, while optionally
providing the hardening as well.

A lot of code has also been tidied up. I didn't
track the changes I made with this one, because
it was a major re-write of nvmutil; it is now
libreboot-utils, and I will continue to write
more programs in here over time. It's basically
now a bunch of hardened wrappers around various
libc functions, e.g. there is also a secure I/O
wrapper for read/write.

There is a custom randomisation function, rlong,
which simply uses arc4random or getrandom, on
BSD and Linux respectively. Efforts are made to
make it as reliable as possible, to the extent
that it never returns with failure; in the unlikely
event that it fails, it aborts. It also sleeps
between failure, to mitigate certain DoS attacks.

You can just go in util/libreboot-utils and
type make, then you will have the nvmutil and
mkhtemp binaries, which you can just use. It
all works. Everything was massively rewritten.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-26 06:59:42 +00:00