From: Karel Zak Date: Wed, 27 May 2026 13:15:22 +0000 (+0200) Subject: loopdev: use openat2(RESOLVE_NO_SYMLINKS) for backing file X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=119d23f1e3f55cf10e3c66dab80fc308c9f26456;p=thirdparty%2Futil-linux.git loopdev: use openat2(RESOLVE_NO_SYMLINKS) for backing file 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 --- diff --git a/lib/loopdev.c b/lib/loopdev.c index ab8ffac41..ac0b7c1f6 100644 --- a/lib/loopdev.c +++ b/lib/loopdev.c @@ -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"));