Buildroot Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Waldemar Brodkorb <wbx@openadk.org>
To: Titouan Christophe <titouan.christophe@mind.be>
Cc: buildroot@buildroot.org,
	Giulio Benetti <giulio.benetti@benettiengineering.com>,
	thomas.perale@mind.be
Subject: Re: [Buildroot] [PATCH for 2025.02.x] package/util-linux: add patch for CVE-2026-27456
Date: Thu, 7 May 2026 15:14:37 +0200	[thread overview]
Message-ID: <afyQPbG8W74rRqfN@waldemar-brodkorb.de> (raw)
In-Reply-To: <20260427101206.1362913-1-titouan.christophe@mind.be>

Hi,

this patch breaks compilation on Debian 13 with following error:

lib/loopdev.c: In function ‘loopcxt_set_backing_file’:
lib/loopdev.c:1273:32: error: implicit declaration of function ‘ul_canonicalize_path’; did you mean ‘canonicalize_path’? [-Wimplicit-function-declaration]
 1273 |                 lc->filename = ul_canonicalize_path(filename);
      |                                ^~~~~~~~~~~~~~~~~~~~
      |                                canonicalize_path
lib/loopdev.c:1273:32: warning: nested extern declaration of ‘ul_canonicalize_path’ [-Wnested-externs]
lib/loopdev.c:1273:30: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
 1273 |                 lc->filename = ul_canonicalize_path(filename);
      |                              ^
make[4]: *** [Makefile:11808: lib/libcommon_la-loopdev.lo] Error 1
make[3]: *** [Makefile:16952: all-recursive] Error 1
make[2]: *** [Makefile:7294: all] Error 2
make[1]: *** [package/pkg-generic.mk:273: /home/wbx/br-2025.02/output/build/host-util-linux-2.40.2/.stamp_built] Error 2
make: *** [Makefile:83: _all] Error 2

best regards
 Waldemar

Titouan Christophe via buildroot wrote,

> Signed-off-by: Titouan Christophe <titouan.christophe@mind.be>
> ---
>  .../0006-add-loopdev-fl-nofollow.patch        | 111 ++++++++++++++++++
>  package/util-linux/util-linux.mk              |   3 +
>  2 files changed, 114 insertions(+)
>  create mode 100644 package/util-linux/0006-add-loopdev-fl-nofollow.patch
> 
> diff --git a/package/util-linux/0006-add-loopdev-fl-nofollow.patch b/package/util-linux/0006-add-loopdev-fl-nofollow.patch
> new file mode 100644
> index 0000000000..21b1e2596c
> --- /dev/null
> +++ b/package/util-linux/0006-add-loopdev-fl-nofollow.patch
> @@ -0,0 +1,111 @@
> +From 5e390467b26a3cf3fecc04e1a0d482dff3162fc4 Mon Sep 17 00:00:00 2001
> +From: Karel Zak <kzak@redhat.com>
> +Date: Thu, 19 Feb 2026 13:59:46 +0100
> +Subject: [PATCH] loopdev: add LOOPDEV_FL_NOFOLLOW to prevent symlink attacks
> +
> +Add a new LOOPDEV_FL_NOFOLLOW flag for loop device context that
> +prevents symlink following in both path canonicalization and file open.
> +
> +When set:
> +- loopcxt_set_backing_file() uses strdup() instead of
> +  ul_canonicalize_path() (which calls realpath() and follows symlinks)
> +- loopcxt_setup_device() adds O_NOFOLLOW to open() flags
> +
> +The flag is set for non-root (restricted) mount operations in
> +libmount's loop device hook. This prevents a TOCTOU race condition
> +where an attacker could replace the backing file (specified in
> +/etc/fstab) with a symlink to an arbitrary root-owned file between
> +path resolution and open().
> +
> +Vulnerable Code Flow:
> +
> +  mount /mnt/point (non-root, SUID)
> +    mount.c: sanitize_paths() on user args (mountpoint only)
> +    mnt_context_mount()
> +      mnt_context_prepare_mount()
> +        mnt_context_apply_fstab()           <-- source path from fstab
> +        hooks run at MNT_STAGE_PREP_SOURCE
> +          hook_loopdev.c: setup_loopdev()
> +            backing_file = fstab source path ("/home/user/disk.img")
> +            loopcxt_set_backing_file()       <-- calls realpath() as ROOT
> +              ul_canonicalize_path()         <-- follows symlinks!
> +            loopcxt_setup_device()
> +              open(lc->filename, O_RDWR|O_CLOEXEC)  <-- no O_NOFOLLOW
> +
> +Two vulnerabilities in the path:
> +
> +1) loopcxt_set_backing_file() calls ul_canonicalize_path() which uses
> +   realpath() -- this follows symlinks as euid=0. If the attacker swaps
> +   the file to a symlink before this call, lc->filename becomes the
> +   resolved target path (e.g., /root/secret.img).
> +
> +2) loopcxt_setup_device() opens lc->filename without O_NOFOLLOW. Even
> +   if canonicalization happened correctly, the file can be swapped to a
> +   symlink between canonicalize and open.
> +
> +Addresses: https://github.com/util-linux/util-linux/security/advisories/GHSA-qq4x-vfq4-9h9g
> +Signed-off-by: Karel Zak <kzak@redhat.com>
> +
> +CVE: CVE-2026-27456
> +Upstream: https://github.com/util-linux/util-linux/commit/5e390467b26a3cf3fecc04e1a0d482dff3162fc4
> +[Titouan: Adapt patch to apply cleanly onto util-linux 2.40]
> +Signed-off-by: Titouan Christophe <titouan.christophe@mind.be>
> +---
> + include/loopdev.h           | 3 ++-
> + lib/loopdev.c               | 7 ++++++-
> + libmount/src/hook_loopdev.c | 3 ++-
> + 3 files changed, 10 insertions(+), 3 deletions(-)
> +
> +diff --git a/include/loopdev.h b/include/loopdev.h
> +index d10bf7f37..0f85dd254 100644
> +--- a/include/loopdev.h
> ++++ b/include/loopdev.h
> +@@ -139,7 +139,8 @@ enum {
> + 	LOOPDEV_FL_NOIOCTL	= (1 << 6),
> + 	LOOPDEV_FL_DEVSUBDIR	= (1 << 7),
> + 	LOOPDEV_FL_CONTROL	= (1 << 8),	/* system with /dev/loop-control */
> +-	LOOPDEV_FL_SIZELIMIT	= (1 << 9)
> ++	LOOPDEV_FL_SIZELIMIT	= (1 << 9),
> ++	LOOPDEV_FL_NOFOLLOW	= (1 << 10)	/* O_NOFOLLOW, don't follow symlinks */
> + };
> + 
> + /*
> +diff --git a/lib/loopdev.c b/lib/loopdev.c
> +index c72fb2c40..3d2274693 100644
> +--- a/lib/loopdev.c
> ++++ b/lib/loopdev.c
> +@@ -1267,7 +1267,10 @@ int loopcxt_set_backing_file(struct loopdev_cxt *lc, const char *filename)
> + 	if (!lc)
> + 		return -EINVAL;
> + 
> +-	lc->filename = canonicalize_path(filename);
> ++	if (lc->flags & LOOPDEV_FL_NOFOLLOW)
> ++		lc->filename = strdup(filename);
> ++	else
> ++		lc->filename = ul_canonicalize_path(filename);
> + 	if (!lc->filename)
> + 		return -errno;
> + 
> +@@ -1408,6 +1411,8 @@ 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))
> +diff --git a/libmount/src/hook_loopdev.c b/libmount/src/hook_loopdev.c
> +index 597b9339a..4df1915a6 100644
> +--- a/libmount/src/hook_loopdev.c
> ++++ b/libmount/src/hook_loopdev.c
> +@@ -272,7 +272,8 @@ static int setup_loopdev(struct libmnt_context *cxt,
> + 	}
> + 
> + 	DBG(LOOP, ul_debugobj(cxt, "not found; create a new loop device"));
> +-	rc = loopcxt_init(&lc, 0);
> ++	rc = loopcxt_init(&lc,
> ++			mnt_context_is_restricted(cxt) ? LOOPDEV_FL_NOFOLLOW : 0);
> + 	if (rc)
> + 		goto done_no_deinit;
> + 	if (mnt_opt_has_value(loopopt)) {
> diff --git a/package/util-linux/util-linux.mk b/package/util-linux/util-linux.mk
> index 5d761e01c9..d30c26deb5 100644
> --- a/package/util-linux/util-linux.mk
> +++ b/package/util-linux/util-linux.mk
> @@ -36,6 +36,9 @@ UTIL_LINUX_CPE_ID_VENDOR = kernel
>  # 0001-libmount-ifdef-statx-call.patch
>  UTIL_LINUX_AUTORECONF = YES
>  
> +# 0006-add-loopdev-fl-nofollow.patch
> +UTIL_LINUX_IGNORE_CVES += CVE-2026-27456
> +
>  UTIL_LINUX_INSTALL_STAGING = YES
>  UTIL_LINUX_DEPENDENCIES = \
>  	host-pkgconf \
> -- 
> 2.53.0
> 
> _______________________________________________
> buildroot mailing list
> buildroot@buildroot.org
> https://lists.buildroot.org/mailman/listinfo/buildroot
> 
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

      parent reply	other threads:[~2026-05-07 13:14 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-27 10:12 [Buildroot] [PATCH for 2025.02.x] package/util-linux: add patch for CVE-2026-27456 Titouan Christophe via buildroot
2026-05-04 14:47 ` Thomas Perale via buildroot
2026-05-07 13:14 ` Waldemar Brodkorb [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=afyQPbG8W74rRqfN@waldemar-brodkorb.de \
    --to=wbx@openadk.org \
    --cc=buildroot@buildroot.org \
    --cc=giulio.benetti@benettiengineering.com \
    --cc=thomas.perale@mind.be \
    --cc=titouan.christophe@mind.be \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox