diff mbox series

[scarthgap,3/7] util-linux: patch CVE-2026-53612

Message ID 20261005170513.632348-3-peter.marko@siemens.com
State New
Headers show
Series [scarthgap,1/7] util-linux: patch CVE-2026-53614 | expand

Commit Message

Peter Marko Oct. 5, 2026, 5:05 p.m. UTC
From: Peter Marko <peter.marko@siemens.com>

Pick patch referencing this CVE from 2.41.5 release.

Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
 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 mbox series

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 <kzak@redhat.com>
+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 <ctf_0x01@foxmail.com>
+Signed-off-by: Karel Zak <kzak@redhat.com>
+(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 <peter.marko@siemens.com>
+---
+ 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 <sched.h>
+ 
+ #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;
+ }
+