CVE-2021-41133 (C, published 2021-10-08T14:15Z)
Description: value: Flatpak is a system for building, distributing, and running sandboxed desktop applications on Linux. In versions prior to 1.10.4 and 1.12.0, Flatpak apps with direct access to AF_UNIX sockets such as those used by Wayland, Pipewire or pipewire-pulse can trick portals and other host-OS services into treating the Flatpak app as though it was an ordinary, non-sandboxed host-OS process. They can do this by manipulating the VFS using recent mount-related syscalls that are not blocked by Flatpak's denylist seccomp filter, in order to substitute a crafted `/.flatpak-info` or make that file disappear entirely. Flatpak apps that act as clients for AF_UNIX sockets such as those used by Wayland, Pipewire or pipewire-pulse can escalate the privileges that the corresponding services will believe the Flatpak app has. Note that protocols that operate entirely over the D-Bus session bus (user bus), system bus or accessibility bus are not affected by this. This is due to the use of a proxy process `xdg-dbus-proxy`, whose VFS cannot be manipulated by the Flatpak app, when interacting with these buses. Patches exist for versions 1.10.4 and 1.12.0, and as of time of publication, a patch for version 1.8.2 is being planned. There are no workarounds aside from upgrading to a patched version.
Severity: MEDIUM (CVSS v3 base score: 7.8)
Weakness: NVD-CWE-Other \u2014 Other
NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
Repository: https://github.com/flatpak/flatpak
Files changed:
common/flatpak-run.c
Commit message: run: Add an errno value to seccomp filters

At the moment, if we block a syscall we always make it fail with EPERM,
but this is risky: user-space libraries can start to use new replacements
for old syscalls at any time, and will often treat EPERM as a fatal error.
For new syscalls, we should make the syscall fail with ENOSYS, which is
indistinguishable from running on an older kernel and will cause fallback
to an older implementation, for example clone3() to clone().

In future we should probably move from EPERM to ENOSYS for some of the
syscalls we already block, but for now keep the status quo.

This is a prerequisite for fixing the vulnerability tracked as
GHSA-67h7-w3jq-vh4q.

Signed-off-by: Simon McVittie <smcv@collabora.com>


Vulnerable code:
    {SCMP_SYS (syslog)},
    {SCMP_SYS (uselib)},
    {SCMP_SYS (acct)},
    {SCMP_SYS (modify_ldt)},
    {SCMP_SYS (quotactl)},
    {SCMP_SYS (add_key)},
    {SCMP_SYS (keyctl)},
    {SCMP_SYS (request_key)},
    {SCMP_SYS (move_pages)},
    {SCMP_SYS (mbind)},
    {SCMP_SYS (get_mempolicy)},
    {SCMP_SYS (set_mempolicy)},
    {SCMP_SYS (migrate_pages)},
    {SCMP_SYS (unshare)},
    {SCMP_SYS (mount)},
    {SCMP_SYS (pivot_root)},
    {SCMP_SYS (clone), &SCMP_A1 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
    {SCMP_SYS (clone), &SCMP_A0 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
    {SCMP_SYS (ioctl), &SCMP_A1 (SCMP_CMP_MASKED_EQ, 0xFFFFFFFFu, (int) TIOCSTI)},
    {SCMP_SYS (perf_event_open)},
    {SCMP_SYS (personality), &SCMP_A0 (SCMP_CMP_NE, allowed_personality)},
    {SCMP_SYS (ptrace)}
        r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 1, *syscall_blocklist[i].arg);
        r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 0);
            r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 1, *syscall_nondevel_blocklist[i].arg);
            r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 0);

Fixed code:
    int                  errnum;
    {SCMP_SYS (syslog), EPERM},
    {SCMP_SYS (uselib), EPERM},
    {SCMP_SYS (acct), EPERM},
    {SCMP_SYS (modify_ldt), EPERM},
    {SCMP_SYS (quotactl), EPERM},
    {SCMP_SYS (add_key), EPERM},
    {SCMP_SYS (keyctl), EPERM},
    {SCMP_SYS (request_key), EPERM},
    {SCMP_SYS (move_pages), EPERM},
    {SCMP_SYS (mbind), EPERM},
    {SCMP_SYS (get_mempolicy), EPERM},
    {SCMP_SYS (set_mempolicy), EPERM},
    {SCMP_SYS (migrate_pages), EPERM},
    {SCMP_SYS (unshare), EPERM},
    {SCMP_SYS (mount), EPERM},
    {SCMP_SYS (pivot_root), EPERM},
    {SCMP_SYS (clone), EPERM, &SCMP_A1 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
    {SCMP_SYS (clone), EPERM, &SCMP_A0 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
    {SCMP_SYS (ioctl), EPERM, &SCMP_A1 (SCMP_CMP_MASKED_EQ, 0xFFFFFFFFu, (int) TIOCSTI)},
    int                  errnum;
    {SCMP_SYS (perf_event_open), EPERM},
    {SCMP_SYS (personality), EPERM, &SCMP_A0 (SCMP_CMP_NE, allowed_personality)},
    {SCMP_SYS (ptrace), EPERM}
      int errnum = syscall_blocklist[i].errnum;

      g_return_val_if_fail (errnum == EPERM || errnum == ENOSYS, FALSE);

        r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 1, *syscall_blocklist[i].arg);
        r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 0);
          int errnum = syscall_nondevel_blocklist[i].errnum;

          g_return_val_if_fail (errnum == EPERM || errnum == ENOSYS, FALSE);

            r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 1, *syscall_nondevel_blocklist[i].arg);
            r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 0);