summaryrefslogtreecommitdiff
path: root/util/libreboot-utils
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-24 17:06:48 +0000
committerLeah Rowe <leah@libreboot.org>2026-03-24 17:18:47 +0000
commite9c5da1a25641e09244d3f52d7bb90983e0e5550 (patch)
tree2561158c2ff784bbde8e0373ef396e1eea3715c5 /util/libreboot-utils
parent56ab5a18fee5257c3c875f2b8597b8379c7b959c (diff)
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>
Diffstat (limited to 'util/libreboot-utils')
-rw-r--r--util/libreboot-utils/include/common.h2
-rw-r--r--util/libreboot-utils/lib/io.c50
-rw-r--r--util/libreboot-utils/lib/mkhtemp.c52
3 files changed, 91 insertions, 13 deletions
diff --git a/util/libreboot-utils/include/common.h b/util/libreboot-utils/include/common.h
index a632b993..e73f46e7 100644
--- a/util/libreboot-utils/include/common.h
+++ b/util/libreboot-utils/include/common.h
@@ -497,6 +497,8 @@ const char *getnvmprogname(void);
/* libc hardening
*/
+int new_tmpfile_at(int dirfd, struct stat *st_dir,
+ int *fd, char **name);
int new_tmpfile(int *fd, char **path);
int new_tmpdir(int *fd, char **path);
int new_tmp_common(int *fd, char **path, int type);
diff --git a/util/libreboot-utils/lib/io.c b/util/libreboot-utils/lib/io.c
index cc38e5c7..0bab9ee5 100644
--- a/util/libreboot-utils/lib/io.c
+++ b/util/libreboot-utils/lib/io.c
@@ -413,7 +413,15 @@ gbe_mv(void)
int tmp_gbe_bin_exists;
char *dest_tmp;
- int dest_fd;
+ int dest_fd = -1;
+
+ char *dir = NULL;
+ char *base = NULL;
+ char *dest_name = NULL;
+
+ int dirfd = -1;
+
+ struct stat st_dir;
/* will be set 0 if it doesn't
*/
@@ -424,6 +432,8 @@ gbe_mv(void)
saved_errno = errno;
+ /* TODO: remove this path-based rename,
+ use fd */
rval = rename(f->tname, f->fname);
if (rval > -1) {
@@ -433,10 +443,12 @@ gbe_mv(void)
tmp_gbe_bin_exists = 0;
- if (fsync_dir(f->fname) < 0) {
+/*
+ if (fsync(dest_fd) < 0) {
f->io_err_gbe_bin = 1;
rval = -1;
}
+*/
goto ret_gbe_mv;
}
@@ -445,22 +457,28 @@ gbe_mv(void)
goto ret_gbe_mv;
/*
- * OR, cross-filesystem rename:
+ * cross-filesystem: copy into target dir tmp
*/
- if ((rval = f->tmp_fd = open(f->tname,
- O_RDONLY | O_BINARY)) == -1)
+ if (fs_dirname_basename(f->fname,
+ &dir, &base, 0) < 0)
goto ret_gbe_mv;
- /* create replacement temp in target directory
- */
- if (new_tmpfile(&dest_fd, &f->fname) < 1)
+ dirfd = fs_open(dir,
+ O_RDONLY | O_DIRECTORY);
+
+ if (dirfd < 0)
goto ret_gbe_mv;
- if (dest_tmp == NULL)
+
+ if (fstat(dirfd, &st_dir) < 0)
goto ret_gbe_mv;
- /* copy data
- */
+ if (new_tmpfile_at(dirfd, &st_dir,
+ &dest_fd, &dest_name) < 0)
+ goto ret_gbe_mv;
+
+ /* copy: tmp to local tmp */
+
rval = rw_file_exact(f->tmp_fd, f->bufcmp,
f->gbe_file_size, 0, IO_PREAD,
NO_LOOP_EAGAIN, LOOP_EINTR,
@@ -486,7 +504,10 @@ gbe_mv(void)
}
dest_fd = -1;
- if (rename(dest_tmp, f->fname) == -1)
+ /* atomic replace */
+
+ if (fs_rename_at(dirfd, dest_name,
+ dirfd, base) == -1)
goto ret_gbe_mv;
if (fsync_dir(f->fname) < 0) {
@@ -494,7 +515,10 @@ gbe_mv(void)
goto ret_gbe_mv;
}
- free_if_null(&dest_tmp);
+ free_if_null(&dest_name);
+ free_if_null(&dir);
+
+ tmp_gbe_bin_exists = 0;
ret_gbe_mv:
diff --git a/util/libreboot-utils/lib/mkhtemp.c b/util/libreboot-utils/lib/mkhtemp.c
index b30f6587..d1ebea25 100644
--- a/util/libreboot-utils/lib/mkhtemp.c
+++ b/util/libreboot-utils/lib/mkhtemp.c
@@ -39,6 +39,58 @@ new_tmpdir(int *fd, char **path)
return new_tmp_common(fd, path, MKHTEMP_DIR);
}
+/* not used by mkhtemp util, but by nvmutil.
+ * it leaves an st variable set after return,
+ * so that verification can be done on a file
+ * being used, before writing it elsewhere
+ */
+int
+new_tmpfile_at(int dirfd, struct stat *st_dir,
+ int *fd, char **name)
+{
+ struct stat st;
+ char suffix[] = "tmp.XXXXXXXXXX";
+ size_t len;
+ char *buf = NULL;
+ char *fname;
+ int saved_errno = errno;
+
+#if defined(PATH_LEN) && \
+ (PATH_LEN) >= 256
+ size_t maxlen = PATH_LEN;
+#else
+ size_t maxlen = 4096;
+#endif
+
+ if (if_err(fd == NULL || name == NULL || st_dir == NULL, EFAULT) ||
+ if_err(*fd >= 0, EEXIST) ||
+ if_err(dirfd < 0, EBADF) ||
+ if_err_sys(slen(suffix, maxlen, &len) < 0) ||
+ if_err_sys((malloc(len + 1)) == NULL))
+ return -1;
+
+ memcpy(buf, suffix, len + 1);
+ fname = buf;
+
+ *fd = mkhtemp(fd, &st,
+ buf, dirfd, fname,
+ st_dir, MKHTEMP_FILE);
+
+ if (*fd < 0)
+ goto err;
+
+ *name = buf;
+ errno = saved_errno;
+
+ return 0;
+
+err:
+ free_if_null(&buf);
+ close_no_err(fd);
+
+ return -1;
+}
+
/* WARNING:
* on error, *path (at **path) may be
NULL, or if the error pertains to