summaryrefslogtreecommitdiff
path: root/util/nvmutil
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-14 17:57:13 +0000
committerLeah Rowe <leah@libreboot.org>2026-03-14 17:57:13 +0000
commitea210177fd0858e710901ec302d2ab8caf14c361 (patch)
tree4cb7429854f2f09ae78e6336c93700278780c69e /util/nvmutil
parent01fd54bc1151be9df0bb9019512bf09cc98be89e (diff)
util/nvmutil: more aggressive file checking
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/nvmutil')
-rw-r--r--util/nvmutil/nvmutil.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c
index 2d602038..c05487cf 100644
--- a/util/nvmutil/nvmutil.c
+++ b/util/nvmutil/nvmutil.c
@@ -390,6 +390,7 @@ static ssize_t rw_file_once(int fd, u8 *mem, size_t len,
int loop_eintr, size_t max_retries);
static ssize_t prw(int fd, void *mem, size_t nrw,
off_t off, int rw_type, int loop_eagain, int loop_eintr);
+static int check_file(int fd, struct stat *st);
static int rw_over_nrw(ssize_t r, size_t nrw);
static off_t lseek_loop(int fd, off_t off,
int whence, int loop_eagain, int loop_eintr);
@@ -1831,21 +1832,9 @@ rw_file_exact(int fd, u8 *mem, size_t nrw,
off_t off, int rw_type, int loop_eagain,
int loop_eintr, size_t max_retries)
{
- struct stat st;
ssize_t rv;
size_t rc;
- /* Programs like cat can use this,
- so we only check if it's a normal
- file if not looping EAGAIN */
- if (!loop_eagain) {
- if (fstat(fd, &st) == -1)
- goto err_rw_file_exact;
-
- if (S_ISREG(st.st_mode))
- goto err_rw_file_exact;
- }
-
for (rc = 0, rv = 0; rc < nrw; ) {
if ((rv = rw_file_once(fd, mem, nrw, off, rw_type, rc,
loop_eagain, loop_eintr, max_retries)) < 0)
@@ -1960,6 +1949,7 @@ prw(int fd, void *mem, size_t nrw,
ssize_t r;
int saved_errno;
int positional_rw;
+ struct stat st;
if (mem == NULL)
goto err_prw;
@@ -1973,6 +1963,20 @@ prw(int fd, void *mem, size_t nrw,
r = -1;
+ /* Programs like cat can use this,
+ so we only check if it's a normal
+ file if not looping EAGAIN */
+ if (!loop_eagain) {
+ /*
+ * Checking on every run of prw()
+ * is expensive if called many
+ * times, but is defensive in
+ * case the status changes.
+ */
+ if (check_file(fd, &st) == -1)
+ return -1;
+ }
+
if (rw_type >= IO_PREAD)
positional_rw = 1; /* pread/pwrite */
else
@@ -2045,6 +2049,22 @@ err_prw:
return -1;
}
+static int
+check_file(int fd, struct stat *st)
+{
+ if (fstat(fd, st) == -1)
+ goto err_is_file;
+
+ if (S_ISREG(st->st_mode))
+ goto err_is_file;
+
+ return 0;
+
+err_is_file:
+ errno = EIO;
+ return -1;
+}
+
/*
* Check overflows caused by buggy libc.
*