From 087c7a6ad2e49f25c1dfddc7e2cf5bd23f4c8f95 Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Fri, 13 Mar 2026 14:29:37 +0000 Subject: util/nvmutil: block O_APPEND in prw() O_APPEND allows writes at EOF, thus breaking positional read/write Signed-off-by: Leah Rowe --- util/nvmutil/nvmutil.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'util') 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) -- cgit v1.2.1