From patchwork Mon Oct 5 17:05:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Marko X-Patchwork-Id: 100008 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B540DCA5FF0 for ; Mon, 5 Oct 2026 17:05:36 +0000 (UTC) Received: from mta-64-225.siemens.flowmailer.net (mta-64-225.siemens.flowmailer.net [185.136.64.225]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24902.1791219928092385261 for ; Mon, 05 Oct 2026 10:05:29 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: no key for signature: lookup fm1._domainkey.siemens.com on 127.0.0.53:53: no such host" header.i=peter.marko@siemens.com header.s=fm1 header.b=guE270JW; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-256628-2026100517052444bc6e15e9000207eb-cpygi3@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 2026100517052444bc6e15e9000207eb for ; Mon, 05 Oct 2026 19:05:25 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=peter.marko@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc; bh=RqnvrFDPrP+7l7BdcNkHTiUa0j7OyD+T7B1nvszIrCI=; b=guE270JW0JbSIw4nDGWood7u0E3Bct/gPHTOQJAnUMzpYldJosUTmW3BnRViI6Aqdo/8Zl 1tQ73k/er5jVglfQK1FaqyT5dHrJZmGusk2wzkUNs1TFUHIPhyEWpC1HlsF3wixJ9ZF/xRcV PvHcs84Y0d7YqfA1lJm5GYKu/P0HaYX9iSA9zBw8oq6bvt2VJwYLtpFY5HDuBVoMP+Ksbawh 0FKeUCN4SE10ske4HoWeX6uVLKyJNSi6T6M8krB63OYogkmHy0r5+qB/NdIUb2CadpIWYkhg jjjI+09TNWC0Sypwtt4+Q0WHRbaexiKC0O9hROUtBRYCyp/E/bz226YQ==; From: Peter Marko To: openembedded-core@lists.openembedded.org Cc: Peter Marko Subject: [scarthgap][PATCH 1/7] util-linux: patch CVE-2026-53614 Date: Mon, 5 Oct 2026 19:05:06 +0200 Message-ID: <20261005170513.632348-1-peter.marko@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-256628:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Mon, 05 Oct 2026 17:05:36 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247246 From: Peter Marko Pick patch referencing this CVE from 2.41.5 release. Signed-off-by: Peter Marko --- meta/recipes-core/util-linux/util-linux.inc | 1 + .../util-linux/CVE-2026-53614.patch | 83 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 meta/recipes-core/util-linux/util-linux/CVE-2026-53614.patch diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc index f651dc2dab4..70acf6dfec3 100644 --- a/meta/recipes-core/util-linux/util-linux.inc +++ b/meta/recipes-core/util-linux/util-linux.inc @@ -49,6 +49,7 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin file://CVE-2026-27456.patch \ file://CVE-2026-13595.patch \ file://CVE-2026-3184.patch \ + file://CVE-2026-53614.patch \ " SRC_URI[sha256sum] = "7b6605e48d1a49f43cc4b4cfc59f313d0dd5402fa40b96810bd572e167dfed0f" diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2026-53614.patch b/meta/recipes-core/util-linux/util-linux/CVE-2026-53614.patch new file mode 100644 index 00000000000..f1dd4ae5d74 --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/CVE-2026-53614.patch @@ -0,0 +1,83 @@ +From cc81bbcec598cb91f0eb8456282f33eed820ed5f Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 16 Jun 2026 10:58:32 +0200 +Subject: [PATCH] libmount: fix SUID bypass via LIBMOUNT_FORCE_MOUNT2 and + legacy mount path + +Use safe_getenv() for LIBMOUNT_FORCE_MOUNT2 to ignore the variable +in SUID context, consistent with LIBMOUNT_FSTAB and other sensitive +environment variables. + +Additionally, refuse multi-step mount(2) sequences (bind+remount and +propagation) for restricted (non-root) users in the legacy mount path. +The two-step approach has a window between syscalls where security +flags (nosuid, noexec, ...) are not yet applied. The new mount API +handles this atomically. + +CVE-2026-53614 + +Reported-by: Xinyao Hu +Signed-off-by: Karel Zak +(cherry picked from commit 9cbfb823500f510b34767edabd3ffd5b436987b4) + +CVE: CVE-2026-53614 +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/cc81bbcec598cb91f0eb8456282f33eed820ed5f] +Signed-off-by: Peter Marko +--- + libmount/src/hook_mount.c | 3 ++- + libmount/src/hook_mount_legacy.c | 8 ++++++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c +index 1ffd19e83..37179fb59 100644 +--- a/libmount/src/hook_mount.c ++++ b/libmount/src/hook_mount.c +@@ -44,6 +44,7 @@ + */ + + #include "mountP.h" ++#include "env.h" + #include "fileutils.h" /* statx() fallback */ + #include "strutils.h" + #include "mount-api-utils.h" +@@ -627,7 +628,7 @@ fail: + + static int force_classic_mount(struct libmnt_context *cxt) + { +- const char *env = getenv("LIBMOUNT_FORCE_MOUNT2"); ++ const char *env = safe_getenv("LIBMOUNT_FORCE_MOUNT2"); + + if (env) { + if (strcmp(env, "always") == 0) +diff --git a/libmount/src/hook_mount_legacy.c b/libmount/src/hook_mount_legacy.c +index 18b7a0066..94a8fc685 100644 +--- a/libmount/src/hook_mount_legacy.c ++++ b/libmount/src/hook_mount_legacy.c +@@ -282,6 +282,8 @@ static int hook_prepare(struct libmnt_context *cxt, + + /* add extra mount(2) calls for each propagation flag */ + if (flags & MS_PROPAGATION) { ++ if (mnt_context_is_restricted(cxt)) ++ goto eperm; + rc = prepare_propagation(cxt, hs); + if (rc) + return rc; +@@ -291,12 +293,18 @@ static int hook_prepare(struct libmnt_context *cxt, + if ((flags & MS_BIND) + && (flags & MNT_BIND_SETTABLE) + && !(flags & MS_REMOUNT)) { ++ if (mnt_context_is_restricted(cxt)) ++ goto eperm; + rc = prepare_bindremount(cxt, hs); + if (rc) + return rc; + } + + return rc; ++eperm: ++ DBG(HOOK, ul_debugobj(hs, ++ "multi-step mount(2) refused for non-root user")); ++ return -EPERM; + } + + const struct libmnt_hookset hookset_mount_legacy = From patchwork Mon Oct 5 17:05:07 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Marko X-Patchwork-Id: 100009 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B62F1CA5FFE for ; Mon, 5 Oct 2026 17:05:36 +0000 (UTC) Received: from mta-65-228.siemens.flowmailer.net (mta-65-228.siemens.flowmailer.net [185.136.65.228]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24905.1791219934682157448 for ; Mon, 05 Oct 2026 10:05:36 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=peter.marko@siemens.com header.s=fm1 header.b=Jdsq0qyl; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.228, mailfrom: fm-256628-202610051705327d36f2c3bf0002072f-gz6gou@rts-flowmailer.siemens.com) Received: by mta-65-228.siemens.flowmailer.net with ESMTPSA id 202610051705327d36f2c3bf0002072f for ; Mon, 05 Oct 2026 19:05:32 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=peter.marko@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=djTdexBAuBvAswVwvNYMMUCkB0qWv9L4u3/kYMoVcEk=; b=Jdsq0qylcOcMoKzfGuKarw9gaqcWxUcXffGf3EmMKvdbnZi6VbMEoavS6rBGMFLX2OnRae ChfsGH2PerKpjSoweHcGl5URj3UihnyeAZpeGtUSAYWVqTaISULv6pmevBR0tHl1uEIz4mbP iWIHEOETESC9XJ/yqsWx36fWK6PYskVDgGy+329FBPEQQRm5XTBaTDqe1oDj/TP1XcJuYLc3 zfoAPhqAkD+YP/mcHOHKBzxitH8IIZxY2LUeD2wAcYnHduZknZDr9zFEGbGRYR7jK0XmojiP RSbPGtsGx33DmfuA1CfnazN95bLj1+CT7sLmhdGMq/8apAB/BhnRJXlA==; From: Peter Marko To: openembedded-core@lists.openembedded.org Cc: Peter Marko Subject: [scarthgap][PATCH 2/7] util-linux: patch CVE-2026-53613 Date: Mon, 5 Oct 2026 19:05:07 +0200 Message-ID: <20261005170513.632348-2-peter.marko@siemens.com> In-Reply-To: <20261005170513.632348-1-peter.marko@siemens.com> References: <20261005170513.632348-1-peter.marko@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-256628:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Mon, 05 Oct 2026 17:05:36 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247247 From: Peter Marko Pick patch referencing this CVE from 2.41.5 release. Also pick patches implementing used helper functions and fixing consequent build errors. Signed-off-by: Peter Marko --- meta/recipes-core/util-linux/util-linux.inc | 5 + ...ib-fileutils-add-ul_open_no_symlinks.patch | 98 +++++++++ ...dd-ul_openat_resolve-openat2-wrapper.patch | 85 ++++++++ ...x-RESOLVE_NO_SYMLINKS-fallback-value.patch | 71 +++++++ ...x-unused-parameter-warnings-without-.patch | 64 ++++++ .../util-linux/CVE-2026-53613.patch | 192 ++++++++++++++++++ 6 files changed, 515 insertions(+) create mode 100644 meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-add-ul_open_no_symlinks.patch create mode 100644 meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-add-ul_openat_resolve-openat2-wrapper.patch create mode 100644 meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-fix-RESOLVE_NO_SYMLINKS-fallback-value.patch create mode 100644 meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-fix-unused-parameter-warnings-without-.patch create mode 100644 meta/recipes-core/util-linux/util-linux/CVE-2026-53613.patch diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc index 70acf6dfec3..db698ef9367 100644 --- a/meta/recipes-core/util-linux/util-linux.inc +++ b/meta/recipes-core/util-linux/util-linux.inc @@ -50,6 +50,11 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin file://CVE-2026-13595.patch \ file://CVE-2026-3184.patch \ file://CVE-2026-53614.patch \ + file://0001-lib-fileutils-add-ul_open_no_symlinks.patch \ + file://0001-lib-fileutils-add-ul_openat_resolve-openat2-wrapper.patch \ + file://0001-lib-fileutils-fix-unused-parameter-warnings-without-.patch \ + file://0001-lib-fileutils-fix-RESOLVE_NO_SYMLINKS-fallback-value.patch \ + file://CVE-2026-53613.patch \ " SRC_URI[sha256sum] = "7b6605e48d1a49f43cc4b4cfc59f313d0dd5402fa40b96810bd572e167dfed0f" diff --git a/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-add-ul_open_no_symlinks.patch b/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-add-ul_open_no_symlinks.patch new file mode 100644 index 00000000000..d795e32087f --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-add-ul_open_no_symlinks.patch @@ -0,0 +1,98 @@ +From b639bf5c4277b7f828b3fcbdbf94bad5a4d20060 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Wed, 27 May 2026 10:35:39 +0200 +Subject: [PATCH] lib/fileutils: add ul_open_no_symlinks() + +Add a helper that opens a path rejecting symlinks at any component, +not just the last one. Uses openat2(RESOLVE_NO_SYMLINKS) when +available (Linux >= 5.6), falls back to open(O_NOFOLLOW). + +Signed-off-by: Karel Zak +(cherry picked from commit e01e38b24346a21f1d01498c265486a12c009e61) + +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/b639bf5c4277b7f828b3fcbdbf94bad5a4d20060] +Signed-off-by: Peter Marko +--- + configure.ac | 1 + + include/fileutils.h | 2 ++ + lib/fileutils.c | 24 ++++++++++++++++++++++++ + meson.build | 1 + + 4 files changed, 28 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 3bbc94488..2d9388a3c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -316,6 +316,7 @@ AC_CHECK_HEADERS([ \ + linux/kcmp.h \ + linux/net_namespace.h \ + linux/nsfs.h \ ++ linux/openat2.h \ + linux/pr.h \ + linux/raw.h \ + linux/securebits.h \ +diff --git a/include/fileutils.h b/include/fileutils.h +index 6fc93d0db..996e18322 100644 +--- a/include/fileutils.h ++++ b/include/fileutils.h +@@ -61,6 +61,8 @@ static inline int is_same_inode(const int fd, const struct stat *st) + return 1; + } + ++extern int ul_open_no_symlinks(const char *path, int flags, mode_t mode); ++ + extern int dup_fd_cloexec(int oldfd, int lowfd); + extern unsigned int get_fd_tabsize(void); + +diff --git a/lib/fileutils.c b/lib/fileutils.c +index b7acae430..a9c2022be 100644 +--- a/lib/fileutils.c ++++ b/lib/fileutils.c +@@ -11,7 +11,14 @@ + #include + #include + #include ++#include + #include ++#include ++#include ++ ++#ifdef HAVE_LINUX_OPENAT2_H ++# include ++#endif + + #include "c.h" + #include "all-io.h" +@@ -311,3 +318,20 @@ int ul_reopen(int fd, int flags) + + return open(buf, flags); + } ++ ++int ul_open_no_symlinks(const char *path, int flags, mode_t mode) ++{ ++#if defined(SYS_openat2) && defined(RESOLVE_NO_SYMLINKS) ++ struct open_how how = { ++ .flags = (__u64) flags, ++ .mode = (__u64) mode, ++ .resolve = RESOLVE_NO_SYMLINKS, ++ }; ++ int fd = syscall(SYS_openat2, AT_FDCWD, path, &how, sizeof(how)); ++ ++ /* only fall back to O_NOFOLLOW if the syscall is unavailable */ ++ if (fd >= 0 || errno != ENOSYS) ++ return fd; ++#endif ++ return open(path, flags | O_NOFOLLOW, mode); ++} +diff --git a/meson.build b/meson.build +index c79939c05..7b2b9ee71 100644 +--- a/meson.build ++++ b/meson.build +@@ -177,6 +177,7 @@ headers = ''' + linux/kcmp.h + linux/net_namespace.h + linux/nsfs.h ++ linux/openat2.h + linux/mount.h + linux/pr.h + linux/securebits.h diff --git a/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-add-ul_openat_resolve-openat2-wrapper.patch b/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-add-ul_openat_resolve-openat2-wrapper.patch new file mode 100644 index 00000000000..f8320ae82d5 --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-add-ul_openat_resolve-openat2-wrapper.patch @@ -0,0 +1,85 @@ +From 4cccf4edc256507734e3484cfaedf5980945c2fa Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 20 Jul 2026 14:36:16 +0200 +Subject: [PATCH] lib/fileutils: add ul_openat_resolve() openat2 wrapper + +Add ul_openat_resolve() as a generic openat2(2) wrapper with +caller-specified resolve flags. No fallback to weaker alternatives -- +returns -1/ENOSYS if openat2 is unavailable. + +Rewrite ul_open_no_symlinks() to use ul_openat_resolve() with +RESOLVE_NO_SYMLINKS, dropping the unsafe O_NOFOLLOW fallback that +only protected the final path component. + +Add fallback defines for RESOLVE_NO_SYMLINKS and RESOLVE_BENEATH +in fileutils.h. + +Signed-off-by: Karel Zak +(cherry picked from commit b9e07ce6f5ad54c38cf3ebc7100101e487be91bd) +(cherry picked from commit 1426aa06ff2f6a21cba9102c35e3577641b356ff) + +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/4cccf4edc256507734e3484cfaedf5980945c2fa] +Signed-off-by: Peter Marko +--- + include/fileutils.h | 9 +++++++++ + lib/fileutils.c | 22 ++++++++++++++-------- + 2 files changed, 23 insertions(+), 8 deletions(-) + +diff --git a/include/fileutils.h b/include/fileutils.h +index 996e18322..09395620a 100644 +--- a/include/fileutils.h ++++ b/include/fileutils.h +@@ -62,6 +62,15 @@ static inline int is_same_inode(const int fd, const struct stat *st) + } + + extern int ul_open_no_symlinks(const char *path, int flags, mode_t mode); ++extern int ul_openat_resolve(int dirfd, const char *path, int flags, ++ mode_t mode, unsigned long long resolve); ++ ++#ifndef RESOLVE_NO_SYMLINKS ++# define RESOLVE_NO_SYMLINKS 0x02 ++#endif ++#ifndef RESOLVE_BENEATH ++# define RESOLVE_BENEATH 0x08 ++#endif + + extern int dup_fd_cloexec(int oldfd, int lowfd); + extern unsigned int get_fd_tabsize(void); +diff --git a/lib/fileutils.c b/lib/fileutils.c +index a9c2022be..c60070855 100644 +--- a/lib/fileutils.c ++++ b/lib/fileutils.c +@@ -319,19 +319,25 @@ int ul_reopen(int fd, int flags) + return open(buf, flags); + } + +-int ul_open_no_symlinks(const char *path, int flags, mode_t mode) ++int ul_openat_resolve(int dirfd, const char *path, int flags, ++ mode_t mode, unsigned long long resolve) + { +-#if defined(SYS_openat2) && defined(RESOLVE_NO_SYMLINKS) ++#if defined(SYS_openat2) + struct open_how how = { + .flags = (__u64) flags, + .mode = (__u64) mode, +- .resolve = RESOLVE_NO_SYMLINKS, ++ .resolve = resolve, + }; +- int fd = syscall(SYS_openat2, AT_FDCWD, path, &how, sizeof(how)); + +- /* only fall back to O_NOFOLLOW if the syscall is unavailable */ +- if (fd >= 0 || errno != ENOSYS) +- return fd; ++ return syscall(SYS_openat2, dirfd, path, &how, sizeof(how)); ++#else ++ errno = ENOSYS; ++ return -1; + #endif +- return open(path, flags | O_NOFOLLOW, mode); ++} ++ ++int ul_open_no_symlinks(const char *path, int flags, mode_t mode) ++{ ++ return ul_openat_resolve(AT_FDCWD, path, flags, mode, ++ RESOLVE_NO_SYMLINKS); + } diff --git a/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-fix-RESOLVE_NO_SYMLINKS-fallback-value.patch b/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-fix-RESOLVE_NO_SYMLINKS-fallback-value.patch new file mode 100644 index 00000000000..440b513f4b5 --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-fix-RESOLVE_NO_SYMLINKS-fallback-value.patch @@ -0,0 +1,71 @@ +From ba905a1874959c70fd706aa7d49df61076864e0a Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 8 Sep 2026 10:26:38 +0200 +Subject: [PATCH] lib/fileutils: fix RESOLVE_NO_SYMLINKS fallback value + +The fallback #define used 0x02, but that is RESOLVE_NO_MAGICLINKS. +The correct value, as used by the kernel and glibc, is 0x04. + +The fallback is not dead code: no libmount source includes +, and glibc provides the RESOLVE_* macros only via +, which is a recent addition. On older glibc libmount +then asks openat2() to block magic-links instead of symlinks. The +syscall succeeds and follows the symlink, so the protection in +mnt_context_open_tree(), hook_mount.c and hook_idmap.c is silently +ineffective. + +Move the include from lib/fileutils.c to +include/fileutils.h so all users get the kernel values, and correct +the fallback. + +Fixes: b9e07ce6f ("lib/fileutils: add ul_openat_resolve() openat2 wrapper") +Addresses: https://github.com/util-linux/util-linux/issues/4606 +Signed-off-by: Karel Zak +(cherry picked from commit 20361d66df4d3f32d5e137fe61a55cdf156c91f0) + +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/ba905a1874959c70fd706aa7d49df61076864e0a] +Signed-off-by: Peter Marko +--- + include/fileutils.h | 6 +++++- + lib/fileutils.c | 4 ---- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/include/fileutils.h b/include/fileutils.h +index 09395620a..0b36104be 100644 +--- a/include/fileutils.h ++++ b/include/fileutils.h +@@ -11,6 +11,10 @@ + #include + #include + ++#ifdef HAVE_LINUX_OPENAT2_H ++# include ++#endif ++ + #include "c.h" + + extern int mkstemp_cloexec(char *template); +@@ -66,7 +70,7 @@ extern int ul_openat_resolve(int dirfd, const char *path, int flags, + mode_t mode, unsigned long long resolve); + + #ifndef RESOLVE_NO_SYMLINKS +-# define RESOLVE_NO_SYMLINKS 0x02 ++# define RESOLVE_NO_SYMLINKS 0x04 + #endif + #ifndef RESOLVE_BENEATH + # define RESOLVE_BENEATH 0x08 +diff --git a/lib/fileutils.c b/lib/fileutils.c +index 1142febb0..8ca2c0aae 100644 +--- a/lib/fileutils.c ++++ b/lib/fileutils.c +@@ -16,10 +16,6 @@ + #include + #include + +-#ifdef HAVE_LINUX_OPENAT2_H +-# include +-#endif +- + #include "c.h" + #include "all-io.h" + #include "fileutils.h" diff --git a/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-fix-unused-parameter-warnings-without-.patch b/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-fix-unused-parameter-warnings-without-.patch new file mode 100644 index 00000000000..fe14fcae9f0 --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/0001-lib-fileutils-fix-unused-parameter-warnings-without-.patch @@ -0,0 +1,64 @@ +From 339ff352b7b8b868367d2370ed077675326c3bca Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Thu, 3 Sep 2026 09:45:29 +0200 +Subject: [PATCH] lib/fileutils: fix unused parameter warnings without + SYS_openat2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On systems without SYS_openat2 (older kernels), ul_openat_resolve() +is a stub that returns -ENOSYS, making all parameters unused. With +-Werror=unused-parameter this breaks the build. + +Move the #ifdef around the whole function so each branch has its own +declaration — the SYS_openat2 branch uses all parameters normally, +the fallback branch marks them __unused__. + +Fixes: fb8e26535 ("libmount: pin source path with openat2() for restricted users") +Signed-off-by: Karel Zak +(cherry picked from commit a471b62e732a491f1abe42450352fb0f9b5b43ea) + +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/339ff352b7b8b868367d2370ed077675326c3bca] +Signed-off-by: Peter Marko +--- + lib/fileutils.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/lib/fileutils.c b/lib/fileutils.c +index c60070855..1142febb0 100644 +--- a/lib/fileutils.c ++++ b/lib/fileutils.c +@@ -319,10 +319,10 @@ int ul_reopen(int fd, int flags) + return open(buf, flags); + } + ++#if defined(SYS_openat2) + int ul_openat_resolve(int dirfd, const char *path, int flags, + mode_t mode, unsigned long long resolve) + { +-#if defined(SYS_openat2) + struct open_how how = { + .flags = (__u64) flags, + .mode = (__u64) mode, +@@ -330,11 +330,19 @@ int ul_openat_resolve(int dirfd, const char *path, int flags, + }; + + return syscall(SYS_openat2, dirfd, path, &how, sizeof(how)); ++} + #else ++int ul_openat_resolve( ++ int dirfd __attribute__((__unused__)), ++ const char *path __attribute__((__unused__)), ++ int flags __attribute__((__unused__)), ++ mode_t mode __attribute__((__unused__)), ++ unsigned long long resolve __attribute__((__unused__))) ++{ + errno = ENOSYS; + return -1; +-#endif + } ++#endif + + int ul_open_no_symlinks(const char *path, int flags, mode_t mode) + { diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2026-53613.patch b/meta/recipes-core/util-linux/util-linux/CVE-2026-53613.patch new file mode 100644 index 00000000000..0fb313d3db2 --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/CVE-2026-53613.patch @@ -0,0 +1,192 @@ +From 2c002044d1be71ebf45c24571f1a4532a408d0d7 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 16 Jun 2026 11:13:54 +0200 +Subject: [PATCH 07/15] libmount: add fd_target to context for TOCTOU + prevention + +Add a pinned O_PATH target fd to libmnt_context with lazy-open getter +mnt_context_get_target_fd() and mnt_context_close_target_fd(). + +The fd is opened via ul_open_no_symlinks() (RESOLVE_NO_SYMLINKS) to +reject symlinks at any path component. The fd is closed on context +reset. + +CVE-2026-53613 + +Signed-off-by: Karel Zak +(cherry picked from commit 78a860982e036f38fe9c0b3344998df5ac2c2ff5) + +CVE: CVE-2026-53613 +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/0b010025a0e429bc80355c94db86a843395d49e2] +Signed-off-by: Peter Marko +--- + libmount/src/context.c | 43 ++++++++++++++++++++++++++++++++ + libmount/src/context_mount.c | 7 ++++++ + libmount/src/hook_mount.c | 18 ++++++++++++- + libmount/src/hook_mount_legacy.c | 3 +++ + libmount/src/mountP.h | 7 ++++++ + 5 files changed, 77 insertions(+), 1 deletion(-) + +diff --git a/libmount/src/context.c b/libmount/src/context.c +index 0cd320190..3055c63df 100644 +--- a/libmount/src/context.c ++++ b/libmount/src/context.c +@@ -37,6 +37,7 @@ + */ + + #include "mountP.h" ++#include "fileutils.h" + #include "strutils.h" + #include "namespace.h" + #include "match.h" +@@ -65,6 +66,7 @@ struct libmnt_context *mnt_new_context(void) + cxt->ns_orig.fd = -1; + cxt->ns_tgt.fd = -1; + cxt->ns_cur = &cxt->ns_orig; ++ cxt->fd_target = -1; + + cxt->map_linux = mnt_get_builtin_optmap(MNT_LINUX_MAP); + cxt->map_userspace = mnt_get_builtin_optmap(MNT_USERSPACE_MAP); +@@ -171,6 +173,7 @@ int mnt_reset_context(struct libmnt_context *cxt) + cxt->map_userspace = mnt_get_builtin_optmap(MNT_USERSPACE_MAP); + + mnt_context_reset_status(cxt); ++ mnt_context_close_target_fd(cxt); + mnt_context_deinit_hooksets(cxt); + + if (cxt->table_fltrcb) +@@ -395,6 +398,46 @@ int mnt_context_is_restricted(struct libmnt_context *cxt) + return cxt->restricted; + } + ++int mnt_context_target_fd_required(struct libmnt_context *cxt) ++{ ++ return mnt_context_is_restricted(cxt); ++} ++ ++int mnt_context_reopen_target_fd(struct libmnt_context *cxt) ++{ ++ assert(cxt); ++ ++ if (!mnt_context_target_fd_required(cxt)) ++ return 0; ++ mnt_context_close_target_fd(cxt); ++ if (mnt_context_get_target_fd(cxt) < 0) ++ return -errno; ++ return 0; ++} ++ ++int mnt_context_get_target_fd(struct libmnt_context *cxt) ++{ ++ assert(cxt); ++ ++ if (cxt->fd_target < 0) { ++ const char *target = mnt_fs_get_target(cxt->fs); ++ ++ if (target) ++ cxt->fd_target = ul_open_no_symlinks(target, ++ O_PATH | O_CLOEXEC, 0); ++ } ++ return cxt->fd_target; ++} ++ ++void mnt_context_close_target_fd(struct libmnt_context *cxt) ++{ ++ assert(cxt); ++ ++ if (cxt->fd_target >= 0) ++ close(cxt->fd_target); ++ cxt->fd_target = -1; ++} ++ + /** + * mnt_context_force_unrestricted: + * @cxt: mount context +diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c +index 41986e74b..dd46bf053 100644 +--- a/libmount/src/context_mount.c ++++ b/libmount/src/context_mount.c +@@ -726,6 +726,13 @@ static int prepare_target(struct libmnt_context *cxt) + if (rc == 0) + rc = mnt_context_call_hooks(cxt, MNT_STAGE_PREP_TARGET); + ++ if (rc == 0 ++ && mnt_context_target_fd_required(cxt) ++ && mnt_context_get_target_fd(cxt) < 0) { ++ DBG(CXT, ul_debugobj(cxt, "failed to pin target")); ++ rc = -errno; ++ } ++ + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + +diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c +index 593111168..a34b2d4bd 100644 +--- a/libmount/src/hook_mount.c ++++ b/libmount/src/hook_mount.c +@@ -527,9 +527,25 @@ static int hook_attach_target(struct libmnt_context *cxt, + umount2(target, MNT_DETACH); + } + +- rc = move_mount(api->fd_tree, "", AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH); ++ /* fd_target is open in restricted mode (see prepare_target()) */ ++ if (mnt_context_target_fd_required(cxt)) { ++ int fd = mnt_context_get_target_fd(cxt); ++ ++ if (fd < 0) ++ return -errno; ++ rc = move_mount(api->fd_tree, "", fd, "", ++ MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH); ++ } else ++ rc = move_mount(api->fd_tree, "", AT_FDCWD, target, ++ MOVE_MOUNT_F_EMPTY_PATH); ++ + set_syscall_status(cxt, "move_mount", rc == 0); + ++ if (rc == 0) { ++ /* re-open to point to the mounted filesystem root */ ++ rc = mnt_context_reopen_target_fd(cxt); ++ } ++ + return rc == 0 ? 0 : -errno; + } + +diff --git a/libmount/src/hook_mount_legacy.c b/libmount/src/hook_mount_legacy.c +index 56e92b05d..b7882a108 100644 +--- a/libmount/src/hook_mount_legacy.c ++++ b/libmount/src/hook_mount_legacy.c +@@ -248,6 +248,9 @@ static int hook_mount(struct libmnt_context *cxt, + return rc; + } + ++ /* re-open to point to the mounted filesystem root */ ++ rc = mnt_context_reopen_target_fd(cxt); ++ + cxt->syscall_status = 0; + return rc; + } +diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h +index 339e2761a..37a00e571 100644 +--- a/libmount/src/mountP.h ++++ b/libmount/src/mountP.h +@@ -442,6 +442,8 @@ struct libmnt_context + unsigned int has_selinux_opt : 1; /* temporary for broken fsconfig() syscall */ + unsigned int force_clone : 1; /* OPEN_TREE_CLONE */ + ++ int fd_target; /* pinned target fd (RESOLVE_NO_SYMLINKS) */ ++ + struct list_head hooksets_datas; /* global hooksets data */ + struct list_head hooksets_hooks; /* global hooksets data */ + }; +@@ -630,6 +632,11 @@ extern int mnt_context_prepare_update(struct libmnt_context *cxt); + extern int mnt_context_merge_mflags(struct libmnt_context *cxt); + extern int mnt_context_update_tabs(struct libmnt_context *cxt); + ++extern int mnt_context_target_fd_required(struct libmnt_context *cxt); ++extern int mnt_context_get_target_fd(struct libmnt_context *cxt); ++extern void mnt_context_close_target_fd(struct libmnt_context *cxt); ++extern int mnt_context_reopen_target_fd(struct libmnt_context *cxt); ++ + extern int mnt_context_umount_setopt(struct libmnt_context *cxt, int c, char *arg); + extern int mnt_context_mount_setopt(struct libmnt_context *cxt, int c, char *arg); + From patchwork Mon Oct 5 17:05:08 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Marko X-Patchwork-Id: 100010 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6EE2ACA5FFC for ; Mon, 5 Oct 2026 17:05:46 +0000 (UTC) Received: from mta-64-228.siemens.flowmailer.net (mta-64-228.siemens.flowmailer.net [185.136.64.228]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24908.1791219943464556503 for ; Mon, 05 Oct 2026 10:05:43 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=peter.marko@siemens.com header.s=fm1 header.b=ui2+FrBB; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.228, mailfrom: fm-256628-202610051705415f34293a7900020727-f62u0x@rts-flowmailer.siemens.com) Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 202610051705415f34293a7900020727 for ; Mon, 05 Oct 2026 19:05:41 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=peter.marko@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=ALQobqc+evjUHSRM16+GdohL9S1iuvBE5Uq2at5mEuY=; b=ui2+FrBBOsa5gE/dwPUlBsDWlYYBnzSSAv10F7cpE7Q7bJgXKIYACK6zIQInuersgVvwIF Aha9EtO5Izb3As3RmYxcgMnisNt69jW9HvMtCDlmWlNAH7RtQgB+3mFUEzUjJDqXdPRSrfH8 lQhshzpCE0ZcW1NzcSpy5XhxLzxSZF5PdsldULsliulcoop18qgViKTkXB3oFgbbHCjVVO1K v4lpcBmwhCKq50iBQ+5GC5DYVWdjY0oZdst+30J4bHEGAb/7WgvfqVo4W9ggjNgDctjYuN/9 tNrrkzo55VRJCw2/4paIxavA2fckQfUe+f9QdsAHHPhUvFpg9OuvqQDw==; From: Peter Marko To: openembedded-core@lists.openembedded.org Cc: Peter Marko Subject: [scarthgap][PATCH 3/7] util-linux: patch CVE-2026-53612 Date: Mon, 5 Oct 2026 19:05:08 +0200 Message-ID: <20261005170513.632348-3-peter.marko@siemens.com> In-Reply-To: <20261005170513.632348-1-peter.marko@siemens.com> References: <20261005170513.632348-1-peter.marko@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-256628:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Mon, 05 Oct 2026 17:05:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247248 From: Peter Marko Pick patch referencing this CVE from 2.41.5 release. Signed-off-by: Peter Marko --- meta/recipes-core/util-linux/util-linux.inc | 1 + .../util-linux/CVE-2026-53612.patch | 92 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 meta/recipes-core/util-linux/util-linux/CVE-2026-53612.patch diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc index db698ef9367..4b889927c80 100644 --- a/meta/recipes-core/util-linux/util-linux.inc +++ b/meta/recipes-core/util-linux/util-linux.inc @@ -55,6 +55,7 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin file://0001-lib-fileutils-fix-unused-parameter-warnings-without-.patch \ file://0001-lib-fileutils-fix-RESOLVE_NO_SYMLINKS-fallback-value.patch \ file://CVE-2026-53613.patch \ + file://CVE-2026-53612.patch \ " SRC_URI[sha256sum] = "7b6605e48d1a49f43cc4b4cfc59f313d0dd5402fa40b96810bd572e167dfed0f" diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2026-53612.patch b/meta/recipes-core/util-linux/util-linux/CVE-2026-53612.patch new file mode 100644 index 00000000000..94a70c6159c --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/CVE-2026-53612.patch @@ -0,0 +1,92 @@ +From 897a08c2b11dfa66975c3d24d63c7bf5f5be1a7c Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 16 Jun 2026 11:15:19 +0200 +Subject: [PATCH] libmount: use fd-based fchownat/chmod in hook_owner + +Replace path-based lchown()/chmod() with fd-based operations in the +X-mount.{owner,group,mode} post-mount hook. + +For restricted users the fd_target is pinned in prepare_target() and +re-opened after mount in hook_attach_target() to point to the mounted +filesystem root. For root a local O_PATH fd is opened. Ownership is +changed via fchownat(fd, "", ..., AT_EMPTY_PATH), mode via +/proc/self/fd/N. + +This prevents TOCTOU attacks where an ancestor directory is swapped +between mount and the chmod/chown operations. + +CVE-2026-53612 + +Reported-by: Xinyao Hu +Signed-off-by: Karel Zak +(cherry picked from commit 24da33905c7115c4cbccd0afb2a469804e96467a) + +CVE: CVE-2026-53612 +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/897a08c2b11dfa66975c3d24d63c7bf5f5be1a7c] +Signed-off-by: Peter Marko +--- + libmount/src/hook_owner.c | 32 ++++++++++++++++++++++++-------- + 1 file changed, 24 insertions(+), 8 deletions(-) + +diff --git a/libmount/src/hook_owner.c b/libmount/src/hook_owner.c +index 11b238c89..99f0e705d 100644 +--- a/libmount/src/hook_owner.c ++++ b/libmount/src/hook_owner.c +@@ -17,6 +17,7 @@ + #include + + #include "mountP.h" ++#include "pathnames.h" + #include "fileutils.h" + + struct hook_data { +@@ -48,7 +49,7 @@ static int hook_post( + { + struct hook_data *hd = (struct hook_data *) data; + const char *target; +- int rc = 0; ++ int rc = 0, fd; + + assert(cxt); + +@@ -59,18 +60,33 @@ static int hook_post( + if (!target) + return 0; + ++ /* fd_target is pinned in restricted mode (see prepare_target()), ++ * for root open it here to keep chmod/chown fd-based too */ ++ if (mnt_context_target_fd_required(cxt)) ++ fd = mnt_context_get_target_fd(cxt); ++ else ++ fd = open(target, O_PATH | O_CLOEXEC); ++ ++ if (fd < 0) ++ return -MNT_ERR_CHMOD; ++ + if (hd->owner != (uid_t) -1 || hd->group != (uid_t) -1) { +- DBG(CXT, ul_debugobj(cxt, " lchown(%s, %u, %u)", target, hd->owner, hd->group)); +- if (lchown(target, hd->owner, hd->group) == -1) +- return -MNT_ERR_CHOWN; ++ DBG(CXT, ul_debugobj(cxt, " fchownat(%s, %u, %u)", target, hd->owner, hd->group)); ++ if (fchownat(fd, "", hd->owner, hd->group, AT_EMPTY_PATH) == -1) ++ rc = -MNT_ERR_CHOWN; + } + +- if (hd->mode != (mode_t) -1) { +- DBG(CXT, ul_debugobj(cxt, " chmod(%s, %04o)", target, hd->mode)); +- if (chmod(target, hd->mode) == -1) +- return -MNT_ERR_CHMOD; ++ if (!rc && hd->mode != (mode_t) -1) { ++ char buf[sizeof(_PATH_PROC_FDDIR) + 1 + sizeof(stringify_value(INT_MAX))]; ++ ++ snprintf(buf, sizeof(buf), _PATH_PROC_FDDIR "/%d", fd); ++ DBG(CXT, ul_debugobj(cxt, " chmod(%s, %04o)", buf, hd->mode)); ++ if (chmod(buf, hd->mode) == -1) ++ rc = -MNT_ERR_CHMOD; + } + ++ if (!mnt_context_target_fd_required(cxt)) ++ close(fd); + return rc; + } + From patchwork Mon Oct 5 17:05:09 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Marko X-Patchwork-Id: 100011 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 70B63CA5FFC for ; Mon, 5 Oct 2026 17:06:06 +0000 (UTC) Received: from mta-65-227.siemens.flowmailer.net (mta-65-227.siemens.flowmailer.net [185.136.65.227]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.25233.1791219957173545072 for ; Mon, 05 Oct 2026 10:05:57 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=peter.marko@siemens.com header.s=fm1 header.b=jL3YYkDl; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.227, mailfrom: fm-256628-202610051705555a5dc089e100020760-jb0dc6@rts-flowmailer.siemens.com) Received: by mta-65-227.siemens.flowmailer.net with ESMTPSA id 202610051705555a5dc089e100020760 for ; Mon, 05 Oct 2026 19:05:55 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=peter.marko@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=TV0kE1e9yRi0sxPQuJG9fAuTbGpsRNc5F0BUUfeGYMs=; b=jL3YYkDlW7tkLj3QbpbLF1JRPt0T7UtGpfIQ8qX2WsuYO0bJTuEbBLWKttHIwC/zDKg0Kn /m7eLGeQWktR3LF3x7QEsl3L1xa9hIsQZ9F4jzg/BbWn7f3Ty33WIhWsWHNjWC10adO5Re76 ZvWJ5M8rfRxihOMpPu3+mhMJITIUFG878QzAa2WZCrAWvHA4zhlzPZCdIWaWxMDX/BPvrNac hJw5wy/cdFc23eTL5TNUcaR+m1Vu8naiytERQYL98IJb8h7jiwGFJdPCNPrVlGv8QgThRNDb k5MZbyDA3o4+ExcryQIYrodXaz7WP4Y3Yr1jfOu/i4lHvvg31LbGqz6w==; From: Peter Marko To: openembedded-core@lists.openembedded.org Cc: Peter Marko Subject: [scarthgap][PATCH 4/7] util-linux: patch CVE-2024-28085 regression Date: Mon, 5 Oct 2026 19:05:09 +0200 Message-ID: <20261005170513.632348-4-peter.marko@siemens.com> In-Reply-To: <20261005170513.632348-1-peter.marko@siemens.com> References: <20261005170513.632348-1-peter.marko@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-256628:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Mon, 05 Oct 2026 17:06:06 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247249 From: Peter Marko Pick patch referencing this CVE from 2.41.6 release. Signed-off-by: Peter Marko --- meta/recipes-core/util-linux/util-linux.inc | 1 + .../util-linux/CVE-2024-28085-0003.patch | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 meta/recipes-core/util-linux/util-linux/CVE-2024-28085-0003.patch diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc index 4b889927c80..6598a92b30f 100644 --- a/meta/recipes-core/util-linux/util-linux.inc +++ b/meta/recipes-core/util-linux/util-linux.inc @@ -56,6 +56,7 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin file://0001-lib-fileutils-fix-RESOLVE_NO_SYMLINKS-fallback-value.patch \ file://CVE-2026-53613.patch \ file://CVE-2026-53612.patch \ + file://CVE-2024-28085-0003.patch \ " SRC_URI[sha256sum] = "7b6605e48d1a49f43cc4b4cfc59f313d0dd5402fa40b96810bd572e167dfed0f" diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2024-28085-0003.patch b/meta/recipes-core/util-linux/util-linux/CVE-2024-28085-0003.patch new file mode 100644 index 00000000000..63d09ef4a1b --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/CVE-2024-28085-0003.patch @@ -0,0 +1,77 @@ +From 61b49b7160bbb6780279344574746617e7fb11a4 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 24 Aug 2026 16:37:28 +0200 +Subject: [PATCH] wall, write: sanitize hostname in banner header + +The CVE-2024-28085 fix sanitized only message bodies via +fputs_careful(), but the banner headers in wall(1) and write(1) +still interpolate the system hostname without sanitization. + +An unprivileged user can set a malicious hostname containing +terminal escape sequences via a user namespace (unshare -Ur -u ++ sethostname(2)), and wall/write will deliver those sequences +to the terminals of all logged-in users. + +Fix by routing the banner output through fputs_careful() which +strips control characters. + +This is an additional fix for CVE-2024-28085 (CVSS 3.1 score: 3.3). +A new CVE ID has not been assigned (yet). + +Reported-by: Skyler Ferrante +Signed-off-by: Karel Zak +(cherry picked from commit 9ce8f2b5aefa011ef5b0c34aa14df9bb9db02dab) +(cherry picked from commit f358b098d47659837d85b66fb387201224b272a0) + +CVE: CVE-2024-28085 +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/61b49b7160bbb6780279344574746617e7fb11a4] +Signed-off-by: Peter Marko +--- + term-utils/wall.c | 3 ++- + term-utils/write.c | 6 ++++-- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/term-utils/wall.c b/term-utils/wall.c +index 7a4a858f5..c1c47d531 100644 +--- a/term-utils/wall.c ++++ b/term-utils/wall.c +@@ -316,7 +316,8 @@ static char *makemsg(char *fname, char **mvec, int mvecsz, + snprintf(lbuf, lbuflen, + _("Broadcast message from %s@%s (%s) (%s):"), + whom, hostname, where, date); +- fprintf(fs, "%-*.*s\007\007\r\n", TERM_WIDTH, TERM_WIDTH, lbuf); ++ fputs_careful(lbuf, fs, '^', true, TERM_WIDTH); ++ fprintf(fs, "\007\007\r\n"); + free(hostname); + } + fprintf(fs, "%*s\r\n", TERM_WIDTH, " "); +diff --git a/term-utils/write.c b/term-utils/write.c +index 3784f0300..d680d7464 100644 +--- a/term-utils/write.c ++++ b/term-utils/write.c +@@ -233,6 +233,7 @@ static void do_write(const struct write_control *ctl) + time_t now; + struct tm *tm; + char *host, *line = NULL; ++ char buf[512]; + size_t linelen = 0; + struct sigaction sigact; + +@@ -262,14 +263,15 @@ static void do_write(const struct write_control *ctl) + /* print greeting */ + printf("\r\n\a\a\a"); + if (strcmp(login, pwuid) != 0) +- printf(_("Message from %s@%s (as %s) on %s at %02d:%02d ..."), ++ snprintf(buf, sizeof(buf), _("Message from %s@%s (as %s) on %s at %02d:%02d ..."), + login, host, pwuid, ctl->src_tty_name, + tm->tm_hour, tm->tm_min); + else +- printf(_("Message from %s@%s on %s at %02d:%02d ..."), ++ snprintf(buf, sizeof(buf), _("Message from %s@%s on %s at %02d:%02d ..."), + login, host, ctl->src_tty_name, + tm->tm_hour, tm->tm_min); + free(host); ++ fputs_careful(buf, stdout, '^', true, 0); + printf("\r\n"); + + while (getline(&line, &linelen, stdin) >= 0) { From patchwork Mon Oct 5 17:05:10 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Marko X-Patchwork-Id: 100012 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6CD40CA5FFC for ; Mon, 5 Oct 2026 17:06:16 +0000 (UTC) Received: from mta-64-227.siemens.flowmailer.net (mta-64-227.siemens.flowmailer.net [185.136.64.227]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24923.1791219970724437418 for ; Mon, 05 Oct 2026 10:06:11 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=peter.marko@siemens.com header.s=fm1 header.b=Lu5QaPyV; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.227, mailfrom: fm-256628-20261005170608190ae80683000207f2-zpfeqy@rts-flowmailer.siemens.com) Received: by mta-64-227.siemens.flowmailer.net with ESMTPSA id 20261005170608190ae80683000207f2 for ; Mon, 05 Oct 2026 19:06:08 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=peter.marko@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=d9E9Y/RjjoliH5ftZ0EBSvd60dBY4qDRbkdeECMHl4Y=; b=Lu5QaPyVrd33/ShxcMs14Ps6hCJchkpqWUOs/FW5spzZrz1pRsV6fOfgMfA5A+QLifwoPm EVJtU2pHH/0ktXc3ZJNCE+fu4FKANw4UWzVfKWq2/nfP9yOonGNcTmFycNDRy2mdTv/tHRfp p3Mm67g1TNhIxvTGmIebiMDNMBg7VZIwQe6r0zIfF6hTVa9ZMKOjpiXLB2bGxJj608UYU2+X c5kqNsWDTa1dIhHVYTIVhTsINg/nJTfHEOs/TrXUtkVS3xAtK4uEM5v+n3RPJ9bHz7Wcj3gN IsV1cRUzVKL3tZVHLvpoeLlJN7BRuV/saHQEBeflcXtfWIaeBvdlB5AQ==; From: Peter Marko To: openembedded-core@lists.openembedded.org Cc: Peter Marko Subject: [scarthgap][PATCH 5/7] util-linux: patch CVE-2026-78408 Date: Mon, 5 Oct 2026 19:05:10 +0200 Message-ID: <20261005170513.632348-5-peter.marko@siemens.com> In-Reply-To: <20261005170513.632348-1-peter.marko@siemens.com> References: <20261005170513.632348-1-peter.marko@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-256628:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Mon, 05 Oct 2026 17:06:16 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247250 From: Peter Marko Pick patch referencing this CVE from 2.41.6 release. Regression patch as submitted to Wrynose is not needed as that code is not yet present in 2.39.3. Signed-off-by: Peter Marko --- meta/recipes-core/util-linux/util-linux.inc | 1 + .../util-linux/CVE-2026-78408.patch | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 meta/recipes-core/util-linux/util-linux/CVE-2026-78408.patch diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc index 6598a92b30f..2eb9251a704 100644 --- a/meta/recipes-core/util-linux/util-linux.inc +++ b/meta/recipes-core/util-linux/util-linux.inc @@ -57,6 +57,7 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin file://CVE-2026-53613.patch \ file://CVE-2026-53612.patch \ file://CVE-2024-28085-0003.patch \ + file://CVE-2026-78408.patch \ " SRC_URI[sha256sum] = "7b6605e48d1a49f43cc4b4cfc59f313d0dd5402fa40b96810bd572e167dfed0f" diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2026-78408.patch b/meta/recipes-core/util-linux/util-linux/CVE-2026-78408.patch new file mode 100644 index 00000000000..36f3c91ddc5 --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/CVE-2026-78408.patch @@ -0,0 +1,98 @@ +From 43ec8a89f6c99130727084b3496a2ffd2b4200f0 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 31 Aug 2026 17:03:32 +0200 +Subject: [PATCH] nsenter, unshare: add O_CLOEXEC to all open() calls + [CVE-2026-78408] + +Add O_CLOEXEC (and EFD_CLOEXEC for eventfd) as defense in depth to +all file descriptor creation sites in nsenter and unshare. All these +descriptors are already explicitly closed before exec, but O_CLOEXEC +provides a safety net against future code changes that might +accidentally introduce a leak path. + +No functional change. + +Signed-off-by: Karel Zak + +CVE: CVE-2026-78408 +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/43ec8a89f6c99130727084b3496a2ffd2b4200f0] +Backport notes: +- 2 hunks left out as that code is not yet present in 2.39.3. +- Verified that no other "open(" calls are in this version in patched files. +Signed-off-by: Peter Marko +--- + sys-utils/nsenter.c | 6 +++--- + sys-utils/unshare.c | 8 ++++---- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/sys-utils/nsenter.c b/sys-utils/nsenter.c +index cf6c83174..9d9d90a48 100644 +--- a/sys-utils/nsenter.c ++++ b/sys-utils/nsenter.c +@@ -134,7 +134,7 @@ static void open_target_fd(int *fd, const char *type, const char *path) + if (*fd >= 0) + close(*fd); + +- *fd = open(path, O_RDONLY); ++ *fd = open(path, O_RDONLY | O_CLOEXEC); + if (*fd < 0) + err(EXIT_FAILURE, _("cannot open %s"), path); + } +@@ -492,7 +492,7 @@ int main(int argc, char *argv[]) + + /* Remember the current working directory if I'm not changing it */ + if (root_fd >= 0 && wd_fd < 0 && wdns == NULL) { +- wd_fd = open(".", O_RDONLY); ++ wd_fd = open(".", O_RDONLY | O_CLOEXEC); + if (wd_fd < 0) + err(EXIT_FAILURE, + _("cannot open current working directory")); +@@ -515,7 +515,7 @@ int main(int argc, char *argv[]) + + /* working directory specified as in-namespace path */ + if (wdns) { +- wd_fd = open(wdns, O_RDONLY); ++ wd_fd = open(wdns, O_RDONLY | O_CLOEXEC); + if (wd_fd < 0) + err(EXIT_FAILURE, + _("cannot open current working directory")); +diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c +index 05db627be..c47739862 100644 +--- a/sys-utils/unshare.c ++++ b/sys-utils/unshare.c +@@ -108,7 +108,7 @@ static void setgroups_control(int action) + return; + cmd = setgroups_strings[action]; + +- fd = open(file, O_WRONLY); ++ fd = open(file, O_WRONLY | O_CLOEXEC); + if (fd < 0) { + if (errno == ENOENT) + return; +@@ -125,7 +125,7 @@ static void map_id(const char *file, uint32_t from, uint32_t to) + char *buf; + int fd; + +- fd = open(file, O_WRONLY); ++ fd = open(file, O_WRONLY | O_CLOEXEC); + if (fd < 0) + err(EXIT_FAILURE, _("cannot open %s"), file); + +@@ -219,7 +219,7 @@ static void settime(time_t offset, clockid_t clk_id) + + len = snprintf(buf, sizeof(buf), "%d %" PRId64 " 0", clk_id, (int64_t) offset); + +- fd = open("/proc/self/timens_offsets", O_WRONLY); ++ fd = open("/proc/self/timens_offsets", O_WRONLY | O_CLOEXEC); + if (fd < 0) + err(EXIT_FAILURE, _("failed to open /proc/self/timens_offsets")); + +@@ -289,7 +289,7 @@ static pid_t fork_and_wait(int *fd) + pid_t pid; + uint64_t ch; + +- *fd = eventfd(0, 0); ++ *fd = eventfd(0, EFD_CLOEXEC); + if (*fd < 0) + err(EXIT_FAILURE, _("eventfd failed")); + From patchwork Mon Oct 5 17:05:11 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Marko X-Patchwork-Id: 100013 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6F3C1CA5FFC for ; Mon, 5 Oct 2026 17:06:26 +0000 (UTC) Received: from mta-64-227.siemens.flowmailer.net (mta-64-227.siemens.flowmailer.net [185.136.64.227]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.25245.1791219981312335893 for ; Mon, 05 Oct 2026 10:06:21 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=peter.marko@siemens.com header.s=fm1 header.b=e/lQGxhH; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.227, mailfrom: fm-256628-2026100517061954fa2d6785000207be-9njxc1@rts-flowmailer.siemens.com) Received: by mta-64-227.siemens.flowmailer.net with ESMTPSA id 2026100517061954fa2d6785000207be for ; Mon, 05 Oct 2026 19:06:19 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=peter.marko@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=eXTGIdpAZxKNemqAAs3sh6Im5itkppblYX2knc+Gw8Q=; b=e/lQGxhHXx6PRVqDNToJmfKlkoT/ho2hilcNeiywNV2ScQP/vQCwRzSsO4KEChtBbBTn8j 1kzEQaUxt6WqaydhAruZtDb+bJnj+B9TSUtjTlEjgPTn7t2fx4lO3mhQb8g2MOIu1yInT3I0 MMoOLC8rzuGCt1boYbUryWVgJml59ABW50cCuMk/T8mdohT9zTo8u+n7U8TXX2oFWMspWq0P +i4SSyCRBdtVF3fyFnnGf26klfmMjHoG+qq5FwxGkosO7J3Mhl+KrG1RcEGf00OZLpQHRwKF umIyi/iL3zFnCJmPowZrB2UKUIrequyWODyU24MX6WjcsFYerf4/nn6g==; From: Peter Marko To: openembedded-core@lists.openembedded.org Cc: Peter Marko Subject: [scarthgap][PATCH 6/7] util-linux: patch CVE-2026-78410 Date: Mon, 5 Oct 2026 19:05:11 +0200 Message-ID: <20261005170513.632348-6-peter.marko@siemens.com> In-Reply-To: <20261005170513.632348-1-peter.marko@siemens.com> References: <20261005170513.632348-1-peter.marko@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-256628:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Mon, 05 Oct 2026 17:06:26 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247251 From: Peter Marko Pick patches referencing this CVE from 2.41.6 release. Also pick regression patch and patch implementing helper function. Signed-off-by: Peter Marko --- meta/recipes-core/util-linux/util-linux.inc | 4 + ..._open_tree-helper-for-safe-tree-open.patch | 85 +++++++++++++ .../util-linux/CVE-2026-78410-01.patch | 94 ++++++++++++++ .../util-linux/CVE-2026-78410-02.patch | 96 +++++++++++++++ .../util-linux/CVE-2026-78410-03.patch | 115 ++++++++++++++++++ 5 files changed, 394 insertions(+) create mode 100644 meta/recipes-core/util-linux/util-linux/0001-libmount-add-mnt_open_tree-helper-for-safe-tree-open.patch create mode 100644 meta/recipes-core/util-linux/util-linux/CVE-2026-78410-01.patch create mode 100644 meta/recipes-core/util-linux/util-linux/CVE-2026-78410-02.patch create mode 100644 meta/recipes-core/util-linux/util-linux/CVE-2026-78410-03.patch diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc index 2eb9251a704..10803e38938 100644 --- a/meta/recipes-core/util-linux/util-linux.inc +++ b/meta/recipes-core/util-linux/util-linux.inc @@ -58,6 +58,10 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin file://CVE-2026-53612.patch \ file://CVE-2024-28085-0003.patch \ file://CVE-2026-78408.patch \ + file://0001-libmount-add-mnt_open_tree-helper-for-safe-tree-open.patch \ + file://CVE-2026-78410-01.patch \ + file://CVE-2026-78410-02.patch \ + file://CVE-2026-78410-03.patch \ " SRC_URI[sha256sum] = "7b6605e48d1a49f43cc4b4cfc59f313d0dd5402fa40b96810bd572e167dfed0f" diff --git a/meta/recipes-core/util-linux/util-linux/0001-libmount-add-mnt_open_tree-helper-for-safe-tree-open.patch b/meta/recipes-core/util-linux/util-linux/0001-libmount-add-mnt_open_tree-helper-for-safe-tree-open.patch new file mode 100644 index 00000000000..efe68cc17c8 --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/0001-libmount-add-mnt_open_tree-helper-for-safe-tree-open.patch @@ -0,0 +1,85 @@ +From 71ff1c94be2fd2577bf600accb5c6ad2782276ef Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 20 Jul 2026 14:40:16 +0200 +Subject: [PATCH] libmount: add mnt_open_tree() helper for safe tree opening + +Add mnt_open_tree() that combines openat2() path pinning with +open_tree() into a single call. When resolve flags are non-zero, +the path is first pinned with ul_openat_resolve(), then cloned +with open_tree(AT_EMPTY_PATH). When resolve is zero, open_tree() +is called directly. + +This consolidates the openat2+open_tree pattern used for symlink +protection in restricted mount operations. + +Signed-off-by: Karel Zak +(cherry picked from commit 37afc15d9e5a0accea94eb067b151e21f8494880) +(cherry picked from commit 90a1f3b5b134b775dd30a46155064731ba40c519) + +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/71ff1c94be2fd2577bf600accb5c6ad2782276ef] +Signed-off-by: Peter Marko +--- + libmount/src/mountP.h | 2 ++ + libmount/src/utils.c | 29 +++++++++++++++++++++++++++++ + 2 files changed, 31 insertions(+) + +diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h +index 97d0bf8fa..9d022d14e 100644 +--- a/libmount/src/mountP.h ++++ b/libmount/src/mountP.h +@@ -687,6 +687,8 @@ static inline struct libmnt_sysapi *mnt_context_get_sysapi(struct libmnt_context + { + return mnt_context_get_hookset_data(cxt, &hookset_mount); + } ++int mnt_open_tree(int dirfd, const char *path, unsigned long flags, ++ unsigned long long resolve); + #endif + + #endif /* _LIBMOUNT_PRIVATE_H */ +diff --git a/libmount/src/utils.c b/libmount/src/utils.c +index 4c90c951b..e4301689e 100644 +--- a/libmount/src/utils.c ++++ b/libmount/src/utils.c +@@ -24,6 +24,7 @@ + #include "strutils.h" + #include "pathnames.h" + #include "mountP.h" ++#include "fileutils.h" + #include "mangle.h" + #include "canonicalize.h" + #include "env.h" +@@ -1286,6 +1287,34 @@ done: + return 1; + } + ++#ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT ++/* ++ * Open a mount tree, optionally pinning the path with openat2() first. ++ * ++ * When @resolve is non-zero, the path is resolved with openat2() using the ++ * given resolve flags, then the tree is opened with open_tree(AT_EMPTY_PATH). ++ * When @resolve is zero, open_tree() is called directly with the path. ++ */ ++int mnt_open_tree(int dirfd, const char *path, unsigned long flags, ++ unsigned long long resolve) ++{ ++ if (resolve) { ++ int pin_fd, fd; ++ ++ pin_fd = ul_openat_resolve(dirfd, path, ++ O_PATH | O_CLOEXEC, 0, resolve); ++ if (pin_fd < 0) ++ return pin_fd; ++ ++ fd = open_tree(pin_fd, "", flags | AT_EMPTY_PATH); ++ close(pin_fd); ++ return fd; ++ } ++ ++ return open_tree(dirfd, path, flags); ++} ++#endif /* USE_LIBMOUNT_MOUNTFD_SUPPORT */ ++ + #ifdef TEST_PROGRAM + static int test_match_fstype(struct libmnt_test *ts, int argc, char *argv[]) + { diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2026-78410-01.patch b/meta/recipes-core/util-linux/util-linux/CVE-2026-78410-01.patch new file mode 100644 index 00000000000..50dadbbe884 --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/CVE-2026-78410-01.patch @@ -0,0 +1,94 @@ +From b21f4cee55f723b045920dad5ce48a659d34cac8 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Thu, 9 Jul 2026 16:10:08 +0200 +Subject: [PATCH] libmount: restrict source path canonicalization for non-root + users [CVE-2026-78410] + +In restricted (suid, non-root) mode, mnt_context_prepare_srcpath() +calls realpath() as euid=0 to canonicalize the source path. This +follows symlinks through directories where the real user has write +access (e.g. /home/user/), allowing redirection to arbitrary files. + +Only canonicalize /dev/ paths (e.g. /dev/cdrom -> /dev/sr0) and +verify the result stays within /dev/. For non-/dev/ paths (e.g. +disk images in user-writable directories), keep the original fstab +path. Symlink protection for these paths is handled at open time +by RESOLVE_NO_SYMLINKS in ul_open_no_symlinks(). + +This is a follow-up to commits: + 5e390467b ("loopdev: add LOOPDEV_FL_NOFOLLOW to prevent symlink attacks") + d07aad41e ("libmount: ignore X-mount.nocanonicalize for restricted users") + +Signed-off-by: Karel Zak +(cherry picked from commit e554245ccc165fcdd4b8ba68bf2994ee14b98607) +(cherry picked from commit 6051830a27a852fed92ebd8493e57aa3d5d9cf18) + +CVE: CVE-2026-78410 +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/b21f4cee55f723b045920dad5ce48a659d34cac8] +Backport notes: +- Left out hunk from manual not yet present in 2.39.3 +- Adapted to use the startswith() helper available in util-linux 2.39.3. +Signed-off-by: Peter Marko +--- + libmount/src/context.c | 17 ++++++++++++++++- + sys-utils/mount.8.adoc | 10 ++++++++-- + 2 files changed, 24 insertions(+), 3 deletions(-) + +diff --git a/libmount/src/context.c b/libmount/src/context.c +index 00fd099c9..8418b2d64 100644 +--- a/libmount/src/context.c ++++ b/libmount/src/context.c +@@ -1888,7 +1888,22 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt) + /* + * Source is PATH (canonicalize) + */ +- path = mnt_resolve_path(src, cache); ++ if (mnt_context_is_restricted(cxt)) { ++ /* In restricted mode, only canonicalize /dev/ ++ * paths (e.g. /dev/cdrom -> /dev/sr0) and verify ++ * the result stays in /dev/. For non-/dev/ paths ++ * (e.g. disk images in user dirs), keep the ++ * original fstab path -- symlink protection is ++ * handled at open time by RESOLVE_NO_SYMLINKS. ++ */ ++ if (startswith(src, "/dev/")) { ++ path = mnt_resolve_path(src, cache); ++ if (path && !startswith(path, "/dev/")) ++ path = NULL; ++ } ++ } else ++ path = mnt_resolve_path(src, cache); ++ + if (path && strcmp(path, src) != 0) + rc = mnt_fs_set_source(cxt->fs, path); + } +diff --git a/sys-utils/mount.8.adoc b/sys-utils/mount.8.adoc +index 2acf2e15c..add2914ae 100644 +--- a/sys-utils/mount.8.adoc ++++ b/sys-utils/mount.8.adoc +@@ -186,6 +186,10 @@ For more details, see *fstab*(5). Only the user that mounted a filesystem can un + + The *user* mount option is accepted if no username is specified. If used in the format *user=someone*, the option is silently ignored and visible only for external mount helpers (/sbin/mount.) for compatibility with some network filesystems. + ++For mount source paths, *mount*(8) only canonicalizes (resolves symlinks) paths starting with _/dev/_ for unprivileged users and verifies the result stays within _/dev/_. Source paths outside _/dev/_ (e.g. disk images in user-writable directories) are kept as-is from _fstab_. ++ ++Filesystem type auto-detection for unprivileged users relies exclusively on *udev* metadata rather than direct device probing; this means file images that are not registered with udev require an explicit filesystem type in _fstab_. ++ + === Bind mount operation + + Remount part of the file hierarchy somewhere else. The call is: +@@ -426,10 +430,12 @@ The argument following the *-t* is used to indicate the filesystem type. The fil + + + The programs *mount* and *umount*(8) support filesystem subtypes. The subtype is defined by a '.subtype' suffix. For example 'fuse.sshfs'. It's recommended to use subtype notation rather than add any prefix to the mount source (for example 'sshfs#example.com' is deprecated). + + +-If no *-t* option is given, or if the *auto* type is specified, *mount* will try to guess the desired type. *mount* uses the *libblkid*(3) library for guessing the filesystem type; if that does not turn up anything that looks familiar, *mount* will try to read the file _/etc/filesystems_, or, if that does not exist, _/proc/filesystems_. All of the filesystem types listed there will be tried, except for those that are labeled "nodev" (e.g. _devpts_, _proc_ and _nfs_). If _/etc/filesystems_ ends in a line with a single {asterisk}, mount will read _/proc/filesystems_ afterwards. While trying, all filesystem types will be mounted with the mount option *silent*. ++If no *-t* option is given, or if the *auto* type is specified, *mount* will try to guess the desired type. The filesystem type is determined using *udev* metadata first, then by direct device probing via *libblkid*(3) for root users. If neither method identifies the type, *mount* will fall back to trying all types listed in _/etc/filesystems_, or if that file does not exist, _/proc/filesystems_. Types labeled "nodev" (e.g. _devpts_, _proc_ and _nfs_) are skipped. If _/etc/filesystems_ ends in a line with a single {asterisk}, mount will read _/proc/filesystems_ afterwards. While trying, all filesystem types will be mounted with the mount option *silent*. + //TRANSLATORS: Keep {asterisk} untranslated. + + +-The *auto* type may be useful for user-mounted floppies. Creating a file _/etc/filesystems_ can be useful to change the probe order (e.g., to try vfat before msdos or ext3 before ext2) or if you use a kernel module autoloader. ++For unprivileged (non-root) users, direct device probing via *libblkid*(3) is disabled and filesystem type detection relies exclusively on *udev* metadata. This means file images that are not registered with *udev* require an explicit filesystem type in _fstab_. +++ ++Creating a file _/etc/filesystems_ can be useful to change the probe order (e.g., to try vfat before msdos or ext3 before ext2) or if you use a kernel module autoloader. + + + More than one type may be specified in a comma-separated list, for the *-t* option as well as in an _/etc/fstab_ entry. The list of filesystem types for the *-t* option can be prefixed with *no* to specify the filesystem types on which no action should be taken. The prefix *no* has no effect when specified in an _/etc/fstab_ entry. + + diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2026-78410-02.patch b/meta/recipes-core/util-linux/util-linux/CVE-2026-78410-02.patch new file mode 100644 index 00000000000..27669463630 --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/CVE-2026-78410-02.patch @@ -0,0 +1,96 @@ +From 9fcb98bf08d9119d07ba3a3c709b1a85e4a1bbcb Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 20 Jul 2026 14:59:21 +0200 +Subject: [PATCH] libmount: pin source path with openat2() for restricted users + [CVE-2026-78410] + +In restricted (non-root) mode, mnt_context_open_tree() resolves the +source path via open_tree(AT_FDCWD, path, ...) which follows symlinks +in intermediate path components. A local attacker who can replace the +fstab-authorized bind source path or an ancestor with a symlink can +redirect the privileged mount operation to an arbitrary directory. + +When combined with X-mount.owner/group/mode the post-mount hook +applies root-privileged chown/chmod to the bind source inode, giving +a local ownership/permission modification primitive on paths not +authorized by fstab. + +Fix by using mnt_open_tree() with RESOLVE_NO_SYMLINKS in restricted +mode. Also fix hook_idmap.c fallback open_tree() call to use the +same pattern. Unrestricted (root) callers pass resolve=0 and get +the direct open_tree() path. + +Signed-off-by: Karel Zak +(cherry picked from commit fb8e2653553ce2ecd077a294d53a1422d7c6dbc0) +(cherry picked from commit 9a8d0d60c55d3a55f89f6f75a17bae31bc5ee1c6) + +CVE: CVE-2026-78410 +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/9fcb98bf08d9119d07ba3a3c709b1a85e4a1bbcb] +Backport notes: +- In 2.39.3, source tree opening is in hook_mount.c:open_mount_tree(), + not context.c:mnt_context_open_tree(). Apply that security hunk there. +- Add fileutils.h to hook_idmap.c for the RESOLVE_NO_SYMLINKS definition; + without it, compilation fails when mountfd support is enabled. +- Replace the duplicate fileutils.h include in utils.c with + mount-api-utils.h for the open_tree() declaration and syscall fallback. + The original fileutils.h include further down is retained. +Signed-off-by: Peter Marko +--- + libmount/src/hook_idmap.c | 7 +++++-- + libmount/src/hook_mount.c | 3 ++- + libmount/src/utils.c | 2 +- + 3 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/libmount/src/hook_idmap.c b/libmount/src/hook_idmap.c +index adaa9c636..97d8e0d1e 100644 +--- a/libmount/src/hook_idmap.c ++++ b/libmount/src/hook_idmap.c +@@ -25,6 +25,7 @@ + #include "strutils.h" + #include "all-io.h" + #include "namespace.h" ++#include "fileutils.h" + #include "mount-api-utils.h" + + #include "mountP.h" +@@ -330,9 +331,11 @@ static int hook_mount_post( + } + #endif + if (fd_tree < 0) +- fd_tree = open_tree(-1, target, ++ fd_tree = mnt_open_tree(AT_FDCWD, target, + OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC | +- (recursive ? AT_RECURSIVE : 0)); ++ (recursive ? AT_RECURSIVE : 0), ++ mnt_context_is_restricted(cxt) ? ++ RESOLVE_NO_SYMLINKS : 0); + if (fd_tree < 0) { + DBG(HOOK, ul_debugobj(hs, " failed to open tree")); + return -MNT_ERR_IDMAP; +diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c +index a34b2d4..f5198c6 100644 +--- a/libmount/src/hook_mount.c ++++ b/libmount/src/hook_mount.c +@@ -245,7 +245,8 @@ static int open_mount_tree(struct libmnt_context *cxt, const char *path, unsigne + DBG(HOOK, ul_debug("open_tree(path=%s%s%s)", path, + oflg & OPEN_TREE_CLONE ? " clone" : "", + oflg & AT_RECURSIVE ? " recursive" : "")); +- fd = open_tree(AT_FDCWD, path, oflg); ++ fd = mnt_open_tree(AT_FDCWD, path, oflg, ++ mnt_context_is_restricted(cxt) ? RESOLVE_NO_SYMLINKS : 0); + set_syscall_status(cxt, "open_tree", fd >= 0); + + return fd; +diff --git a/libmount/src/utils.c b/libmount/src/utils.c +index 9e2f4d53d..6c6f1aaeb 100644 +--- a/libmount/src/utils.c ++++ b/libmount/src/utils.c +@@ -24,7 +24,7 @@ + #include "strutils.h" + #include "pathnames.h" + #include "mountP.h" +-#include "fileutils.h" ++#include "mount-api-utils.h" + #include "mangle.h" + #include "canonicalize.h" + #include "env.h" diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2026-78410-03.patch b/meta/recipes-core/util-linux/util-linux/CVE-2026-78410-03.patch new file mode 100644 index 00000000000..15366a8864d --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/CVE-2026-78410-03.patch @@ -0,0 +1,115 @@ +From 233cf7321e9d0fd2cea901d0a97e565c725640ad Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Thu, 3 Sep 2026 10:01:29 +0200 +Subject: [PATCH] libmount: use USE_LIBMOUNT_MOUNTFD_SUPPORT for idmap hook + +The idmap hookset was originally guarded by HAVE_MOUNTFD_API (kernel +headers have the new mount syscalls) rather than +USE_LIBMOUNT_MOUNTFD_SUPPORT (libmount is built with mountfd support). + +This was intentional (commit 9040c0900, 2022) -- the idea was to keep +idmap working even with --disable-libmount-mountfd-support by calling +the raw open_tree() syscall directly, while using an inner #ifdef +USE_LIBMOUNT_MOUNTFD_SUPPORT to optionally reuse the sysapi fd_tree. + +This fine-grained approach broke when the CVE-2026-78410 fix replaced +the raw open_tree() call with mnt_open_tree(), which is only available +under USE_LIBMOUNT_MOUNTFD_SUPPORT. The build fails with +--disable-libmount-mountfd-support because mnt_open_tree() is +undeclared. + +Rather than maintaining two code paths for a feature that fundamentally +depends on the new mount API, gate the entire idmap hookset on +USE_LIBMOUNT_MOUNTFD_SUPPORT -- consistent with how hookset_mount is +guarded. Remove the now-redundant inner #ifdef. + +Also add a note to mount.8 that X-mount.idmap requires the new +fd-based mount API. + +Addresses: https://github.com/util-linux/util-linux/issues/4598 +Signed-off-by: Karel Zak +(cherry picked from commit e06799ac325a881a297d2ffd6fe568cacdcd00ab) + +CVE: CVE-2026-78410 +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/233cf7321e9d0fd2cea901d0a97e565c725640ad] +Signed-off-by: Peter Marko +--- + libmount/src/hook_idmap.c | 6 ++---- + libmount/src/hooks.c | 2 +- + libmount/src/version.c | 2 +- + sys-utils/mount.8.adoc | 1 + + 4 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/libmount/src/hook_idmap.c b/libmount/src/hook_idmap.c +index d4d7fbacc..94c025097 100644 +--- a/libmount/src/hook_idmap.c ++++ b/libmount/src/hook_idmap.c +@@ -34,7 +34,7 @@ + # include + #endif + +-#if defined(HAVE_MOUNTFD_API) && defined(HAVE_LINUX_MOUNT_H) ++#ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT + + typedef enum idmap_type_t { + ID_TYPE_UID, /* uidmap entry */ +@@ -319,7 +319,6 @@ static int hook_mount_post( + * Once a mount has been attached to the filesystem it can't be + * idmapped anymore. So create a new detached mount. + */ +-#ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT + { + struct libmnt_sysapi *api = mnt_context_get_sysapi(cxt); + +@@ -329,7 +328,6 @@ static int hook_mount_post( + DBG(HOOK, ul_debugobj(hs, " reuse tree FD")); + } + } +-#endif + if (fd_tree < 0) + fd_tree = mnt_open_tree(AT_FDCWD, target, + OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC | +@@ -521,4 +519,4 @@ const struct libmnt_hookset hookset_idmap = + .deinit = hookset_deinit + }; + +-#endif /* HAVE_MOUNTFD_API && HAVE_LINUX_MOUNT_H */ ++#endif /* USE_LIBMOUNT_MOUNTFD_SUPPORT */ +diff --git a/libmount/src/hooks.c b/libmount/src/hooks.c +index 23eca4efd..5ae91edd7 100644 +--- a/libmount/src/hooks.c ++++ b/libmount/src/hooks.c +@@ -46,7 +46,7 @@ static const struct libmnt_hookset *hooksets[] = + &hookset_mount, + #endif + &hookset_mount_legacy, +-#if defined(HAVE_MOUNTFD_API) && defined(HAVE_LINUX_MOUNT_H) ++#ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT + &hookset_idmap, + #endif + &hookset_owner +diff --git a/libmount/src/version.c b/libmount/src/version.c +index 3b61618b5..5c70ebf8a 100644 +--- a/libmount/src/version.c ++++ b/libmount/src/version.c +@@ -38,7 +38,7 @@ static const char *lib_features[] = { + #ifdef USE_LIBMOUNT_SUPPORT_NAMESPACES + "namespaces", + #endif +-#if defined(HAVE_MOUNTFD_API) && defined(HAVE_LINUX_MOUNT_H) ++#ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT + "idmapping", + #endif + #ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT +diff --git a/sys-utils/mount.8.adoc b/sys-utils/mount.8.adoc +index add2914ae..4bc1bb0f9 100644 +--- a/sys-utils/mount.8.adoc ++++ b/sys-utils/mount.8.adoc +@@ -724,6 +724,7 @@ Set _mountpoint_'s mode after mounting. + + *X-mount.idmap*=__id-type__:__id-mount__:__id-host__:__id-range__ [__id-type__:__id-mount__:__id-host__:__id-range__], *X-mount.idmap*=__file__:: + Use this option to create an idmapped mount. ++This feature requires the new file-descriptor-based mount API (available since Linux 5.2). + An idmapped mount allows to change ownership of all files located under a mount according to the ID-mapping associated with a user namespace. + The ownership change is tied to the lifetime and localized to the relevant mount. + The relevant ID-mapping can be specified in two ways: From patchwork Mon Oct 5 17:05:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Marko X-Patchwork-Id: 100014 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E647CA5FF0 for ; Mon, 5 Oct 2026 17:06:36 +0000 (UTC) Received: from mta-64-225.siemens.flowmailer.net (mta-64-225.siemens.flowmailer.net [185.136.64.225]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24943.1791219988715356082 for ; Mon, 05 Oct 2026 10:06:29 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=peter.marko@siemens.com header.s=fm1 header.b=O02HbH+p; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-256628-2026100517062729131ae4f1000207fc-8bh2xw@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 2026100517062729131ae4f1000207fc for ; Mon, 05 Oct 2026 19:06:27 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=peter.marko@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=dgLowGhjnYYDGM8Cj+NYQgHMc11B2J3rsiFhl3H/KDA=; b=O02HbH+pP80sdxSnU8vjVjXaYttuJAzXjEyc4nvEhrSEnlpLq5xuXFDzUGBo74Z1llZvIo if5XbdVKEyfa3tHYwtMjz6sWOAGOsIoQgRaJp9rI/uWff5YEaPITgUqiyQw36d4z8bS2vp+7 0EA8421vF9AiGkosdZqFL8R6XAif9quDnw/Bqc7gLOEqsBK83CfJSC4ci/7A6tdHBzO4YYYt ApP2FzrZUPL3SstaBTV5ajsOThwN51KSjlIXHfla5BHGuCs68Q46BgHKEDFO7/4AZKBTJ4aK denVM0QWBaGYL6qqtJp3pcKvkCT31kI+DiDmTf3B07C1BhYxAWXqZG4A==; From: Peter Marko To: openembedded-core@lists.openembedded.org Cc: Peter Marko Subject: [scarthgap][PATCH 7/7] util-linux: patch CVE-2026-76642 Date: Mon, 5 Oct 2026 19:05:12 +0200 Message-ID: <20261005170513.632348-7-peter.marko@siemens.com> In-Reply-To: <20261005170513.632348-1-peter.marko@siemens.com> References: <20261005170513.632348-1-peter.marko@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-256628:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Mon, 05 Oct 2026 17:06:36 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247252 From: Peter Marko Pick patch referencing this CVE from 2.41.6 release. Signed-off-by: Peter Marko --- meta/recipes-core/util-linux/util-linux.inc | 1 + .../util-linux/CVE-2026-76642.patch | 136 ++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 meta/recipes-core/util-linux/util-linux/CVE-2026-76642.patch diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc index 10803e38938..fdc8c62f6e5 100644 --- a/meta/recipes-core/util-linux/util-linux.inc +++ b/meta/recipes-core/util-linux/util-linux.inc @@ -62,6 +62,7 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin file://CVE-2026-78410-01.patch \ file://CVE-2026-78410-02.patch \ file://CVE-2026-78410-03.patch \ + file://CVE-2026-76642.patch \ " SRC_URI[sha256sum] = "7b6605e48d1a49f43cc4b4cfc59f313d0dd5402fa40b96810bd572e167dfed0f" diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2026-76642.patch b/meta/recipes-core/util-linux/util-linux/CVE-2026-76642.patch new file mode 100644 index 00000000000..b5d811770a3 --- /dev/null +++ b/meta/recipes-core/util-linux/util-linux/CVE-2026-76642.patch @@ -0,0 +1,136 @@ +From a15c00a9e545aa8b9cf6ec0f888ff6c7b3eaeedc Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 28 Jul 2026 11:40:25 +0200 +Subject: [PATCH] libmount: skip post-mount hooks after failed mount helper + [CVE-2026-76642] + +When an external mount. helper exits nonzero, exec_helper() +stores the failure in helper_status but returns zero (meaning the +fork/exec/wait infrastructure succeeded). This zero propagates as +the mount result, causing MNT_STAGE_MOUNT_POST and MNT_STAGE_POST +hooks to execute as if the mount had succeeded. + +This allows privileged post-mount operations on the pre-existing +target filesystem: + + - X-mount.idmap clones and idmaps the underlying target, creating + an overmount that inherits suid/exec from the root filesystem + (ignoring nosuid/nodev/noexec from fstab) + + - X-mount.owner/group/mode changes the physical target inode + ownership and permissions even though no mount was created + +Gate both MNT_STAGE_MOUNT_POST in mnt_context_do_mount() and +MNT_STAGE_POST in mnt_context_mount() on is_success_status(), which +already correctly distinguishes helper exit status from process +execution status. This is a centralized fix -- individual hooks do +not need their own guards. + +Audit of all hooks registered at these stages: + + MNT_STAGE_MOUNT_POST: + - hook_mount.c (attach, propagation, vfsflags): already skip when + helper executed (commit f94a7760) + - hook_idmap.c: would clone+idmap pre-existing target -- now blocked + - hook_subdir.c: deinit calls tmptgt_cleanup() -- safe + - hook_mount_legacy.c (propagation, bindremount): no resources to leak + - hook_loopdev.c: deinit fixed to call delete_loopdev() when the + cleanup hook is skipped (was only free(), leaking fd and device) + - hook_veritydev.c: deinit calls delete_veritydev() -- safe + + MNT_STAGE_POST: + - hook_owner.c: would chown/chmod target -- now blocked; deinit + only frees uid/gid/mode struct, no resources to leak + +Signed-off-by: Karel Zak +(cherry picked from commit f57cea130839c0af8dc0525274267ae4cfd66bbf) +(cherry picked from commit 1d14676ea70003e9f5b2a6a76af0cadb1190411a) + +CVE: CVE-2026-76642 +Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/a15c00a9e545aa8b9cf6ec0f888ff6c7b3eaeedc] +Signed-off-by: Peter Marko +--- + libmount/src/context_mount.c | 23 ++++++++++++++++++++--- + libmount/src/hook_loopdev.c | 13 +++++++++++-- + 2 files changed, 31 insertions(+), 5 deletions(-) + +diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c +index 77435684b..80c45beeb 100644 +--- a/libmount/src/context_mount.c ++++ b/libmount/src/context_mount.c +@@ -574,6 +574,22 @@ static int is_success_status(struct libmnt_context *cxt) + return 0; + } + ++/* Check if the mount stage explicitly failed (helper or syscall returned ++ * an error). Unlike is_success_status(), this treats "nothing happened" ++ * as not-failed -- the MOUNT stage may be a no-op for operations like ++ * bind/move with the new mount API where open_tree() runs in PREP and ++ * move_mount() is deferred to MOUNT_POST. */ ++static int is_mount_stage_failed(struct libmnt_context *cxt) ++{ ++ if (mnt_context_helper_executed(cxt)) ++ return mnt_context_get_helper_status(cxt) != 0; ++ ++ if (mnt_context_syscall_called(cxt)) ++ return mnt_context_get_status(cxt) != 1; ++ ++ return 0; ++} ++ + /* try mount(2) for all items in comma separated list of the filesystem @types */ + static int do_mount_by_types(struct libmnt_context *cxt, const char *types) + { +@@ -874,8 +890,9 @@ int mnt_context_do_mount(struct libmnt_context *cxt) + } else + res = do_mount_by_pattern(cxt, cxt->fstype_pattern); + +- /* after mount stage */ +- if (res == 0) { ++ /* after mount stage -- the post-mount hooks are commit-path only, ++ * skip them if the mount helper or syscall has failed */ ++ if (res == 0 && !is_mount_stage_failed(cxt)) { + rc = mnt_context_call_hooks(cxt, MNT_STAGE_MOUNT_POST); + if (rc) + return rc; +@@ -1058,7 +1075,7 @@ again: + } + } + +- if (rc == 0) ++ if (rc == 0 && !is_mount_stage_failed(cxt)) + rc = mnt_context_call_hooks(cxt, MNT_STAGE_POST); + + mnt_context_deinit_hooksets(cxt); +diff --git a/libmount/src/hook_loopdev.c b/libmount/src/hook_loopdev.c +index 34351116c..af9a52227 100644 +--- a/libmount/src/hook_loopdev.c ++++ b/libmount/src/hook_loopdev.c +@@ -23,6 +23,8 @@ struct hook_data { + int loopdev_fd; + }; + ++static int delete_loopdev(struct libmnt_context *cxt, struct hook_data *hd); ++ + /* de-initiallize this module */ + static int hookset_deinit(struct libmnt_context *cxt, const struct libmnt_hookset *hs) + { +@@ -30,9 +32,16 @@ static int hookset_deinit(struct libmnt_context *cxt, const struct libmnt_hookse + + DBG(HOOK, ul_debugobj(hs, "deinit '%s'", hs->name)); + +- /* remove all our hooks */ ++ /* remove all our hooks and free hook data */ + while (mnt_context_remove_hook(cxt, hs, 0, &data) == 0) { +- free(data); ++ if (data) { ++ struct hook_data *hd = (struct hook_data *) data; ++ ++ /* cleanup after skipped MOUNT_POST hook */ ++ if (hd->loopdev_fd > -1) ++ delete_loopdev(cxt, hd); ++ free(hd); ++ } + data = NULL; + } +