summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-15 00:49:57 +0000
committerLeah Rowe <leah@libreboot.org>2026-03-15 00:53:16 +0000
commitbe2f4ce6cd3767c9211335f990e9048d9c7ba4d7 (patch)
tree5e0b2f2e48be7cc70abd4f57169a681454ec2ee2 /util
parentd5c363d20607134538a0a12a9f0c88135c50b372 (diff)
util/nvmutil: extra race-condition check in prw
even with OFF_RESET, we still want some error checking. if the check fails again immediately after, then it suggests that another program really is modifying the file, so we should stop. the first check is done on the theory that another program *was* working on it, but now isn't. once again, this isn't perfect. use read pread/pwrite if you need thread safety (and even then, you still need to actually check your code) Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util')
-rw-r--r--util/nvmutil/nvmutil.c39
1 files changed, 20 insertions, 19 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c
index 59d2facd..120586a9 100644
--- a/util/nvmutil/nvmutil.c
+++ b/util/nvmutil/nvmutil.c
@@ -2073,25 +2073,8 @@ real_pread_pwrite:
* if the offset changed to what
* we previously got. If it did,
* then another thread may have
- * changed it.
- *
- * This is no substitute for real
- * pread/pwrite, which would be
- * fully atomic at kernel-level
- * and do not use file offsets.
- *
- * TODO: Add a toggle to make it
- * recover instead, reset
- * to known offset, and
- * carry on operations.
- *
- * Failure is the better option
- * here, since recovery would
- * mask hidden bugs in code.
- * We cannot guarantee thread
- * safety, except in the event
- * that violations cause exit;
- * you would then debug it.
+ * changed it. Enabled if
+ * off_reset is OFF_RESET.
*/
if (off != verified) {
if (!off_reset)
@@ -2112,6 +2095,24 @@ real_pread_pwrite:
return -1;
}
+ verified = lseek_loop(fd, (off_t)0, SEEK_CUR,
+ loop_eagain, loop_eintr);
+
+ /*
+ * Verify again before I/O
+ * (even with OFF_ERR)
+ *
+ * This implements the first check
+ * even with OFF_ERR, but without
+ * the recovery. On ERR_RESET, if
+ * the check fails again, then we
+ * know something else is touching
+ * the file, so it's best that we
+ * probably leave it alone and err.
+ */
+ if (verified != off)
+ goto err_prw;
+
do {
if (rw_type == IO_PREAD)
r = read(fd, mem, nrw);