On 03/11/2026 05:08, Collin Funk wrote:
It would also be good to add a test for other races, but I still need
to think of the best way to do it. Perhaps for the rename one, a long
file name could maybe reproduce it consistently, since it calls
renameatu N times where N is the length of the file name.

The chmod one can probably only be done with a breakpoint or something
like that.

I was thinking about using strace to send a SIGSTOP for something similar 
recently,
so it's probably worth adding such a test for reference at least.
I've attached a test that fails without the fix and passes with it.

diff --git a/src/shred.c b/src/shred.c

+  ok = (do_wipefd (fd, qname, s, flags)
+        && (! flags->remove_file || wipename (dirfd, name, qname, flags)));
- if (close (fd) != 0)
+ done:
+  if (0 <= fd && close (fd) < 0)
      {
        error (0, errno, _("%s: failed to close"), qname);
        ok = false;
      }
-  if (ok && flags->remove_file)
-    ok = wipename (name, qname, flags);
+  if (dirfd != AT_FDCWD)
+    close (dirfd);
    return ok;
  }
That unlinks the file even if close() returned EIO.
I think it would be better to reorder to keep the file around in that case,
at least as a witness to the failing overwrite operation.

cheers,
Padraig

Attachment: chmod-race.sh
Description: application/shellscript

Reply via email to