summaryrefslogtreecommitdiff
path: root/util/nvmutil/lib/state.c
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-20 04:02:51 +0000
committerLeah Rowe <leah@libreboot.org>2026-03-22 13:50:44 +0000
commit6838db4647b600bf5b356429f54850bf801e7ba4 (patch)
treecc98541897703d2949af27dc050cad8cba5061a0 /util/nvmutil/lib/state.c
parentf50ffd6bb13c04cb185fb6311f8875582bf18388 (diff)
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>
Diffstat (limited to 'util/nvmutil/lib/state.c')
-rw-r--r--util/nvmutil/lib/state.c155
1 files changed, 81 insertions, 74 deletions
diff --git a/util/nvmutil/lib/state.c b/util/nvmutil/lib/state.c
index 02a3e51c..9869bb14 100644
--- a/util/nvmutil/lib/state.c
+++ b/util/nvmutil/lib/state.c
@@ -23,8 +23,11 @@
#include "../include/common.h"
struct xstate *
-xstatus(int argc, char *argv[])
+xstart(int argc, char *argv[])
{
+ static int first_run = 1;
+ static int pre_init = 0;
+
static struct xstate us = {
/* DO NOT MESS THIS UP, OR THERE WILL BE DEMONS */
{
@@ -86,92 +89,52 @@ xstatus(int argc, char *argv[])
};
- static int first_run = 1;
-
- if (!first_run)
- return &us;
+ struct xstate *x = &us;
- us.f.buf = us.f.real_buf;
+ if (!first_run) {
+ if (pre_init)
+ err_no_cleanup(ECANCELED,
+ "Outside access to state during init");
- first_run = 0;
- us.argv0 = argv[0];
+ first_run = 0;
- if (argc > 1)
- us.f.fname = argv[1];
+ return &us;
+ }
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
+ err_no_cleanup(EINVAL, "xstart: Too few arguments");
+ if (argv == NULL)
+ err_no_cleanup(EINVAL, "xstart: NULL argv");
+
+ first_run = 0;
+ pre_init = 1;
-#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
+ us.argv0 = argv[0];
+ us.f.fname = argv[1];
#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(us.f.tname, "rwc") == -1)
- err(errno, "unveil rwc: %s", us.f.tname);
+ // TODO: new_tmplate (do for above too)
+ us.f.tname = new_tmpfile(&us.f.tmp_fd, 0, NULL); // TODO: NULL BAD!
#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 */
+// TODO: CHECK ACCESSES VIA xstatus()
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.fname);
- }
-
- 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)");
-
- if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
- err(errno, "pledge (kill unveil)");
-#endif
+ if (us.f.tname == NULL)
+ err_no_cleanup(errno, "x->f.tname null");
+ if (*us.f.tname == '\0')
+ err_no_cleanup(errno, "x->f.tname empty");
- open_gbe_file();
+ if (fstat(us.f.tmp_fd, &us.f.tmp_st) < 0)
+ err_no_cleanup(errno, "%s: stat", us.f.tname);
memset(us.f.real_buf, 0, sizeof(us.f.real_buf));
memset(us.f.bufcmp, 0, sizeof(us.f.bufcmp));
@@ -179,16 +142,55 @@ xstatus(int argc, char *argv[])
/* for good measure */
memset(us.f.pad, 0, sizeof(us.f.pad));
- copy_gbe();
- read_checksums();
+ pre_init = 0;
return &us;
}
+struct xstate *
+xstatus(void)
+{
+ struct xstate *x = xstart(0, NULL);
+
+ if (x == NULL)
+ err_no_cleanup(EACCES, "NULL pointer to xstate");
+
+ sanitize_command_list();
+
+ return x;
+}
+
+/* early init functions that
+ should not access state
+ WARNING:
+ does not do cleanup. only
+ call this during pre-init
+ */
+void
+err_no_cleanup(int nvm_errval, const char *msg, ...)
+{
+ va_list args;
+
+ if (errno == 0)
+ errno = nvm_errval;
+ if (!errno)
+ errno = ECANCELED;
+
+ fprintf(stderr, "nvmutil: ");
+
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+
+ fprintf(stderr, ": %s\n", strerror(errno));
+
+ exit(EXIT_FAILURE);
+}
+
void
err(int nvm_errval, const char *msg, ...)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
va_list args;
@@ -214,7 +216,7 @@ err(int nvm_errval, const char *msg, ...)
const char *
getnvmprogname(void)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
const char *p;
static char fallback[] = "nvmutil";
@@ -239,7 +241,7 @@ getnvmprogname(void)
int
exit_cleanup(void)
{
- struct xstate *x = xstatus(0, NULL);
+ struct xstate *x = xstatus();
struct xfile *f;
int close_err;
@@ -252,14 +254,19 @@ exit_cleanup(void)
f = &x->f;
if (f->gbe_fd > -1) {
- if (close_on_eintr(f->gbe_fd) == -1)
+ if (close_on_eintr(f->gbe_fd) == -1) {
+ f->gbe_fd = -1;
close_err = 1;
+ }
f->gbe_fd = -1;
}
if (f->tmp_fd > -1) {
- if (close_on_eintr(f->tmp_fd) == -1)
+ if (close_on_eintr(f->tmp_fd) == -1) {
+ f->tmp_fd = -1;
close_err = 1;
+ }
+ f->tmp_fd = -1;
}
if (f->tname != NULL) {