FlawOpen

flawopen.com/Teardowns/cve-2023-2640-ubuntu-overlayfs-privilege-escalation

● CVE-2023-2640 · CVSS 7.8 · High
FlawOpen Security Research

CVE-2023-2640: Ubuntu OverlayFS LPE

CVE-2023-2640 is an Ubuntu OverlayFS permission-check bypass on specific kernel builds. Check your kernel flavor and install the vendor fix.

💡 Plain English Explainer (ELI5)

Think of a building with a clerk who checks whether a visitor may attach an official seal to a document. A local shortcut was meant to skip checks only for the building’s own maintenance labels. A later change routed every seal request through that shortcut, including restricted security seals. The fix restores the normal permission check for the mounted filesystem’s user namespace.

Core Concepts & Subsystem Terms

OverlayFS
A Linux union filesystem that presents files from a lower layer and writes changes to an upper layer.
Extended attribute (xattr)
Metadata attached to a filesystem object. Linux security modules and file capabilities use specific xattr namespaces.
ovl_do_setxattr()
An OverlayFS helper that writes an xattr to an upper-layer object. The affected Ubuntu wrapper used a no-permission-check VFS helper too broadly.
Copy-up
OverlayFS operation that creates an upper-layer copy of a lower-layer object when a write requires a writable copy.

Framework mappings

  • CWE reference for the weakness described in this guide: CWE-863

Root Cause Analysis

Ubuntu’s CVE record says the vulnerable configuration requires both upstream commit c914c0e27eb0 and the Ubuntu SAUCE patch “Skip permission checking for trusted.overlayfs.* xattrs.” The SAUCE patch changed OverlayFS xattr wrappers to call _noperm VFS helpers, intending to skip checks only for OverlayFS-internal trusted.overlayfs.* metadata. After the upstream wrapper change, the helper was used for other xattr operations too, so a local unprivileged user could set privileged extended attributes on mounted files and have them copied to upper files without the appropriate checks. Canonical’s fix reverts the broad no-permission path and calls vfs_setxattr() with the upper mount’s user namespace. This is an Ubuntu-kernel-specific local privilege-escalation issue; package exposure and practical impact depend on release, kernel flavor, and namespace/mount policy.

Step-by-Step Attack Flow

Step 1

Affected Ubuntu kernel configuration

The kernel must contain both c914c0e27eb0 and Ubuntu’s SAUCE patch that skips permission checks for trusted.overlayfs.* xattrs. A CVE label or upstream Linux version alone does not establish exposure.

Step 2

Local user reaches OverlayFS xattr handling

A local unprivileged user must be able to use the affected OverlayFS path under the host’s namespace and mount policy. Ubuntu documents this as a local attack.

Step 3

Permission bypass applies too broadly

The changed wrapper routed xattr updates through _noperm helpers, intended for OverlayFS-internal metadata. The upstream wrapper change meant other xattrs could also miss the appropriate permission checks.

Step 4

Privileged xattr reaches an upper object

Ubuntu states that privileged extended attributes could be set on mounted files and then copied to upper files without the required checks, potentially enabling local privilege escalation. Do not assume every kernel build or container layout is exploitable.

Source Code: Flaw vs. Secure Implementation

The affected SAUCE path called __vfs_setxattr_noperm() for all xattrs after an upstream wrapper change broadened its reach. The fix uses vfs_setxattr() with the upper mount’s user namespace so normal VFS permission checks apply. This is the focused wrapper change from Canonical’s patch, with surrounding debug logging omitted.

Source excerpt: fs/overlayfs/overlayfs.h — ovl_do_setxattr()

UNPATCHED FLAW
/* Canonical Ubuntu patch context before reverting the SAUCE change. */
static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
                                  const char *name, const void *value,
                                  size_t size, int flags)
{
    struct inode *inode = dentry->d_inode;
    int err;

    inode_lock(inode);
    err = __vfs_setxattr_noperm(&init_user_ns, dentry, name,
                                value, size, flags);
    inode_unlock(inode);
    return err;
}
HARDENED SECURE PATCH
/* Canonical Ubuntu fix: restore the permission-checking VFS wrapper. */
static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
                                  const char *name, const void *value,
                                  size_t size, int flags)
{
    int err = vfs_setxattr(ovl_upper_mnt_userns(ofs), dentry, name,
                           value, size, flags);
    return err;
}

Engineering & System Hardening Checklist

Sources