]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
loopdev: use openat2(RESOLVE_NO_SYMLINKS) for backing file
authorKarel Zak <kzak@redhat.com>
Wed, 27 May 2026 13:15:22 +0000 (15:15 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 28 May 2026 08:27:00 +0000 (10:27 +0200)
Use ul_open_no_symlinks() instead of open(O_NOFOLLOW) when
LOOPDEV_FL_NOFOLLOW is set.  O_NOFOLLOW only rejects symlinks at the
last path component, but TOCTOU attacks swap intermediate components.
openat2(RESOLVE_NO_SYMLINKS) rejects symlinks at any component.

Signed-off-by: Karel Zak <kzak@redhat.com>
lib/loopdev.c

index ab8ffac41945ca946d6ed85c3141425c6fa8108a..ac0b7c1f6369f53b84763499e693ad898fd4d154 100644 (file)
@@ -1398,16 +1398,21 @@ int loopcxt_setup_device(struct loopdev_cxt *lc)
        if (lc->config.info.lo_flags & LO_FLAGS_DIRECT_IO)
                flags |= O_DIRECT;
        if (lc->flags & LOOPDEV_FL_NOFOLLOW)
-               flags |= O_NOFOLLOW;
-
-       if ((file_fd = open(lc->filename, mode | flags)) < 0) {
-               if (mode != O_RDONLY && (errno == EROFS || errno == EACCES))
-                       file_fd = open(lc->filename, (mode = O_RDONLY) | flags);
+               file_fd = ul_open_no_symlinks(lc->filename, mode | flags, 0);
+       else
+               file_fd = open(lc->filename, mode | flags);
 
-               if (file_fd < 0) {
-                       DBG_OBJ(SETUP, lc, ul_debug("open backing file failed: %m"));
-                       return -errno;
-               }
+       if (file_fd < 0 && mode != O_RDONLY
+           && (errno == EROFS || errno == EACCES)) {
+               mode = O_RDONLY;
+               if (lc->flags & LOOPDEV_FL_NOFOLLOW)
+                       file_fd = ul_open_no_symlinks(lc->filename, mode | flags, 0);
+               else
+                       file_fd = open(lc->filename, mode | flags);
+       }
+       if (file_fd < 0) {
+               DBG_OBJ(SETUP, lc, ul_debug("open backing file failed: %m"));
+               return -errno;
        }
        DBG_OBJ(SETUP, lc, ul_debug("backing file open: OK"));