CVE-2020-16120: unprivileged overlayfs permission checking

Bug #1894980 reported by Christian Brauner
266
This bug affects 1 person
Affects Status Importance Assigned to Milestone
linux (Ubuntu)
Fix Released
Undecided
Unassigned

Bug Description

Opening this as a tracking bug for CVE-2020-16120

Hi,

while playing with shiftfs I've noticed a strange interaction with
overlay and that seems to allow reading files under an accessible
directory, even if they are not readable to the user who created the
user namespace.

While overlay would not accept a FUSE file system as upper layer, it
seems the check doesn't work when it goes through a shiftfs layer.

For the exploit purpose, I've used fuse-overlayfs only because I am
familiar with it but I'd expect any FUSE file system to behave
in the same way. The additional drop_unlink.patch patch is used only to
inhibit deleting temporary files in fuse-overlayfs.

The steps required are:

1) create a user namespace with an unprivileged user.
2) mount a FUSE file system where we have full control at M1. In
   the exploit fuse-overlayfs with a custom patch is used.
3) mount shiftfs from the FUSE mount M1 to a mountpoint M2.
4) mount overlay using /etc as lowerdir and M2 for the upperdir (and
   workdir).
5) attempt a "mv M2/shadow M2/something-else".

The shadow file that is coming from the lower layer (/etc/shadow), is
copied to the shiftfs and ultimately to the FUSE file system. The copy
would fail but that happens too late, after the FUSE file system already
received the file content. Since we have full control on the FUSE file
system, we can access the content of /etc/shadow.

For running the exploit, you need to have the fuse-overlayfs
dependencies installed (libc6-dev gcc g++ make automake autoconf pkgconf
libfuse3-dev).

It is enough to run "make" as unprivileged user and if the exploit
succeeds you get the content of the /etc/shadow file under the result/
directory.

Tested on Ubuntu 20.04 with Linux 5.4.0-42-generic.

Thanks,
Giuseppe

CVE References

Revision history for this message
Christian Brauner (cbrauner) wrote :
Revision history for this message
Christian Brauner (cbrauner) wrote :

Afaict, the bug is due to permission checking for copying up files in overlayfs that we are susceptible too because we allow unpriv overlayfs mounts.

When overlayfs does not support metacopy only copy up then overlayfs will copy up the whole file, i.e. including its contents, to the upper filesystem.

To this end overlayfs will call dentry_open() on any file from the lower filesystem in ovl_copy_up_flags(). But dentry_open() doesn't perform any permission checks and will always succeed.

After that overlayfs will copy the lower file contents into the upper filesystem and finally call ovl_set_attr() on it to change the mode and ids of the copied up file. Should ovl_set_attr() fail then the created file will have been improperly copied up, i.e. it will not accurately reflect the ownership the lower file had in the lower filesystem. An attacker can abuse this to get read access to a file on the system.

Getting ovl_set_attr() to fail can e.g. be triggered by mounting fuse-overlayfs in a new user and mount namespaces, then mounting shiftfs on top of it. Finally an overlayfs mount can be created on top of shiftfs that uses a directory or filesystem with invalid ids in the current user namespace as lower filesystem. Then a copy needs to be triggered in the overlayfs mount by e.g. renaming or moving a file in the merged directory. The initial copy up of the data of the file will succeed while the ovl_set_attr() will fail since the ids of the lower filesystem are not valid in the current user namespace. With some trickery, this can be used to leave a copied-up file with the caller's permissions lying in the workdir of the overlayfs mount. This file can now be read by the attacker.

Fixing this involves backporting

commit 56230d956739b9cb1cbde439d76227d77979a04d
Author: Miklos Szeredi <email address hidden>
Date: Tue Jun 2 22:20:26 2020 +0200

    ovl: verify permissions in ovl_path_open()

    Check permission before opening a real file.

    ovl_path_open() is used by readdir and copy-up routines.

    ovl_permission() theoretically already checked copy up permissions, but it
    doesn't hurt to re-do these checks during the actual copy-up.

    For directory reading ovl_permission() only checks access to topmost
    underlying layer. Readdir on a merged directory accesses layers below the
    topmost one as well. Permission wasn't checked for these layers.

    Note: modifying ovl_permission() to perform this check would be far more
    complex and hence more bug prone. The result is less precise permissions
    returned in access(2). If this turns out to be an issue, we can revisit
    this bug.

    Signed-off-by: Miklos Szeredi <email address hidden>

and a small number of preliminary patches since this issue has been fixed upstream.

Revision history for this message
Seth Forshee (sforshee) wrote : Re: [Bug 1894980] Re: CVE-2020-16120: unprivileged overlayfs permission checking

Attaching backports for focal. Note that I've also reverted the sauce
patch for CVE-2018-6559 as the backports make the permission checks
added in that patch redundant.

Revision history for this message
Seth Forshee (sforshee) wrote :

Also attaching a test for CVE-2018-6559 to be used to check for regressions.

Revision history for this message
Steve Beattie (sbeattie) wrote :

Hello Giuseppe et al,

Apologies for the delay in updating the status on this vulnerability. We are planning on 17:00 UTC October 13th, 2020 as a disclosure date.

Thanks again for the excellent report and your patience on this issue!

Changed in linux (Ubuntu):
status: New → Confirmed
Steve Beattie (sbeattie)
Changed in linux (Ubuntu):
status: Confirmed → Fix Released
information type: Private Security → Public Security
To post a comment you must log in.
This report contains Public Security information  
Everyone can see this security related information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.