mirror of
https://gitlab.com/buildroot.org/buildroot.git
synced 2026-09-10 00:04:06 -09:00
- 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>
82 lines
2.7 KiB
Diff
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 =
|