3931 Commits

Author SHA1 Message Date
Leah Rowe
2723a9ccd8 util/nvmutil: guard against running twice
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-18 00:16:01 +00:00
Leah Rowe
6def381e3c nvmutil: make commands check themselves
check yourself before you execute yourself

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-18 00:09:55 +00:00
Leah Rowe
ec96cb46fc util/nvmutil: check file flags properly
masking O_ACCMODE tells you which flag it is

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 22:26:17 +00:00
Leah Rowe
6fe909f9f7 util/nvmutil: tighter pledge and unveil
call it sooner. set new_state afterward.

i had to uncouple nv from some functions
for this, and i also added some extra
checks especially at exit, about whether
to touch nv (whether it is initialised)

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 22:21:16 +00:00
Leah Rowe
9573d872f3 util/nvmutil: stricter work buf check
check it right after initialisation

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 21:43:37 +00:00
Leah Rowe
d01aedd289 79-character rule must be obeyed
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 21:40:25 +00:00
Leah Rowe
3fba6f2d64 util/nvmutil: fix comment
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 21:24:04 +00:00
Leah Rowe
16d50d42da util/nvmutil: default to clang on make-hell
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 21:00:43 +00:00
Leah Rowe
dcdbd5eda1 util/nvmutil: tidy up memcmp
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 20:35:10 +00:00
Leah Rowe
952a3d52a5 nvmutil: add suffixes to makefile
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 19:39:27 +00:00
Leah Rowe
63f0fe9702 nvmutil: tidy up the makefile
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 19:35:50 +00:00
Leah Rowe
fd1bafecd1 util/nvmutil: portable default make rules
older compilers might not have -std for example.

the code is portable, but old compilers can't
compile with just "make", you have to add lots
of flags

i will now use "make strict" and "make hell"
in testing, but otherwise make without flags
are fine.

move the current strictness to command:

make strict

added an extra command:

make hell

hell uses -Weverything, and is useful with
clang's strict testing, on which i only got
a very small number of errors (it's way less
than a lot of programs would get with this
flag, because -Weverything is REALLY STRICT):

ja, mich nvmutil$ make hell CC=clang
clang -I.   -Wall -Wextra -pedantic -std=c90 -Os -Werror -Weverything nvmutil.c -o nvmutil
In file included from nvmutil.c:35:
./nvmutil.h:225:16: error: padding struct 'struct commands' with 1 byte to align 'rw_size' [-Werror,-Wpadded]
  225 |         unsigned long rw_size; /* within the 4KB GbE part */
      |                       ^
./nvmutil.h:217:8: error: padding size of 'struct commands' with 4 bytes to alignment boundary [-Werror,-Wpadded]
  217 | struct commands {
      |        ^
./nvmutil.h:235:8: error: padding size of 'struct xfile' with 4 bytes to alignment boundary [-Werror,-Wpadded]
  235 | struct xfile {
      |        ^
./nvmutil.h:288:16: error: padding struct 'struct xstate' with 4 bytes to align 'xsize' [-Werror,-Wpadded]
  288 |         unsigned long xsize;
      |                       ^
nvmutil.c:617:43: error: implicit conversion changes signedness: 'off_t' (aka 'long') to 'unsigned long' [-Werror,-Wsign-conversion]
  617 |         _r = rw_file_exact(f->gbe_fd, f->buf, f->gbe_file_size,
      |              ~~~~~~~~~~~~~                    ~~~^~~~~~~~~~~~~
nvmutil.c:626:43: error: implicit conversion changes signedness: 'off_t' (aka 'long') to 'unsigned long' [-Werror,-Wsign-conversion]
  626 |         _r = rw_file_exact(f->tmp_fd, f->buf, f->gbe_file_size,
      |              ~~~~~~~~~~~~~                    ~~~^~~~~~~~~~~~~
nvmutil.c:654:46: error: implicit conversion changes signedness: 'off_t' (aka 'long') to 'unsigned long' [-Werror,-Wsign-conversion]
  654 |         _r = rw_file_exact(f->tmp_fd, f->bufcmp, f->gbe_file_size,
      |              ~~~~~~~~~~~~~                       ~~~^~~~~~~~~~~~~
nvmutil.c:661:39: error: implicit conversion changes signedness: 'off_t' (aka 'long') to 'unsigned long' [-Werror,-Wsign-conversion]
  661 |         if (x_i_memcmp(f->buf, f->bufcmp, f->gbe_file_size) != 0)
      |             ~~~~~~~~~~                    ~~~^~~~~~~~~~~~~
nvmutil.c:702:23: error: implicit conversion loses integer precision: 'int' to 'unsigned char' [-Werror,-Wimplicit-int-conversion]
  702 |                 f->part_valid[_p] = good_checksum(_p);
      |                                   ~ ^~~~~~~~~~~~~~~~~
nvmutil.c:1045:21: error: implicit conversion loses integer precision: 'int' to 'unsigned char' [-Werror,-Wimplicit-int-conversion]
 1045 |         f->part_valid[0] = good_checksum(0);
      |                          ~ ^~~~~~~~~~~~~~~~
nvmutil.c:1046:21: error: implicit conversion loses integer precision: 'int' to 'unsigned char' [-Werror,-Wimplicit-int-conversion]
 1046 |         f->part_valid[1] = good_checksum(1);
      |                          ~ ^~~~~~~~~~~~~~~~
nvmutil.c:1170:45: error: implicit conversion changes signedness: 'off_t' (aka 'long') to 'unsigned long' [-Werror,-Wsign-conversion]
 1170 |                     (unsigned long)(p * (f->gbe_file_size >> 1)));
      |                                       ~  ~~~~~~~~~~~~~~~~~^~~~
nvmutil.c:1269:37: error: implicit conversion loses integer precision: 'int' to 'unsigned short' [-Werror,-Wimplicit-int-conversion]
 1269 |         return (unsigned short)f->buf[pos] |
      |         ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
 1270 |             ((unsigned short)f->buf[pos + 1] << 8);
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nvmutil.c:1610:9: error: implicit conversion changes signedness: 'off_t' (aka 'long') to 'unsigned long' [-Werror,-Wsign-conversion]
 1609 |         r = rw_file_exact(f->tmp_fd, f->bufcmp,
      |             ~~~~~~~~~~~~~
 1610 |             f->gbe_file_size, 0, IO_PREAD,
      |             ~~~^~~~~~~~~~~~~
nvmutil.c:1618:9: error: implicit conversion changes signedness: 'off_t' (aka 'long') to 'unsigned long' [-Werror,-Wsign-conversion]
 1617 |         r = rw_file_exact(dest_fd, f->bufcmp,
      |             ~~~~~~~~~~~~~
 1618 |             f->gbe_file_size, 0, IO_PWRITE,
      |             ~~~^~~~~~~~~~~~~
nvmutil.c:1609:6: error: implicit conversion loses integer precision: 'long' to 'int' [-Werror,-Wshorten-64-to-32]
 1609 |         r = rw_file_exact(f->tmp_fd, f->bufcmp,
      |           ~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1610 |             f->gbe_file_size, 0, IO_PREAD,
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1611 |             NO_LOOP_EAGAIN, LOOP_EINTR,
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1612 |             MAX_ZERO_RW_RETRY, OFF_ERR);
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~
nvmutil.c:1617:6: error: implicit conversion loses integer precision: 'long' to 'int' [-Werror,-Wshorten-64-to-32]
 1617 |         r = rw_file_exact(dest_fd, f->bufcmp,
      |           ~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1618 |             f->gbe_file_size, 0, IO_PWRITE,
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1619 |             NO_LOOP_EAGAIN, LOOP_EINTR,
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1620 |             MAX_ZERO_RW_RETRY, OFF_ERR);
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~
nvmutil.c:1936:45: error: implicit conversion changes signedness: 'long' to 'unsigned long' [-Werror,-Wsign-conversion]
 1936 |                 if (rv >= 0 && (unsigned long)rv > (nrw - rc))
      |                                                         ~ ^~
nvmutil.c:2193:27: error: signed shift result (0x8000000000000000) sets the sign bit of the shift expression's type ('long') and becomes negative [-Werror,-Wshift-sign-overflow]
 2193 |         if (nrw > (unsigned long)X_LONG_MAX)
      |                                  ^~~~~~~~~~
./nvmutil.h:147:38: note: expanded from macro 'X_LONG_MAX'
  147 | #define X_LONG_MAX ((long)(~((long)1 << (sizeof(long)*CHAR_BIT-1))))
      |                              ~~~~~~~ ^  ~~~~~~~~~~~~~~~~~~~~~~~~~
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make: *** [Makefile:42: hell] Fehler 1

in a future commit, i intend to fix all of these issues,
so that the code reliably compiles in hell-mode.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 19:08:49 +00:00
Leah Rowe
5ab3b11446 util/nvmutil: move asserts to header
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 18:30:07 +00:00
Leah Rowe
2cb1797acc nvmutil: extremely defensive CHAR_BIT test
this program needs bits to be 8

some obscure systems set it to something else

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 18:28:01 +00:00
Leah Rowe
cb8ac86bd4 util/nvmutil: add defensive buffer check
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 18:19:40 +00:00
Leah Rowe
b00fb6127e util/nvmutil: remove stale comment
and add another

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 18:09:34 +00:00
Leah Rowe
15b8cd7833 util/nvmutil: fix randomness in mkstemp
i need to re-initialise r each time.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 17:36:11 +00:00
Leah Rowe
0db9cc321f util/nvmutil: split up copy_gbe
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 17:29:07 +00:00
Leah Rowe
6e63106dae util/nvmuti: make fsync_dir() generic
yes, this begins the next phase of nvmutil:

remove global status in functions that should be
generic, and make functions that are not generic,
generic. make everything as re-useable in a library
as possible.

most of the program is error control, as it should
be, but much of it is mixed in with functions
that really should just be split up for libraries.

so that is what i'm now beginning.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 16:59:50 +00:00
Leah Rowe
6b1757da57 prototype for new_state() in nvmutil
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 08:09:27 +00:00
Leah Rowe
9a9bcfe070 util/nvmutil: split up nvmutil.c
i still use a global variable, but now only
one, which is a structure containing the
state of the entire program

now i can easily start modifying it to make
functions generic, and then i can start
making parts of it into easy libraries

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 07:49:17 +00:00
Leah Rowe
730c8b47b2 cleanup
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 03:09:27 +00:00
Leah Rowe
1d123b1f50 util/nvmutil: start removing global state
for now still actually global, but i'm gradually
putting variables into a single global stucture
which will then allow me to make everything
local, which would then allow me to start
splitting up the program and modularising it.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-17 03:05:37 +00:00
Leah Rowe
14857555ed nvmutil: stronger entropy_jitter()
run it for a bit longer

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 22:09:26 +00:00
Leah Rowe
db4df52576 util/nvmutil: don't use strcpy
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 22:05:42 +00:00
Leah Rowe
4f581950c2 util/nvmutil: check fd path in try_fdpath
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 22:02:17 +00:00
Leah Rowe
045d85dcc5 util/nvmutil: add bound check to x_try_fdpath
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:53:30 +00:00
Leah Rowe
841fe878f3 another comment
it's a pretty insane hack. i should probably
just use normal fchmod

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:51:01 +00:00
Leah Rowe
ce139ab0ae comment
also improved the macro, making it stricter

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:46:06 +00:00
Leah Rowe
82f38ed87a cleanup (fix potential overflow in mkstemp)
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:17:54 +00:00
Leah Rowe
26a2224d82 fsync_dir: abort if path length is empty
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:15:01 +00:00
Leah Rowe
ed9eae213b nvmutil: prevent theoretical overflow on time()
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:13:13 +00:00
Leah Rowe
ca76a35f93 also O_NOFOLLOW
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:09:05 +00:00
Leah Rowe
a622151965 util/nvmutil: dir fsync with O_DIRECTORY
guards against replacement attacks, on systems
that support this flag

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:07:49 +00:00
Leah Rowe
ea9d108529 util/nvmutil: fix mkstemp randomness
i made the string longer, but forgot
to adjust it. the new random function
is also better

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:06:15 +00:00
Leah Rowe
5d0d74af4c cast
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:01:33 +00:00
Leah Rowe
e33831ef20 util/nvmutil: more reliable fallback crypto
we assume the fallback will be rare, so now we
make the mix static and keep xoring it, on the
theory that the number of failures on urandom
will be random, and tthat the fallback may only
apply once or twice in thousands of calls.

the time jitter is adjusted; rather than judge
the difference between two points close to each
other in time, we judge tthe randomness in
difference of time elapsed. this mitigates fast
CPUs being very fast and introducing rounding
errors, and also improves performonce on much
slower CPUs

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 21:00:07 +00:00
Leah Rowe
46432005ed util/nvmutil: use real rename() syscall
i was being cute earlier, but the rewrite
defeats the purpose of atomic file handling
in nvmutil, by not actually renaming! it was
more like, doing an actual copy, which meant
that corruption is likely during power loss

i've commented the code because i may
use it in a library in the future.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 19:56:53 +00:00
Leah Rowe
4bcb671755 nvmutil: harden against hardlink attacks
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 18:41:03 +00:00
Leah Rowe
04fc4259d8 redundancy
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 18:38:21 +00:00
Leah Rowe
b76166f7e0 util/nvmutil: loop EINTR on fsync
this improves reliability, making it more
likely that data actually gets synced,
since fsync can return -1 with EINTR,
indicating that a re-try should be
attempted.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 18:35:35 +00:00
Leah Rowe
9f9e220ff9 pointer safety
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 18:28:36 +00:00
Leah Rowe
655ce99d74 don't use PATH_MAX
unreliable

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 18:22:29 +00:00
Leah Rowe
ff769306ba macro safety
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 18:19:42 +00:00
Leah Rowe
7da3173ead util/nvmutil: portable S_IFMT
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 18:18:44 +00:00
Leah Rowe
8bd04bc5ad util/nvmutil: remove integer typedefs
better to just use standard names

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 18:14:53 +00:00
Leah Rowe
3c4ad4231f util/nvmutil: remove global statics
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 18:11:30 +00:00
Leah Rowe
31a5ab3e15 util/nvmutil: fix unveil usage
arandom probably isn't available on super old obsd right??????

rather, unveil isn't. on systems that have arandom

yet we should not unveil something that may not
exist on modern systems

just don't unveil arandom, and don't check arandom
if unveil is enabled

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 17:30:03 +00:00
Leah Rowe
a4b2d0218a util/nvmutil: proper /dev/fd search in fchmod
some systems may not even have it

works with /dev/fd (bsd/mac etc)

works with linux (/proc/self/fd)

and falls back on super old systems
that have neither

Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 17:14:20 +00:00
Leah Rowe
8b887eb7b2 util/nvmutil: tidy up makefile options
Signed-off-by: Leah Rowe <leah@libreboot.org>
2026-03-16 16:59:17 +00:00