Files
buildroot/package/util-linux/0013-CVE-2026-53614.patch
Thomas Perale 4f7f72e10a package/util-linux: backport patch CVE-2026-53614
- CVE-2026-53614
    The SUID binary /usr/bin/mount from util-linux trusts the
    environment variable LIBMOUNT_FORCE_MOUNT2 via a raw getenv() call
    in libmount/src/hook_mount.c. An unprivileged user can set
    LIBMOUNT_FORCE_MOUNT2=always to force the mount process to use the
    legacy (non-atomic) bind mount path instead of the secure new mount
    API path.

    In the legacy path, a bind mount is performed in two separate
    syscalls: first mount(src, tgt, MS_BIND) which exposes the source
    directory without security flags, then mount(tgt,
    MS_REMOUNT|MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV) which applies the
    flags. Between these two syscalls, a brief window exists where the
    bind-mounted directory is visible without nosuid/noexec protection.
    A concurrent process can execute a SUID binary from the bind target
    during this window.

For more information, see:
 - https://github.com/util-linux/util-linux/security/advisories/GHSA-67r7-8m5w-22wx
 - cc81bbcec5

Signed-off-by: Thomas Perale <thomas.perale@mind.be>
2026-07-02 21:47:38 +02:00

82 lines
2.7 KiB
Diff

From 31e37c1c7dcf25b76ccf41391fe934a75644c661 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
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.
Reported-by: Xinyao Hu <ctf_0x01@foxmail.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
(cherry picked from commit 9cbfb823500f510b34767edabd3ffd5b436987b4)
Upstream: https://github.com/util-linux/util-linux/commit/cc81bbcec598cb91f0eb8456282f33eed820ed5f
CVE: CVE-2026-53614
Signed-off-by: Thomas Perale <thomas.perale@mind.be>
---
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 374078c97f8..570ee8e01f9 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"
@@ -658,7 +659,7 @@ static int init_sysapi(struct libmnt_context *cxt,
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 cfdd7af2b2c..942e26e7770 100644
--- a/libmount/src/hook_mount_legacy.c
+++ b/libmount/src/hook_mount_legacy.c
@@ -285,6 +285,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;
@@ -294,12 +296,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 =