mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-07-16 03:25:25 +02:00
util/nvmutil: make EINTR configurable in prw()
Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
+44
-25
@@ -330,15 +330,16 @@ static off_t gbe_x_offset(size_t part, const char *f_op,
|
|||||||
static ssize_t rw_gbe_file_exact(int fd, u8 *mem, size_t nrw,
|
static ssize_t rw_gbe_file_exact(int fd, u8 *mem, size_t nrw,
|
||||||
off_t off, int rw_type);
|
off_t off, int rw_type);
|
||||||
static ssize_t rw_file_exact(int fd, u8 *mem, size_t len,
|
static ssize_t rw_file_exact(int fd, u8 *mem, size_t len,
|
||||||
off_t off, int rw_type, int loop_eagain);
|
off_t off, int rw_type, int loop_eagain, int loop_eintr);
|
||||||
static ssize_t rw_file_once(int fd, u8 *mem, size_t len,
|
static ssize_t rw_file_once(int fd, u8 *mem, size_t len,
|
||||||
off_t off, int rw_type, size_t rc, int loop_eagain);
|
off_t off, int rw_type, size_t rc, int loop_eagain,
|
||||||
|
int loop_eintr);
|
||||||
static ssize_t prw(int fd, void *mem, size_t nrw,
|
static ssize_t prw(int fd, void *mem, size_t nrw,
|
||||||
off_t off, int rw_type, int loop_eagain);
|
off_t off, int rw_type, int loop_eagain, int loop_eintr);
|
||||||
static int rw_over_nrw(ssize_t r, size_t nrw);
|
static int rw_over_nrw(ssize_t r, size_t nrw);
|
||||||
static off_t lseek_eintr(int fd, off_t off,
|
static off_t lseek_eintr(int fd, off_t off,
|
||||||
int whence, int loop_eagain);
|
int whence, int loop_eagain, int loop_eintr);
|
||||||
static int err_eagain(int loop_eagain);
|
static int err_eagain(int loop_err, int errval);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Error handling and cleanup
|
* Error handling and cleanup
|
||||||
@@ -1153,7 +1154,7 @@ rhex(void)
|
|||||||
|
|
||||||
if (!n) {
|
if (!n) {
|
||||||
n = sizeof(rnum);
|
n = sizeof(rnum);
|
||||||
if (rw_file_exact(urandom_fd, rnum, n, 0, IO_READ, 0) == -1)
|
if (rw_file_exact(urandom_fd, rnum, n, 0, IO_READ, 0, 1) == -1)
|
||||||
err(errno, "Randomisation failed");
|
err(errno, "Randomisation failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1322,7 +1323,7 @@ static void
|
|||||||
gbe_cat_buf(u8 *b)
|
gbe_cat_buf(u8 *b)
|
||||||
{
|
{
|
||||||
if (rw_file_exact(STDOUT_FILENO, b,
|
if (rw_file_exact(STDOUT_FILENO, b,
|
||||||
GBE_PART_SIZE, 0, IO_WRITE, 1) < 0)
|
GBE_PART_SIZE, 0, IO_WRITE, 1, 1) < 0)
|
||||||
err(errno, "stdout: cat");
|
err(errno, "stdout: cat");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1576,7 +1577,7 @@ rw_gbe_file_exact(int fd, u8 *mem, size_t nrw,
|
|||||||
if (nrw > GBE_PART_SIZE)
|
if (nrw > GBE_PART_SIZE)
|
||||||
goto err_rw_gbe_file_exact;
|
goto err_rw_gbe_file_exact;
|
||||||
|
|
||||||
return rw_file_exact(fd, mem, nrw, off, rw_type, 0);
|
return rw_file_exact(fd, mem, nrw, off, rw_type, 0, 1);
|
||||||
|
|
||||||
err_rw_gbe_file_exact:
|
err_rw_gbe_file_exact:
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
@@ -1602,14 +1603,15 @@ err_rw_gbe_file_exact:
|
|||||||
*/
|
*/
|
||||||
static ssize_t
|
static ssize_t
|
||||||
rw_file_exact(int fd, u8 *mem, size_t nrw,
|
rw_file_exact(int fd, u8 *mem, size_t nrw,
|
||||||
off_t off, int rw_type, int loop_eagain)
|
off_t off, int rw_type, int loop_eagain,
|
||||||
|
int loop_eintr)
|
||||||
{
|
{
|
||||||
ssize_t rv;
|
ssize_t rv;
|
||||||
size_t rc;
|
size_t rc;
|
||||||
|
|
||||||
for (rc = 0, rv = 0; rc < nrw; ) {
|
for (rc = 0, rv = 0; rc < nrw; ) {
|
||||||
if ((rv = rw_file_once(fd, mem, nrw, off, rw_type, rc,
|
if ((rv = rw_file_once(fd, mem, nrw, off, rw_type, rc,
|
||||||
loop_eagain)) <= 0)
|
loop_eagain, loop_eintr)) <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
rc += (size_t)rv;
|
rc += (size_t)rv;
|
||||||
@@ -1629,7 +1631,7 @@ rw_file_exact(int fd, u8 *mem, size_t nrw,
|
|||||||
static ssize_t
|
static ssize_t
|
||||||
rw_file_once(int fd, u8 *mem, size_t nrw,
|
rw_file_once(int fd, u8 *mem, size_t nrw,
|
||||||
off_t off, int rw_type, size_t rc,
|
off_t off, int rw_type, size_t rc,
|
||||||
int loop_eagain)
|
int loop_eagain, int loop_eintr)
|
||||||
{
|
{
|
||||||
ssize_t rv;
|
ssize_t rv;
|
||||||
size_t retries_on_zero = 0;
|
size_t retries_on_zero = 0;
|
||||||
@@ -1639,7 +1641,8 @@ rw_file_once(int fd, u8 *mem, size_t nrw,
|
|||||||
goto err_rw_file_once;
|
goto err_rw_file_once;
|
||||||
|
|
||||||
read_again:
|
read_again:
|
||||||
rv = prw(fd, mem + rc, nrw - rc, off + rc, rw_type, loop_eagain);
|
rv = prw(fd, mem + rc, nrw - rc, off + rc, rw_type,
|
||||||
|
loop_eagain, loop_eintr);
|
||||||
|
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1672,10 +1675,21 @@ err_rw_file_once:
|
|||||||
* A fallback is provided for regular read/write.
|
* A fallback is provided for regular read/write.
|
||||||
* rw_type can be IO_READ, IO_WRITE, IO_PREAD
|
* rw_type can be IO_READ, IO_WRITE, IO_PREAD
|
||||||
* or IO_PWRITE
|
* or IO_PWRITE
|
||||||
|
*
|
||||||
|
* loop_eagain does a retry loop on EAGAIN if set
|
||||||
|
* loop_eintr does a retry loop on EINTR if set
|
||||||
|
*
|
||||||
|
* Unlike the bare syscalls, prw() does security
|
||||||
|
* checks e.g. checks NULL strings, checks bounds,
|
||||||
|
* also mitigates a few theoretical libc bugs.
|
||||||
|
* It is designed for extremely safe single-threaded
|
||||||
|
* I/O on applications that need it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
prw(int fd, void *mem, size_t nrw,
|
prw(int fd, void *mem, size_t nrw,
|
||||||
off_t off, int rw_type, int loop_eagain)
|
off_t off, int rw_type,
|
||||||
|
int loop_eagain, int loop_eintr)
|
||||||
{
|
{
|
||||||
off_t off_orig;
|
off_t off_orig;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
@@ -1708,8 +1722,8 @@ try_rw_again:
|
|||||||
else if (rw_type == IO_READ)
|
else if (rw_type == IO_READ)
|
||||||
r = read(fd, mem, nrw);
|
r = read(fd, mem, nrw);
|
||||||
|
|
||||||
if (r == -1 && (errno == EINTR
|
if (r == -1 && (errno == err_eagain(loop_eintr, EINTR)
|
||||||
|| errno == err_eagain(loop_eagain)))
|
|| errno == err_eagain(loop_eagain, EAGAIN)))
|
||||||
goto try_rw_again;
|
goto try_rw_again;
|
||||||
|
|
||||||
return rw_over_nrw(r, nrw);
|
return rw_over_nrw(r, nrw);
|
||||||
@@ -1729,9 +1743,10 @@ try_rw_again:
|
|||||||
goto err_prw;
|
goto err_prw;
|
||||||
|
|
||||||
if ((off_orig = lseek_eintr(fd, (off_t)0, SEEK_CUR,
|
if ((off_orig = lseek_eintr(fd, (off_t)0, SEEK_CUR,
|
||||||
loop_eagain)) == (off_t)-1)
|
loop_eagain, loop_eintr)) == (off_t)-1)
|
||||||
r = -1;
|
r = -1;
|
||||||
else if (lseek_eintr(fd, off, SEEK_SET, loop_eagain) == (off_t)-1)
|
else if (lseek_eintr(fd, off, SEEK_SET,
|
||||||
|
loop_eagain, loop_eintr) == (off_t)-1)
|
||||||
r = -1;
|
r = -1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -1741,12 +1756,13 @@ try_rw_again:
|
|||||||
r = write(fd, mem, nrw);
|
r = write(fd, mem, nrw);
|
||||||
|
|
||||||
r = rw_over_nrw(r, nrw);
|
r = rw_over_nrw(r, nrw);
|
||||||
} while (r == -1 && (errno == EINTR
|
} while (r == -1 &&
|
||||||
|| errno == err_eagain(loop_eagain)));
|
(errno == err_eagain(loop_eintr, EINTR)
|
||||||
|
|| errno == err_eagain(loop_eagain, EAGAIN)));
|
||||||
|
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
if (lseek_eintr(fd, off_orig, SEEK_SET,
|
if (lseek_eintr(fd, off_orig, SEEK_SET,
|
||||||
loop_eagain) == (off_t)-1) {
|
loop_eagain, loop_eintr) == (off_t)-1) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1803,23 +1819,26 @@ err_rw_over_nrw:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static off_t
|
static off_t
|
||||||
lseek_eintr(int fd, off_t off, int whence, int loop_eagain)
|
lseek_eintr(int fd, off_t off, int whence,
|
||||||
|
int loop_eagain, int loop_eintr)
|
||||||
{
|
{
|
||||||
off_t old;
|
off_t old;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
old = lseek(fd, off, whence);
|
old = lseek(fd, off, whence);
|
||||||
} while (old == (off_t)-1
|
} while (old == (off_t)-1
|
||||||
&& (!(errno == EINTR || errno == err_eagain(loop_eagain))));
|
&& (!(
|
||||||
|
errno == err_eagain(loop_eintr, EINTR) ||
|
||||||
|
errno == err_eagain(loop_eagain, EAGAIN))));
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
err_eagain(int loop_eagain)
|
err_eagain(int loop_err, int errval)
|
||||||
{
|
{
|
||||||
if (loop_eagain)
|
if (loop_err)
|
||||||
return EAGAIN;
|
return errval;
|
||||||
|
|
||||||
/* errno is never negative,
|
/* errno is never negative,
|
||||||
so functions checking it
|
so functions checking it
|
||||||
|
|||||||
Reference in New Issue
Block a user