]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
mkswap: use fd-based operations to avoid TOCTOU in open_device()
authorKarel Zak <kzak@redhat.com>
Mon, 15 Jun 2026 09:36:10 +0000 (11:36 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 15 Jun 2026 09:36:10 +0000 (11:36 +0200)
Replace path-based stat()+chmod() with open() first, then fstat()
and fchmod() on the file descriptor. This eliminates the race window
between checking and modifying the file.

Also skip fchmod() when permissions are already 0600.

Signed-off-by: Karel Zak <kzak@redhat.com>
disk-utils/mkswap.c

index b740e62168806d256ed38474eb3a1142fda68d26..d220d8f8ce61248c596afe2e097806cca105d1bc 100644 (file)
@@ -401,13 +401,16 @@ static void open_device(struct mkswap_control *ctl)
        assert(ctl->devname);
 
        if (ctl->file) {
-               if (stat(ctl->devname, &ctl->devstat) == 0) {
+               ctl->fd = open(ctl->devname, O_RDWR | O_CREAT, 0600);
+               if (ctl->fd >= 0) {
+                       if (fstat(ctl->fd, &ctl->devstat) < 0)
+                               err(EXIT_FAILURE, _("stat of %s failed"), ctl->devname);
                        if (!S_ISREG(ctl->devstat.st_mode))
-                               err(EXIT_FAILURE, _("cannot create swap file %s: node isn't regular file"), ctl->devname);
-                       if (chmod(ctl->devname, 0600) < 0)
+                               errx(EXIT_FAILURE, _("cannot create swap file %s: node isn't regular file"), ctl->devname);
+                       if ((ctl->devstat.st_mode & 07777) != 0600
+                           && fchmod(ctl->fd, 0600) < 0)
                                err(EXIT_FAILURE, _("cannot set permissions on swap file %s"), ctl->devname);
                }
-               ctl->fd = open(ctl->devname, O_RDWR | O_CREAT, 0600);
        } else {
                if (stat(ctl->devname, &ctl->devstat) < 0)
                        err(EXIT_FAILURE, _("stat of %s failed"), ctl->devname);