From ac04a5f50abdbf241d14bce845051051eb80b137 Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Sun, 29 Mar 2026 14:15:34 +0100 Subject: libreboot-utils/lib: loop eintr on [p]read/[p]write i forgot to do this! with this, I/O should be bullet proof now. i already loop this on other I/O commands. Signed-off-by: Leah Rowe --- util/libreboot-utils/include/common.h | 8 +++ util/libreboot-utils/lib/file.c | 117 ++++++++++++++++++++++++++++++++-- util/libreboot-utils/lib/rand.c | 3 +- 3 files changed, 121 insertions(+), 7 deletions(-) (limited to 'util') diff --git a/util/libreboot-utils/include/common.h b/util/libreboot-utils/include/common.h index aa5d043a..0ccc02aa 100644 --- a/util/libreboot-utils/include/common.h +++ b/util/libreboot-utils/include/common.h @@ -482,6 +482,14 @@ ssize_t rw_over_nrw(ssize_t r, size_t nrw); off_t lseek_on_eintr(int fd, off_t off, int whence, int loop_eagain, int loop_eintr); int try_err(int loop_err, int errval); +ssize_t read_on_eintr(int fd, + void *buf, size_t count); +ssize_t write_on_eintr(int fd, + void *buf, size_t count); +ssize_t pread_on_eintr(int fd, + void *buf, size_t count, off_t off); +ssize_t pwrite_on_eintr(int fd, + void *buf, size_t count, off_t off); /* Error handling and cleanup */ diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c index 48eb37ed..f35d9749 100644 --- a/util/libreboot-utils/lib/file.c +++ b/util/libreboot-utils/lib/file.c @@ -323,15 +323,15 @@ try_rw_again: real_pread_pwrite: #endif if (rw_type == IO_WRITE) - r = write(fd, mem, nrw); + r = write_on_eintr(fd, mem, nrw); else if (rw_type == IO_READ) - r = read(fd, mem, nrw); + r = read_on_eintr(fd, mem, nrw); #if defined(REAL_POS_IO) && \ REAL_POS_IO > 0 else if (rw_type == IO_PWRITE) - r = pwrite(fd, mem, nrw, off); + r = pwrite_on_eintr(fd, mem, nrw, off); else if (rw_type == IO_PREAD) - r = pread(fd, mem, nrw, off); + r = pread_on_eintr(fd, mem, nrw, off); #endif if (r == -1 && (errno == try_err(loop_eintr, EINTR) @@ -386,9 +386,9 @@ real_pread_pwrite: } if (rw_type == IO_PREAD) - r = read(fd, mem, nrw); + r = read_on_eintr(fd, mem, nrw); else if (rw_type == IO_PWRITE) - r = write(fd, mem, nrw); + r = write_on_eintr(fd, mem, nrw); if (rw_over_nrw(r, nrw) == -1) break; @@ -955,13 +955,118 @@ retry: return rval; } +ssize_t +read_on_eintr(int fd, + void *buf, size_t count) +{ + int saved_errno = errno; + int rval; + if (if_err(buf == NULL, EFAULT) || + if_err(fd < 0, EBADF) || + if_err(count == 0, EINVAL)) + goto err; +retry: + errno = 0; + if ((rval = read(fd, buf, count)) == -1 && ( + errno == EINTR || + errno == EAGAIN || + errno == EWOULDBLOCK || + errno == ETXTBSY)) + goto retry; + errno = saved_errno; + return rval; +err: + return set_errno(saved_errno, EIO); +} +ssize_t +pread_on_eintr(int fd, + void *buf, size_t count, + off_t off) +{ + int saved_errno = errno; + int rval; + if (if_err(buf == NULL, EFAULT) || + if_err(fd < 0, EBADF) || + if_err(off < 0, EFAULT) || + if_err(count == 0, EINVAL)) + goto err; +retry: + errno = 0; + if ((rval = pread(fd, buf, count, off)) == -1 && ( + errno == EINTR || + errno == EAGAIN || + errno == EWOULDBLOCK || + errno == ETXTBSY)) + goto retry; + errno = saved_errno; + return rval; +err: + return set_errno(saved_errno, EIO); +} + +ssize_t +write_on_eintr(int fd, + void *buf, size_t count) +{ + int saved_errno = errno; + int rval; + if (if_err(buf == NULL, EFAULT) || + if_err(fd < 0, EBADF) || + if_err(count == 0, EINVAL)) + goto err; + +retry: + errno = 0; + + if ((rval = write(fd, buf, count)) == -1 && ( + errno == EINTR || + errno == EAGAIN || + errno == EWOULDBLOCK || + errno == ETXTBSY)) + goto retry; + + errno = saved_errno; + return rval; +err: + return set_errno(saved_errno, EIO); +} + +ssize_t +pwrite_on_eintr(int fd, + void *buf, size_t count, + off_t off) +{ + int saved_errno = errno; + int rval; + + if (if_err(buf == NULL, EFAULT) || + if_err(fd < 0, EBADF) || + if_err(off < 0, EFAULT) || + if_err(count == 0, EINVAL)) + goto err; + +retry: + errno = 0; + + if ((rval = pwrite(fd, buf, count, off)) == -1 && ( + errno == EINTR || + errno == EAGAIN || + errno == EWOULDBLOCK || + errno == ETXTBSY)) + goto retry; + + errno = saved_errno; + return rval; +err: + return set_errno(saved_errno, EIO); +} diff --git a/util/libreboot-utils/lib/rand.c b/util/libreboot-utils/lib/rand.c index 2aa0de3a..9da8d9eb 100644 --- a/util/libreboot-utils/lib/rand.c +++ b/util/libreboot-utils/lib/rand.c @@ -150,7 +150,8 @@ rset(void *buf, size_t n) int fd = -1; open_on_eintr("/dev/urandom", &fd, O_RDONLY, 0400, NULL); retry_rand: - if ((rc = read(fd, (unsigned char *)buf + off, n - off)) < 0) { + if ((rc = read_on_eintr(fd, + (unsigned char *)buf + off, n - off)) < 0) { #elif defined(__linux__) retry_rand: if ((rc = (ssize_t)syscall(SYS_getrandom, -- cgit v1.2.1