From: Karel Zak Date: Mon, 15 Jun 2026 09:36:10 +0000 (+0200) Subject: mkswap: use fd-based operations to avoid TOCTOU in open_device() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b1ae0fc48d1e9f0604cbc30d4871fdd362d84c02;p=thirdparty%2Futil-linux.git mkswap: use fd-based operations to avoid TOCTOU in open_device() 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 --- diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c index b740e6216..d220d8f8c 100644 --- a/disk-utils/mkswap.c +++ b/disk-utils/mkswap.c @@ -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);