diff mbox series

[wrynose,v2] util-linux: upgrade 2.41.3 -> 2.41.5

Message ID 20260723062240.2516398-1-sivakumar.bs@gmail.com
State New
Delegated to: Yoann Congal
Headers show
Series [wrynose,v2] util-linux: upgrade 2.41.3 -> 2.41.5 | expand

Commit Message

Siva Kumar Balasubramanian July 23, 2026, 6:22 a.m. UTC
2.41.4 and 2.41.5 are point releases in the same 2.41 stable series and
contain only bug fixes and security fixes (no new features, no API/ABI
breaks), so the upgrade complies with the stable branch policy.

Among the fixes pulled in:
 - Several mount(8) TOCTOU / symlink hardening fixes (incl. CVE-2026-27456)
 - libblkid integer overflow in parse_dos_extended() and a use-after-free
   in partition probing
 - pam_lastlog2: fix libpam linking in the autotools build so
   pam_lastlog2.so links against libpam, fixing the runtime "undefined
   symbol: pam_syslog" / dlopen failure [YOCTO #16320]

Drop the loopdev symlink-attack backport that is now part of the release:
 - 0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch
   (upstream f55f9906, released in 2.41.4)

Full changes: https://github.com/util-linux/util-linux/compare/v2.41.3...v2.41.5

Signed-off-by: Siva Balasubramanian <sivakumar.bs@gmail.com>
---
v2: Correct the commit message. wrynose only carried the loopdev backport,
    not a pam_lastlog2 backport, so only one backport is dropped. The
    pam_lastlog2 libpam linking fix comes in natively with 2.41.5. (Paul
    Barker)

 ...2.41.3.bb => util-linux-libuuid_2.41.5.bb} |   0
 meta/recipes-core/util-linux/util-linux.inc   |   3 +-
 ...DEV_FL_NOFOLLOW-to-prevent-symlink-a.patch | 114 ------------------
 ...l-linux_2.41.3.bb => util-linux_2.41.5.bb} |   0
 4 files changed, 1 insertion(+), 116 deletions(-)
 rename meta/recipes-core/util-linux/{util-linux-libuuid_2.41.3.bb => util-linux-libuuid_2.41.5.bb} (100%)
 delete mode 100644 meta/recipes-core/util-linux/util-linux/0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch
 rename meta/recipes-core/util-linux/{util-linux_2.41.3.bb => util-linux_2.41.5.bb} (100%)

Comments

Siva Kumar Balasubramanian July 23, 2026, 6:26 a.m. UTC | #1
Hi Paul,

You're right, thanks for catching that. wrynose only carried the loopdev
backport; the pam_lastlog2 fix was never backported there, it just comes
in natively with 2.41.5. I've sent a v2 that corrects the commit message
to drop only the loopdev backport and describes the pam_lastlog2 fix as
one of the fixes pulled in by the upgrade. The diff is unchanged.

Regards,
Siva

On Thu, Jul 23, 2026 at 11:52 AM Siva Balasubramanian <
sivakumar.bs@gmail.com> wrote:

> 2.41.4 and 2.41.5 are point releases in the same 2.41 stable series and
> contain only bug fixes and security fixes (no new features, no API/ABI
> breaks), so the upgrade complies with the stable branch policy.
>
> Among the fixes pulled in:
>  - Several mount(8) TOCTOU / symlink hardening fixes (incl. CVE-2026-27456)
>  - libblkid integer overflow in parse_dos_extended() and a use-after-free
>    in partition probing
>  - pam_lastlog2: fix libpam linking in the autotools build so
>    pam_lastlog2.so links against libpam, fixing the runtime "undefined
>    symbol: pam_syslog" / dlopen failure [YOCTO #16320]
>
> Drop the loopdev symlink-attack backport that is now part of the release:
>  - 0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch
>    (upstream f55f9906, released in 2.41.4)
>
> Full changes:
> https://github.com/util-linux/util-linux/compare/v2.41.3...v2.41.5
>
> Signed-off-by: Siva Balasubramanian <sivakumar.bs@gmail.com>
> ---
> v2: Correct the commit message. wrynose only carried the loopdev backport,
>     not a pam_lastlog2 backport, so only one backport is dropped. The
>     pam_lastlog2 libpam linking fix comes in natively with 2.41.5. (Paul
>     Barker)
>
>  ...2.41.3.bb => util-linux-libuuid_2.41.5.bb} |   0
>  meta/recipes-core/util-linux/util-linux.inc   |   3 +-
>  ...DEV_FL_NOFOLLOW-to-prevent-symlink-a.patch | 114 ------------------
>  ...l-linux_2.41.3.bb => util-linux_2.41.5.bb} |   0
>  4 files changed, 1 insertion(+), 116 deletions(-)
>  rename meta/recipes-core/util-linux/{util-linux-libuuid_2.41.3.bb =>
> util-linux-libuuid_2.41.5.bb} (100%)
>  delete mode 100644
> meta/recipes-core/util-linux/util-linux/0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch
>  rename meta/recipes-core/util-linux/{util-linux_2.41.3.bb =>
> util-linux_2.41.5.bb} (100%)
>
> diff --git a/meta/recipes-core/util-linux/util-linux-libuuid_2.41.3.bb
> b/meta/recipes-core/util-linux/util-linux-libuuid_2.41.5.bb
> similarity index 100%
> rename from meta/recipes-core/util-linux/util-linux-libuuid_2.41.3.bb
> rename to meta/recipes-core/util-linux/util-linux-libuuid_2.41.5.bb
> diff --git a/meta/recipes-core/util-linux/util-linux.inc
> b/meta/recipes-core/util-linux/util-linux.inc
> index 0235862666..aec8721ca3 100644
> --- a/meta/recipes-core/util-linux/util-linux.inc
> +++ b/meta/recipes-core/util-linux/util-linux.inc
> @@ -20,9 +20,8 @@ SRC_URI =
> "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin
>
> file://0001-lsfd-mkfds-foreign-sockets-skip-when-lacking-sock_di.patch \
>
> file://0001-ts-kill-decode-use-RTMIN-from-kill-L-instead-of-hard.patch \
>             file://0001-tests-script-Disable-size-option-test.patch \
> -
>  file://0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch \
>             "
>
> -SRC_URI[sha256sum] =
> "3330d873f0fceb5560b89a7dc14e4f3288bbd880e96903ed9b50ec2b5799e58b"
> +SRC_URI[sha256sum] =
> "f586e35d320ff537aab3ffeca37e9ecd482ccbe013590db4429a414d8aa6a728"
>
>  CVE_PRODUCT = "util-linux"
> diff --git
> a/meta/recipes-core/util-linux/util-linux/0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch
> b/meta/recipes-core/util-linux/util-linux/0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch
> deleted file mode 100644
> index 0951c9f5fb..0000000000
> ---
> a/meta/recipes-core/util-linux/util-linux/0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch
> +++ /dev/null
> @@ -1,114 +0,0 @@
> -From f55f9906b4f6eeb2b4a4120317df9de935253c10 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>
> -(cherry picked from commit 5e390467b26a3cf3fecc04e1a0d482dff3162fc4)
> -
> -CVE: CVE-2026-27456
> -Upstream-Status: Backport
> -Signed-off-by: Ross Burton <ross.burton@arm.com>
> ----
> - 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 e5ec1c98a..6bdb1393a 100644
> ---- a/include/loopdev.h
> -+++ b/include/loopdev.h
> -@@ -140,7 +140,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 2359bf781..76685be70 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 = 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 444d69d6f..34351116c 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)) {
> ---
> -2.43.0
> -
> diff --git a/meta/recipes-core/util-linux/util-linux_2.41.3.bb
> b/meta/recipes-core/util-linux/util-linux_2.41.5.bb
> similarity index 100%
> rename from meta/recipes-core/util-linux/util-linux_2.41.3.bb
> rename to meta/recipes-core/util-linux/util-linux_2.41.5.bb
> --
> 2.34.1
>
>
diff mbox series

Patch

diff --git a/meta/recipes-core/util-linux/util-linux-libuuid_2.41.3.bb b/meta/recipes-core/util-linux/util-linux-libuuid_2.41.5.bb
similarity index 100%
rename from meta/recipes-core/util-linux/util-linux-libuuid_2.41.3.bb
rename to meta/recipes-core/util-linux/util-linux-libuuid_2.41.5.bb
diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc
index 0235862666..aec8721ca3 100644
--- a/meta/recipes-core/util-linux/util-linux.inc
+++ b/meta/recipes-core/util-linux/util-linux.inc
@@ -20,9 +20,8 @@  SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin
            file://0001-lsfd-mkfds-foreign-sockets-skip-when-lacking-sock_di.patch \
            file://0001-ts-kill-decode-use-RTMIN-from-kill-L-instead-of-hard.patch \
            file://0001-tests-script-Disable-size-option-test.patch \
-           file://0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch \
            "
 
-SRC_URI[sha256sum] = "3330d873f0fceb5560b89a7dc14e4f3288bbd880e96903ed9b50ec2b5799e58b"
+SRC_URI[sha256sum] = "f586e35d320ff537aab3ffeca37e9ecd482ccbe013590db4429a414d8aa6a728"
 
 CVE_PRODUCT = "util-linux"
diff --git a/meta/recipes-core/util-linux/util-linux/0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch b/meta/recipes-core/util-linux/util-linux/0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch
deleted file mode 100644
index 0951c9f5fb..0000000000
--- a/meta/recipes-core/util-linux/util-linux/0001-loopdev-add-LOOPDEV_FL_NOFOLLOW-to-prevent-symlink-a.patch
+++ /dev/null
@@ -1,114 +0,0 @@ 
-From f55f9906b4f6eeb2b4a4120317df9de935253c10 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>
-(cherry picked from commit 5e390467b26a3cf3fecc04e1a0d482dff3162fc4)
-
-CVE: CVE-2026-27456
-Upstream-Status: Backport
-Signed-off-by: Ross Burton <ross.burton@arm.com>
----
- 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 e5ec1c98a..6bdb1393a 100644
---- a/include/loopdev.h
-+++ b/include/loopdev.h
-@@ -140,7 +140,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 2359bf781..76685be70 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 = 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 444d69d6f..34351116c 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)) {
--- 
-2.43.0
-
diff --git a/meta/recipes-core/util-linux/util-linux_2.41.3.bb b/meta/recipes-core/util-linux/util-linux_2.41.5.bb
similarity index 100%
rename from meta/recipes-core/util-linux/util-linux_2.41.3.bb
rename to meta/recipes-core/util-linux/util-linux_2.41.5.bb