From 2ed8db3adc19dd922e31082634146e159f65af2e Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Wed, 18 Mar 2026 19:30:32 +0000 Subject: util/nvmutil: major cleanup handle init in xstatus() it's now a singleton design also tidied up some other code also removed todo.c. bloat. will do all those anyway. too much change. i just kept touching the code until it looked good Signed-off-by: Leah Rowe --- util/nvmutil/lib/state.c | 192 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 145 insertions(+), 47 deletions(-) (limited to 'util/nvmutil/lib/state.c') diff --git a/util/nvmutil/lib/state.c b/util/nvmutil/lib/state.c index ec420594..f4f83e48 100644 --- a/util/nvmutil/lib/state.c +++ b/util/nvmutil/lib/state.c @@ -5,13 +5,6 @@ * This tool lets you modify Intel GbE NVM (Gigabit Ethernet * Non-Volatile Memory) images, e.g. change the MAC address. * These images configure your Intel Gigabit Ethernet adapter. - * - * This code is designed to be portable, running on as many - * Unix and Unix-like systems as possible (mainly BSD/Linux). - * - * Recommended CFLAGS for Clang/GCC: - * - * -Os -Wall -Wextra -Werror -pedantic -std=c90 */ #ifdef __OpenBSD__ @@ -34,40 +27,16 @@ #include "../include/common.h" /* - * Program state/command table - * Default config stored here, - * and copied to a newly allocated - * buffer in memory, then the pointer - * is passed. The rest of the program - * will manipulate this data. - */ -/* -TODO: -eventually, i will not have this return -a pointer at all. instead, a similar key -mechanism will be used for other access -functions e.g. word/set_word, err(needs -to clean up), and so on. then those -would return values if already initialised, -but would not permit additional init - will -decide exactly how to implement this at a -later state. - -this is part of an ongoing effort to introduce -extreme memory safety into this program. + * Initialise program state, + * load GbE file and verify + * data, ready for operation + * (singleton design) */ struct xstate * -xstatus(void) +xstatus(int argc, char *argv[]) { - static int first_run = 1; - static struct xstate us = { - /* .cmd (update cmd[] in the struct if adding to it) - DO NOT FORGET. or C will init zeroes/NULLs */ - - /* cmd[] members */ - /* DO NOT MESS THIS UP */ - /* items must be set *exactly* */ + /* DO NOT MESS THIS UP, OR THERE WILL BE DEMONS */ { { CMD_DUMP, "dump", cmd_helper_dump, ARGC_3, @@ -122,36 +91,165 @@ xstatus(void) /* .no_cmd (set 0 when a command is found) */ 1, - /* .xsize (size of the stuct will be stored here later) */ - 0, - /* .cat (cat helpers set this) */ -1 }; + static int first_run = 1; + if (!first_run) return &us; + us.f.buf = us.f.real_buf; + first_run = 0; + us.argv0 = argv[0]; + + if (argc > 1) + us.f.fname = argv[1]; + + if (argc < 3) + usage(); + +/* https://man.openbsd.org/pledge.2 + https://man.openbsd.org/unveil.2 */ +#if defined(__OpenBSD__) && defined(OpenBSD) +#if (OpenBSD) >= 604 + if (pledge("stdio flock rpath wpath cpath unveil", NULL) == -1) + err(errno, "pledge plus unveil"); +#elif (OpenBSD) >= 509 + if (pledge("stdio flock rpath wpath cpath", NULL) == -1) + err(errno, "pledge"); +#endif +#endif - us.xsize = sizeof(us); +#ifndef S_ISREG + err(ECANCELED, "Can't determine file types (S_ISREG undefined)"); +#endif - us.f.buf = us.f.real_buf; +#ifndef CHAR_BIT + err(ECANCELED, "Unknown char size"); +#else + if (CHAR_BIT != 8) + err(EINVAL, "Unsupported char size"); +#endif + +#if defined(__OpenBSD__) && defined(OpenBSD) && \ + (OpenBSD) >= 604 + /* can only use local tmp on openbsd, due to unveil */ + us.f.tname = new_tmpfile(&us.f.tmp_fd, 1, NULL); +#else + us.f.tname = new_tmpfile(&us.f.tmp_fd, 0, NULL); +#endif + if (us.f.tname == NULL) + err(errno, "Can't create tmpfile"); + if (*us.f.tname == '\0') + err(errno, "tmp dir is an empty string"); + +#if defined(__OpenBSD__) && defined(OpenBSD) && \ + OpenBSD >= 604 + if (unveil(f->tname, "rwc") == -1) + err(errno, "unveil rwc: %s", f->tname); +#endif + if (fstat(us.f.tmp_fd, &us.f.tmp_st) < 0) + err(errno, "%s: stat", us.f.tname); + + sanitize_command_list(); + + /* parse user command */ + set_cmd(argc, argv); + set_cmd_args(argc, argv); + +#if defined(__OpenBSD__) && defined(OpenBSD) && \ + (OpenBSD) >= 604 + if ((us.cmd[i].flags & O_ACCMODE) == O_RDONLY) { + if (unveil(us.f.fname, "r") == -1) + err(errno, "%s: unveil r", us.f.fname); + } else { + if (unveil(us.f.fname, "rwc") == -1) + err(errno, "%s: unveil rw", us.f.tname); + } + + if (unveil(us.f.tname, "rwc") == -1) + err(errno, "%s: unveil rwc", us.f.tname); + + if (unveil(NULL, NULL) == -1) + err(errno, "unveil block (rw)"); - us.f.gbe_fd = -1; - us.f.tmp_fd = -1; + if (pledge("stdio flock rpath wpath cpath", NULL) == -1) + err(errno, "pledge (kill unveil)"); +#endif + + open_gbe_file(); + + memset(us.f.real_buf, 0, sizeof(us.f.real_buf)); + memset(us.f.bufcmp, 0, sizeof(us.f.bufcmp)); + + /* for good measure */ + memset(us.f.pad, 0, sizeof(us.f.pad)); - us.f.tname = NULL; - us.f.fname = NULL; + copy_gbe(); + read_checksums(); return &us; } +void +err(int nvm_errval, const char *msg, ...) +{ + struct xstate *x = xstatus(0, NULL); + + va_list args; + + if (errno == 0) + errno = nvm_errval; + if (!errno) + errno = ECANCELED; + + (void)exit_cleanup(); + + if (x != NULL) + fprintf(stderr, "%s: ", getnvmprogname()); + + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + + fprintf(stderr, ": %s\n", strerror(errno)); + + exit(EXIT_FAILURE); +} + +const char * +getnvmprogname(void) +{ + struct xstate *x = xstatus(0, NULL); + + const char *p; + static char fallback[] = "nvmutil"; + + char *rval = fallback; + + if (x != NULL) { + if (x->argv0 == NULL || *x->argv0 == '\0') + return ""; + + rval = x->argv0; + } + + p = x_c_strrchr(rval, '/'); + + if (p) + return p + 1; + else + return rval; +} + int exit_cleanup(void) { - struct xstate *x = xstatus(); + struct xstate *x = xstatus(0, NULL); struct xfile *f; int close_err; -- cgit v1.2.1