diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-15 00:49:57 +0000 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-15 00:53:16 +0000 |
| commit | be2f4ce6cd3767c9211335f990e9048d9c7ba4d7 (patch) | |
| tree | 5e0b2f2e48be7cc70abd4f57169a681454ec2ee2 | |
| parent | d5c363d20607134538a0a12a9f0c88135c50b372 (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>
| -rw-r--r-- | util/nvmutil/nvmutil.c | 39 |
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); |
