Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Date: Mon, 4 May 2020 00:24:19 +0100
From: Piotr Krysiuk <piotras@...il.com>
To: oss-security@...ts.openwall.com
Subject: [CVE-2020-12114] Linux kernel denial of service by corrupting
 mountpoint reference counter

A race condition in fs/namespace.c in the Linux kernel allows unprivileged
local users to cause a denial of service by corrupting mountpoint reference
counter

# Affected Versions

The denial of service has been reproduced against the following Linux
kernel releases from kernel.org:
* 4.19.118 (longterm release)
* 4.14.177 (longterm release)
* 4.9.220 (longterm release)
* 4.4.220 (longterm release)

The denial of service has also been reproduced against the following
distribution kernel versions provided by current Ubuntu LTS releases:
* 5.0.0-1034-gcp (distribution kernel provided by package
"linux-image-5.0.0-1034-gcp" from Ubuntu 18.04.4 LTS)
* 4.15.0-1061-gcp (current distribution kernel provided by package
"linux-image-4.15.0-1061-gcp" from Ubuntu 16.04.6 LTS with all updates
installed)

Linux kernel releases 5.3 and newer from kernel.org are not affected.

# Root Cause

Unprivileged local user can cause kernel panic by triggering destruction of
a mountpoint that is still in use.

This is possible by exploiting a race condition to corrupt mountpoint
reference counter when simultaneously executing put_mountpoint() and
pivot_root():
* one thread increments m_count member of struct mountpoint
  [under namespace_sem, but not holding mount_lock]
    pivot_root()
* another thread simultaneously decrements the same m_count
  [under mount_lock, but not holding namespace_sem]
    put_mountpoint()
      unhash_mnt()
        umount_mnt()
          mntput_no_expire()

# Bug Fix

To fix this race condition, grab mount_lock before updating m_count in
pivot_root().
This requires swapping two lines in fs/namespace.c:
```
@@ -3142,8 +3142,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *,
new_root,
  /* make certain new is below the root */
  if (!is_path_reachable(new_mnt, new.dentry, &root))
  goto out4;
- root_mp->m_count++; /* pin it so it won't go away */
  lock_mount_hash();
+ root_mp->m_count++; /* pin it so it won't go away */
  detach_mnt(new_mnt, &parent_path);
  detach_mnt(root_mnt, &root_parent);
  if (root_mnt->mnt.mnt_flags & MNT_LOCKED) {
```

The above fix has been merged into all relevant longterm branches by
upstream Linux kernel.

The following Linux kernel releases from kernel.org incorporate the fix:
* 4.19.119 (longterm release), see commit
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v4.19.119&id=f511dc75d22e0c000fc70b54f670c2c17f5fba9a
* 4.14.178 (current longterm release), see commit
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v4.14.178&id=e21c8c03af20932c15d8b1d3bb9cbad9607a6eab
* 4.9.221 (current longterm release), see commit
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v4.9.221&id=91e997939dda1a866f23ddfb043dcd4a3ff57524
* 4.4.221 (current longterm release), see commit
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v4.4.221&id=83354adbd7a967230bd23a547c5b695567ddba2c

# Proof Of Concept

I developed a PoC that allows unprivileged local users to reliably trigger
kernel panic inside VM instances on Compute Engine of Google Cloud Platform.

The PoC has been shared privately with <security@...nel.org> and via a
private bug report with Ubuntu.

# Discoverer

Piotr Krysiuk <piotras@...il.com>

# References

CVE-2020-12114 (reserved via https://cveform.mitre.org/)

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.