]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udevadm: lock: fix TOCTOU
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 5 Apr 2022 16:17:23 +0000 (01:17 +0900)
committerLuca Boccassi <luca.boccassi@gmail.com>
Wed, 6 Apr 2022 07:58:23 +0000 (08:58 +0100)
Fixes CID#1487744.

src/udev/udevadm-lock.c

index 3e5d7b356f2072532e6a94ec1690fd7dc0dbe137..951711f1203d0bcee4a2a368ae0667bfcd38759b 100644 (file)
@@ -144,6 +144,7 @@ static int find_devno(
                 const char *device,
                 bool backing) {
 
+        _cleanup_close_ int fd = -1;
         dev_t devt, whole_devt;
         struct stat st;
         int r;
@@ -153,7 +154,11 @@ static int find_devno(
         assert(*devnos || *n_devnos == 0);
         assert(device);
 
-        if (stat(device, &st) < 0)
+        fd = open(device, O_CLOEXEC|O_PATH);
+        if (fd < 0)
+                return log_error_errno(errno, "Failed to open '%s': %m", device);
+
+        if (fstat(fd, &st) < 0)
                 return log_error_errno(errno, "Failed to stat '%s': %m", device);
 
         if (S_ISBLK(st.st_mode))
@@ -166,20 +171,13 @@ static int find_devno(
                 devt = st.st_dev;
         else {
                 _cleanup_close_ int regfd = -1;
-                struct stat st2;
 
                 /* If major(st.st_dev) is zero, this might mean we are backed by btrfs, which needs special
                  * handing, to get the backing device node. */
 
-                regfd = open(device, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
+                regfd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
                 if (regfd < 0)
-                        return log_error_errno(errno, "Failed to open '%s': %m", device);
-
-                /* Extra safety: let's check we are still looking at the same file */
-                if (fstat(regfd, &st2) < 0)
-                        return log_error_errno(errno, "Failed to stat '%s': %m", device);
-                if (!stat_inode_same(&st, &st2))
-                        return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "File '%s' was replaced while we were looking at it.", device);
+                        return log_error_errno(regfd, "Failed to open '%s': %m", device);
 
                 r = btrfs_get_block_device_fd(regfd, &devt);
                 if (r == -ENOTTY)