Skip to content

Commit 41bec98

Browse files
[AutoPR- Security] Patch util-linux for CVE-2026-3184, CVE-2026-27456 [MEDIUM] (#16509)
1 parent 9bc7893 commit 41bec98

7 files changed

Lines changed: 196 additions & 19 deletions

File tree

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
From f1513f7b7b0e218671e60f66ad139d6f081f69df Mon Sep 17 00:00:00 2001
2+
From: Karel Zak <kzak@redhat.com>
3+
Date: Thu, 19 Feb 2026 13:59:46 +0100
4+
Subject: [PATCH] loopdev: add LOOPDEV_FL_NOFOLLOW to prevent symlink attacks
5+
6+
Add a new LOOPDEV_FL_NOFOLLOW flag for loop device context that
7+
prevents symlink following in both path canonicalization and file open.
8+
9+
When set:
10+
- loopcxt_set_backing_file() uses strdup() instead of
11+
ul_canonicalize_path() (which calls realpath() and follows symlinks)
12+
- loopcxt_setup_device() adds O_NOFOLLOW to open() flags
13+
14+
The flag is set for non-root (restricted) mount operations in
15+
libmount's loop device hook. This prevents a TOCTOU race condition
16+
where an attacker could replace the backing file (specified in
17+
/etc/fstab) with a symlink to an arbitrary root-owned file between
18+
path resolution and open().
19+
20+
Vulnerable Code Flow:
21+
22+
mount /mnt/point (non-root, SUID)
23+
mount.c: sanitize_paths() on user args (mountpoint only)
24+
mnt_context_mount()
25+
mnt_context_prepare_mount()
26+
mnt_context_apply_fstab() <-- source path from fstab
27+
hooks run at MNT_STAGE_PREP_SOURCE
28+
hook_loopdev.c: setup_loopdev()
29+
backing_file = fstab source path ("/home/user/disk.img")
30+
loopcxt_set_backing_file() <-- calls realpath() as ROOT
31+
ul_canonicalize_path() <-- follows symlinks!
32+
loopcxt_setup_device()
33+
open(lc->filename, O_RDWR|O_CLOEXEC) <-- no O_NOFOLLOW
34+
35+
Two vulnerabilities in the path:
36+
37+
1) loopcxt_set_backing_file() calls ul_canonicalize_path() which uses
38+
realpath() -- this follows symlinks as euid=0. If the attacker swaps
39+
the file to a symlink before this call, lc->filename becomes the
40+
resolved target path (e.g., /root/secret.img).
41+
42+
2) loopcxt_setup_device() opens lc->filename without O_NOFOLLOW. Even
43+
if canonicalization happened correctly, the file can be swapped to a
44+
symlink between canonicalize and open.
45+
46+
Addresses: https://github.com/util-linux/util-linux/security/advisories/GHSA-qq4x-vfq4-9h9g
47+
Signed-off-by: Karel Zak <kzak@redhat.com>
48+
(cherry picked from commit 5e390467b26a3cf3fecc04e1a0d482dff3162fc4)
49+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
50+
Upstream-reference: https://github.com/util-linux/util-linux/commit/f55f9906b4f6eeb2b4a4120317df9de935253c10.patch
51+
---
52+
include/loopdev.h | 3 ++-
53+
lib/loopdev.c | 7 ++++++-
54+
libmount/src/hook_loopdev.c | 3 ++-
55+
3 files changed, 10 insertions(+), 3 deletions(-)
56+
57+
diff --git a/include/loopdev.h b/include/loopdev.h
58+
index d10bf7f..0f85dd2 100644
59+
--- a/include/loopdev.h
60+
+++ b/include/loopdev.h
61+
@@ -139,7 +139,8 @@ enum {
62+
LOOPDEV_FL_NOIOCTL = (1 << 6),
63+
LOOPDEV_FL_DEVSUBDIR = (1 << 7),
64+
LOOPDEV_FL_CONTROL = (1 << 8), /* system with /dev/loop-control */
65+
- LOOPDEV_FL_SIZELIMIT = (1 << 9)
66+
+ LOOPDEV_FL_SIZELIMIT = (1 << 9),
67+
+ LOOPDEV_FL_NOFOLLOW = (1 << 10) /* O_NOFOLLOW, don't follow symlinks */
68+
};
69+
70+
/*
71+
diff --git a/lib/loopdev.c b/lib/loopdev.c
72+
index c72fb2c..28fb489 100644
73+
--- a/lib/loopdev.c
74+
+++ b/lib/loopdev.c
75+
@@ -1267,7 +1267,10 @@ int loopcxt_set_backing_file(struct loopdev_cxt *lc, const char *filename)
76+
if (!lc)
77+
return -EINVAL;
78+
79+
- lc->filename = canonicalize_path(filename);
80+
+ if (lc->flags & LOOPDEV_FL_NOFOLLOW)
81+
+ lc->filename = strdup(filename);
82+
+ else
83+
+ lc->filename = canonicalize_path(filename);
84+
if (!lc->filename)
85+
return -errno;
86+
87+
@@ -1408,6 +1411,8 @@ int loopcxt_setup_device(struct loopdev_cxt *lc)
88+
89+
if (lc->config.info.lo_flags & LO_FLAGS_DIRECT_IO)
90+
flags |= O_DIRECT;
91+
+ if (lc->flags & LOOPDEV_FL_NOFOLLOW)
92+
+ flags |= O_NOFOLLOW;
93+
94+
if ((file_fd = open(lc->filename, mode | flags)) < 0) {
95+
if (mode != O_RDONLY && (errno == EROFS || errno == EACCES))
96+
diff --git a/libmount/src/hook_loopdev.c b/libmount/src/hook_loopdev.c
97+
index 597b933..4df1915 100644
98+
--- a/libmount/src/hook_loopdev.c
99+
+++ b/libmount/src/hook_loopdev.c
100+
@@ -272,7 +272,8 @@ static int setup_loopdev(struct libmnt_context *cxt,
101+
}
102+
103+
DBG(LOOP, ul_debugobj(cxt, "not found; create a new loop device"));
104+
- rc = loopcxt_init(&lc, 0);
105+
+ rc = loopcxt_init(&lc,
106+
+ mnt_context_is_restricted(cxt) ? LOOPDEV_FL_NOFOLLOW : 0);
107+
if (rc)
108+
goto done_no_deinit;
109+
if (mnt_opt_has_value(loopopt)) {
110+
--
111+
2.45.4
112+
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
From 4c05c5b87f37d241ca1086bbfe761ca7ad278363 Mon Sep 17 00:00:00 2001
2+
From: Karel Zak <kzak@redhat.com>
3+
Date: Thu, 19 Feb 2026 12:20:28 +0100
4+
Subject: [PATCH] login: use original FQDN for PAM_RHOST
5+
6+
When login -h <remotehost> is invoked, init_remote_info() strips the
7+
local domain suffix from the hostname (FQDN to short name) before
8+
storing it in cxt->hostname. This truncated value is then used for
9+
PAM_RHOST, which can bypass pam_access host deny rules that match on
10+
the FQDN.
11+
12+
Preserve the original -h hostname in a new cmd_hostname field and use
13+
it for PAM_RHOST, while keeping the truncated hostname for utmp/wtmp
14+
and logging unchanged.
15+
16+
Note, the real-world impact is low -- login -h is only used by legacy
17+
telnet/rlogin daemons, and exploitation requires FQDN-specific
18+
pam_access rules on a system still using these obsolete services.
19+
20+
Reported-by: Asim Viladi Oglu Manizada <manizada@pm.me>
21+
Signed-off-by: Karel Zak <kzak@redhat.com>
22+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
23+
Upstream-reference: https://github.com/util-linux/util-linux/commit/8b29aeb081e297e48c4c1ac53d88ae07e1331984.patch
24+
---
25+
login-utils/login.c | 5 ++++-
26+
1 file changed, 4 insertions(+), 1 deletion(-)
27+
28+
diff --git a/login-utils/login.c b/login-utils/login.c
29+
index c8544f6..380d676 100644
30+
--- a/login-utils/login.c
31+
+++ b/login-utils/login.c
32+
@@ -128,6 +128,7 @@ struct login_context {
33+
char *thishost; /* this machine */
34+
char *thisdomain; /* this machine's domain */
35+
char *hostname; /* remote machine */
36+
+ char *cmd_hostname; /* remote machine as specified on command line */
37+
char hostaddress[16]; /* remote address */
38+
39+
pid_t pid;
40+
@@ -902,7 +903,7 @@ static pam_handle_t *init_loginpam(struct login_context *cxt)
41+
42+
/* hostname & tty are either set to NULL or their correct values,
43+
* depending on how much we know. */
44+
- rc = pam_set_item(pamh, PAM_RHOST, cxt->hostname);
45+
+ rc = pam_set_item(pamh, PAM_RHOST, cxt->cmd_hostname);
46+
if (is_pam_failure(rc))
47+
loginpam_err(pamh, rc);
48+
49+
@@ -1239,6 +1240,8 @@ static void init_remote_info(struct login_context *cxt, char *remotehost)
50+
51+
get_thishost(cxt, &domain);
52+
53+
+ cxt->cmd_hostname = xstrdup(remotehost);
54+
+
55+
if (domain && (p = strchr(remotehost, '.')) &&
56+
strcasecmp(p + 1, domain) == 0)
57+
*p = '\0';
58+
--
59+
2.45.4
60+

SPECS/util-linux/util-linux.spec

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Summary: Utilities for file systems, consoles, partitions, and messages
66
Name: util-linux
77
Version: 2.40.2
8-
Release: 3%{?dist}
8+
Release: 4%{?dist}
99
License: GPLv2+
1010
Vendor: Microsoft Corporation
1111
Distribution: Azure Linux
@@ -17,6 +17,8 @@ Source2: runuser-l
1717
Source3: su
1818
Source4: su-l
1919
Patch0: CVE-2025-14104.patch
20+
Patch1: CVE-2026-27456.patch
21+
Patch2: CVE-2026-3184.patch
2022
BuildRequires: audit-devel
2123
BuildRequires: libcap-ng-devel
2224
BuildRequires: libselinux-devel
@@ -172,6 +174,9 @@ rm -rf %{buildroot}/lib/systemd/system
172174
%{_mandir}/man3/*
173175

174176
%changelog
177+
* Wed Apr 08 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 2.40.2-4
178+
- Patch for CVE-2026-3184, CVE-2026-27456
179+
175180
* Tue Dec 30 2025 Sandeep Karambelkar <skarambelkar@microsoft.com> - 2.40.2-3
176181
- Compiled with python
177182
- Added the package python3-libmount

toolkit/resources/manifests/package/pkggen_core_aarch64.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ make-4.4.1-2.azl3.aarch64.rpm
7070
patch-2.7.6-9.azl3.aarch64.rpm
7171
libcap-ng-0.8.4-1.azl3.aarch64.rpm
7272
libcap-ng-devel-0.8.4-1.azl3.aarch64.rpm
73-
util-linux-2.40.2-3.azl3.aarch64.rpm
74-
util-linux-devel-2.40.2-3.azl3.aarch64.rpm
75-
util-linux-libs-2.40.2-3.azl3.aarch64.rpm
73+
util-linux-2.40.2-4.azl3.aarch64.rpm
74+
util-linux-devel-2.40.2-4.azl3.aarch64.rpm
75+
util-linux-libs-2.40.2-4.azl3.aarch64.rpm
7676
tar-1.35-2.azl3.aarch64.rpm
7777
xz-5.4.4-3.azl3.aarch64.rpm
7878
xz-devel-5.4.4-3.azl3.aarch64.rpm

toolkit/resources/manifests/package/pkggen_core_x86_64.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ make-4.4.1-2.azl3.x86_64.rpm
7070
patch-2.7.6-9.azl3.x86_64.rpm
7171
libcap-ng-0.8.4-1.azl3.x86_64.rpm
7272
libcap-ng-devel-0.8.4-1.azl3.x86_64.rpm
73-
util-linux-2.40.2-3.azl3.x86_64.rpm
74-
util-linux-devel-2.40.2-3.azl3.x86_64.rpm
75-
util-linux-libs-2.40.2-3.azl3.x86_64.rpm
73+
util-linux-2.40.2-4.azl3.x86_64.rpm
74+
util-linux-devel-2.40.2-4.azl3.x86_64.rpm
75+
util-linux-libs-2.40.2-4.azl3.x86_64.rpm
7676
tar-1.35-2.azl3.x86_64.rpm
7777
xz-5.4.4-3.azl3.x86_64.rpm
7878
xz-devel-5.4.4-3.azl3.x86_64.rpm

toolkit/resources/manifests/package/toolchain_aarch64.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ python3-flit-core-3.9.0-1.azl3.noarch.rpm
542542
python3-gpg-1.23.2-2.azl3.aarch64.rpm
543543
python3-jinja2-3.1.2-3.azl3.noarch.rpm
544544
python3-libcap-ng-0.8.4-1.azl3.aarch64.rpm
545-
python3-libmount-2.40.2-3.azl3.aarch64.rpm
545+
python3-libmount-2.40.2-4.azl3.aarch64.rpm
546546
python3-libs-3.12.9-10.azl3.aarch64.rpm
547547
python3-libxml2-2.11.5-9.azl3.aarch64.rpm
548548
python3-lxml-4.9.3-1.azl3.aarch64.rpm
@@ -599,11 +599,11 @@ texinfo-7.0.3-1.azl3.aarch64.rpm
599599
texinfo-debuginfo-7.0.3-1.azl3.aarch64.rpm
600600
unzip-6.0-22.azl3.aarch64.rpm
601601
unzip-debuginfo-6.0-22.azl3.aarch64.rpm
602-
util-linux-2.40.2-3.azl3.aarch64.rpm
603-
util-linux-debuginfo-2.40.2-3.azl3.aarch64.rpm
604-
util-linux-devel-2.40.2-3.azl3.aarch64.rpm
605-
util-linux-lang-2.40.2-3.azl3.aarch64.rpm
606-
util-linux-libs-2.40.2-3.azl3.aarch64.rpm
602+
util-linux-2.40.2-4.azl3.aarch64.rpm
603+
util-linux-debuginfo-2.40.2-4.azl3.aarch64.rpm
604+
util-linux-devel-2.40.2-4.azl3.aarch64.rpm
605+
util-linux-lang-2.40.2-4.azl3.aarch64.rpm
606+
util-linux-libs-2.40.2-4.azl3.aarch64.rpm
607607
which-2.21-8.azl3.aarch64.rpm
608608
which-debuginfo-2.21-8.azl3.aarch64.rpm
609609
xz-5.4.4-3.azl3.aarch64.rpm

toolkit/resources/manifests/package/toolchain_x86_64.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ python3-flit-core-3.9.0-1.azl3.noarch.rpm
550550
python3-gpg-1.23.2-2.azl3.x86_64.rpm
551551
python3-jinja2-3.1.2-3.azl3.noarch.rpm
552552
python3-libcap-ng-0.8.4-1.azl3.x86_64.rpm
553-
python3-libmount-2.40.2-3.azl3.x86_64.rpm
553+
python3-libmount-2.40.2-4.azl3.x86_64.rpm
554554
python3-libs-3.12.9-10.azl3.x86_64.rpm
555555
python3-libxml2-2.11.5-9.azl3.x86_64.rpm
556556
python3-lxml-4.9.3-1.azl3.x86_64.rpm
@@ -607,11 +607,11 @@ texinfo-7.0.3-1.azl3.x86_64.rpm
607607
texinfo-debuginfo-7.0.3-1.azl3.x86_64.rpm
608608
unzip-6.0-22.azl3.x86_64.rpm
609609
unzip-debuginfo-6.0-22.azl3.x86_64.rpm
610-
util-linux-2.40.2-3.azl3.x86_64.rpm
611-
util-linux-debuginfo-2.40.2-3.azl3.x86_64.rpm
612-
util-linux-devel-2.40.2-3.azl3.x86_64.rpm
613-
util-linux-lang-2.40.2-3.azl3.x86_64.rpm
614-
util-linux-libs-2.40.2-3.azl3.x86_64.rpm
610+
util-linux-2.40.2-4.azl3.x86_64.rpm
611+
util-linux-debuginfo-2.40.2-4.azl3.x86_64.rpm
612+
util-linux-devel-2.40.2-4.azl3.x86_64.rpm
613+
util-linux-lang-2.40.2-4.azl3.x86_64.rpm
614+
util-linux-libs-2.40.2-4.azl3.x86_64.rpm
615615
which-2.21-8.azl3.x86_64.rpm
616616
which-debuginfo-2.21-8.azl3.x86_64.rpm
617617
xz-5.4.4-3.azl3.x86_64.rpm

0 commit comments

Comments
 (0)