summaryrefslogtreecommitdiff
path: root/util/nvmutil
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-13 14:29:37 +0000
committerLeah Rowe <leah@libreboot.org>2026-03-13 14:32:54 +0000
commit087c7a6ad2e49f25c1dfddc7e2cf5bd23f4c8f95 (patch)
treede20b1698938299fd13ad2cd14b5cba44ca8ef8f /util/nvmutil
parente2f55af07f5078e43a376dd6c650c481f5d7baff (diff)
util/nvmutil: block O_APPEND in prw()
O_APPEND allows writes at EOF, thus breaking positional read/write Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/nvmutil')
-rw-r--r--util/nvmutil/nvmutil.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c
index b6a43908..b659f254 100644
--- a/util/nvmutil/nvmutil.c
+++ b/util/nvmutil/nvmutil.c
@@ -1557,17 +1557,6 @@ gbe_x_offset(size_t p, const char *f_op, const char *d_type,
* be used on sockets or pipes, because 0-byte
* reads are treated like fatal errors. This
* means that EOF is also considered fatal.
- *
- * WARNING: Do not use O_APPEND on open() when
- * using this function. If you do, POSIX allows
- * write() to ignore the current file offset and
- * write at EOF, which means that our use of
- * lseek in prw() does not guarantee writing at
- * a specified offset. So if using IO_PWRITE or
- * IO_PREAD, make sure not to pass a file descriptor
- * with the O_APPEND flag. Alternatively, modify
- * do_rw() to directly use pwrite() and pread()
- * instead of prw().
*/
static ssize_t
rw_file_exact(int fd, uint8_t *mem, size_t len,
@@ -1666,6 +1655,7 @@ prw(int fd, void *mem, size_t nrw,
ssize_t r;
int saved_errno;
int prw_type;
+ int flags;
prw_type = rw_type ^ IO_PREAD;
@@ -1673,6 +1663,18 @@ prw(int fd, void *mem, size_t nrw,
|| (unsigned int)prw_type > IO_WRITE)
goto err_prw;
+ /*
+ * O_APPEND must not be used, because this
+ * allows POSIX write() to ignore the
+ * current write offset and write at EOF,
+ * which would therefore break pread/pwrite
+ */
+ flags = fcntl(fd, F_GETFL);
+ if (flags == -1)
+ return -1;
+ if (flags & O_APPEND)
+ goto err_prw;
+
if ((off_orig = lseek_eintr(fd, (off_t)0, SEEK_CUR)) == (off_t)-1)
return -1;
if (lseek_eintr(fd, off, SEEK_SET) == (off_t)-1)