Blob Blame History Raw
From 6d8318a8d4fd82a5b75b6d2c595f54e54310ebd6 Mon Sep 17 00:00:00 2001
From: Matthew Leeds <matthew.leeds@endlessm.com>
Date: Mon, 8 Jun 2020 18:38:12 -0700
Subject: [PATCH 01/13] tree-wide: Replace usages of whitelist/blacklist

The terms whitelist and blacklist are hurtful to some people, and per
our code of conduct Flatpak is an inclusive community. Replace them with
allowlist and blocklist which are also more clear. This terminology
change is being implemented more broadly in the software industry; see
e.g. https://go-review.googlesource.com/c/go/+/236857/

[Backported to 1.2.x to make subsequent security fixes apply without
conflicts: don't touch the documentation, only the code. -smcv]

(cherry picked from commit a994cdb30e78c52d10a5c86bcc86783b86d11648)
(cherry picked from commit 9776116698f0fdb9abc4c278aeb8b89ce8303d46)
---
 common/flatpak-run.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index ea5571bd489b..1098ea7204fe 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2082,8 +2082,8 @@ setup_seccomp (FlatpakBwrap   *bwrap,
    * can do, and we should support code portability between different
    * container tools.
    *
-   * This syscall blacklist is copied from linux-user-chroot, which was in turn
-   * clearly influenced by the Sandstorm.io blacklist.
+   * This syscall blocklist is copied from linux-user-chroot, which was in turn
+   * clearly influenced by the Sandstorm.io blocklist.
    *
    * If you make any changes here, I suggest sending the changes along
    * to other sandbox maintainers.  Using the libseccomp list is also
@@ -2091,7 +2091,7 @@ setup_seccomp (FlatpakBwrap   *bwrap,
    * https://groups.google.com/forum/#!topic/libseccomp
    *
    * A non-exhaustive list of links to container tooling that might
-   * want to share this blacklist:
+   * want to share this blocklist:
    *
    *  https://github.com/sandstorm-io/sandstorm
    *    in src/sandstorm/supervisor.c++
@@ -2106,7 +2106,7 @@ setup_seccomp (FlatpakBwrap   *bwrap,
   {
     int                  scall;
     struct scmp_arg_cmp *arg;
-  } syscall_blacklist[] = {
+  } syscall_blocklist[] = {
     /* Block dmesg */
     {SCMP_SYS (syslog)},
     /* Useless old syscall */
@@ -2145,7 +2145,7 @@ setup_seccomp (FlatpakBwrap   *bwrap,
   {
     int                  scall;
     struct scmp_arg_cmp *arg;
-  } syscall_nondevel_blacklist[] = {
+  } syscall_nondevel_blocklist[] = {
     /* Profiling operations; we expect these to be done by tools from outside
      * the sandbox.  In particular perf has been the source of many CVEs.
      */
@@ -2154,12 +2154,12 @@ setup_seccomp (FlatpakBwrap   *bwrap,
     {SCMP_SYS (personality), &SCMP_A0 (SCMP_CMP_NE, allowed_personality)},
     {SCMP_SYS (ptrace)}
   };
-  /* Blacklist all but unix, inet, inet6 and netlink */
+  /* Blocklist all but unix, inet, inet6 and netlink */
   struct
   {
     int             family;
     FlatpakRunFlags flags_mask;
-  } socket_family_whitelist[] = {
+  } socket_family_allowlist[] = {
     /* NOTE: Keep in numerical order */
     { AF_UNSPEC, 0 },
     { AF_LOCAL, 0 },
@@ -2234,11 +2234,11 @@ setup_seccomp (FlatpakBwrap   *bwrap,
    * leak system stuff or secrets from other apps.
    */
 
-  for (i = 0; i < G_N_ELEMENTS (syscall_blacklist); i++)
+  for (i = 0; i < G_N_ELEMENTS (syscall_blocklist); i++)
     {
-      int scall = syscall_blacklist[i].scall;
-      if (syscall_blacklist[i].arg)
-        r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 1, *syscall_blacklist[i].arg);
+      int scall = syscall_blocklist[i].scall;
+      if (syscall_blocklist[i].arg)
+        r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 1, *syscall_blocklist[i].arg);
       else
         r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 0);
       if (r < 0 && r == -EFAULT /* unknown syscall */)
@@ -2247,11 +2247,11 @@ setup_seccomp (FlatpakBwrap   *bwrap,
 
   if (!devel)
     {
-      for (i = 0; i < G_N_ELEMENTS (syscall_nondevel_blacklist); i++)
+      for (i = 0; i < G_N_ELEMENTS (syscall_nondevel_blocklist); i++)
         {
-          int scall = syscall_nondevel_blacklist[i].scall;
-          if (syscall_nondevel_blacklist[i].arg)
-            r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 1, *syscall_nondevel_blacklist[i].arg);
+          int scall = syscall_nondevel_blocklist[i].scall;
+          if (syscall_nondevel_blocklist[i].arg)
+            r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 1, *syscall_nondevel_blocklist[i].arg);
           else
             r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 0);
 
@@ -2264,23 +2264,23 @@ setup_seccomp (FlatpakBwrap   *bwrap,
    * However, we need to user seccomp_rule_add_exact to avoid libseccomp doing
    * something else: https://github.com/seccomp/libseccomp/issues/8 */
   last_allowed_family = -1;
-  for (i = 0; i < G_N_ELEMENTS (socket_family_whitelist); i++)
+  for (i = 0; i < G_N_ELEMENTS (socket_family_allowlist); i++)
     {
-      int family = socket_family_whitelist[i].family;
+      int family = socket_family_allowlist[i].family;
       int disallowed;
 
-      if (socket_family_whitelist[i].flags_mask != 0 &&
-          (socket_family_whitelist[i].flags_mask & run_flags) != socket_family_whitelist[i].flags_mask)
+      if (socket_family_allowlist[i].flags_mask != 0 &&
+          (socket_family_allowlist[i].flags_mask & run_flags) != socket_family_allowlist[i].flags_mask)
         continue;
 
       for (disallowed = last_allowed_family + 1; disallowed < family; disallowed++)
         {
-          /* Blacklist the in-between valid families */
+          /* Blocklist the in-between valid families */
           seccomp_rule_add_exact (seccomp, SCMP_ACT_ERRNO (EAFNOSUPPORT), SCMP_SYS (socket), 1, SCMP_A0 (SCMP_CMP_EQ, disallowed));
         }
       last_allowed_family = family;
     }
-  /* Blacklist the rest */
+  /* Blocklist the rest */
   seccomp_rule_add_exact (seccomp, SCMP_ACT_ERRNO (EAFNOSUPPORT), SCMP_SYS (socket), 1, SCMP_A0 (SCMP_CMP_GE, last_allowed_family + 1));
 
   if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &seccomp_tmpf, error))
-- 
2.31.1


From 9f578cfb5b5cf3cdeb91b79f7dd9076bd2862830 Mon Sep 17 00:00:00 2001
From: Julian Andres Klode <julian.klode@canonical.com>
Date: Wed, 5 Aug 2020 16:28:50 +0200
Subject: [PATCH 02/13] Fix argument order of clone() for s390x in seccomp
 filter

clone() is a mad syscall with about 4 different argument orders. While
most of them agree that argument 0 is flags, s390 and s390x have the
flags argument second - A0 is the child stack pointer there.

[smcv: Add an explanatory comment; also test __CRIS__ for completeness]

Bug-Debian: https://bugs.debian.org/964541
Bug-Ubuntu: https://launchpad.net/bugs/1886814
Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 8ba141c38f85c8ad82d0ad6d9bde503ec4a971b6)
(cherry picked from commit ad32f848d5b7126a16f15fbfe0ec0a1e4f4b66c3)
---
 common/flatpak-run.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 1098ea7204fe..50dab684b050 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2135,7 +2135,14 @@ setup_seccomp (FlatpakBwrap   *bwrap,
     {SCMP_SYS (unshare)},
     {SCMP_SYS (mount)},
     {SCMP_SYS (pivot_root)},
+#if defined(__s390__) || defined(__s390x__) || defined(__CRIS__)
+    /* Architectures with CONFIG_CLONE_BACKWARDS2: the child stack
+     * and flags arguments are reversed so the flags come second */
+    {SCMP_SYS (clone), &SCMP_A1 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
+#else
+    /* Normally the flags come first */
     {SCMP_SYS (clone), &SCMP_A0 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
+#endif
 
     /* Don't allow faking input to the controlling tty (CVE-2017-5226) */
     {SCMP_SYS (ioctl), &SCMP_A1 (SCMP_CMP_MASKED_EQ, 0xFFFFFFFFu, (int) TIOCSTI)},
-- 
2.31.1


From f41f46aaf57bcecaeb0885d7cbf6a33ab2cf3ca6 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Wed, 1 Sep 2021 11:53:23 +0100
Subject: [PATCH 03/13] 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>
(cherry picked from commit e26ac7586c392b5eb35ff4609fe232c52523b2cf)
(cherry picked from commit fa00b38504ebef43dec74dee2e91af837f4bc7da)
---
 common/flatpak-run.c | 62 +++++++++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 26 deletions(-)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 50dab684b050..f7f40100bd2b 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2105,61 +2105,63 @@ setup_seccomp (FlatpakBwrap   *bwrap,
   struct
   {
     int                  scall;
+    int                  errnum;
     struct scmp_arg_cmp *arg;
   } syscall_blocklist[] = {
     /* Block dmesg */
-    {SCMP_SYS (syslog)},
+    {SCMP_SYS (syslog), EPERM},
     /* Useless old syscall */
-    {SCMP_SYS (uselib)},
+    {SCMP_SYS (uselib), EPERM},
     /* Don't allow disabling accounting */
-    {SCMP_SYS (acct)},
+    {SCMP_SYS (acct), EPERM},
     /* 16-bit code is unnecessary in the sandbox, and modify_ldt is a
        historic source of interesting information leaks. */
-    {SCMP_SYS (modify_ldt)},
+    {SCMP_SYS (modify_ldt), EPERM},
     /* Don't allow reading current quota use */
-    {SCMP_SYS (quotactl)},
+    {SCMP_SYS (quotactl), EPERM},
 
     /* Don't allow access to the kernel keyring */
-    {SCMP_SYS (add_key)},
-    {SCMP_SYS (keyctl)},
-    {SCMP_SYS (request_key)},
+    {SCMP_SYS (add_key), EPERM},
+    {SCMP_SYS (keyctl), EPERM},
+    {SCMP_SYS (request_key), EPERM},
 
     /* Scary VM/NUMA ops */
-    {SCMP_SYS (move_pages)},
-    {SCMP_SYS (mbind)},
-    {SCMP_SYS (get_mempolicy)},
-    {SCMP_SYS (set_mempolicy)},
-    {SCMP_SYS (migrate_pages)},
+    {SCMP_SYS (move_pages), EPERM},
+    {SCMP_SYS (mbind), EPERM},
+    {SCMP_SYS (get_mempolicy), EPERM},
+    {SCMP_SYS (set_mempolicy), EPERM},
+    {SCMP_SYS (migrate_pages), EPERM},
 
     /* Don't allow subnamespace setups: */
-    {SCMP_SYS (unshare)},
-    {SCMP_SYS (mount)},
-    {SCMP_SYS (pivot_root)},
+    {SCMP_SYS (unshare), EPERM},
+    {SCMP_SYS (mount), EPERM},
+    {SCMP_SYS (pivot_root), EPERM},
 #if defined(__s390__) || defined(__s390x__) || defined(__CRIS__)
     /* Architectures with CONFIG_CLONE_BACKWARDS2: the child stack
      * and flags arguments are reversed so the flags come second */
-    {SCMP_SYS (clone), &SCMP_A1 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
+    {SCMP_SYS (clone), EPERM, &SCMP_A1 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
 #else
     /* Normally the flags come first */
-    {SCMP_SYS (clone), &SCMP_A0 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
+    {SCMP_SYS (clone), EPERM, &SCMP_A0 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
 #endif
 
     /* Don't allow faking input to the controlling tty (CVE-2017-5226) */
-    {SCMP_SYS (ioctl), &SCMP_A1 (SCMP_CMP_MASKED_EQ, 0xFFFFFFFFu, (int) TIOCSTI)},
+    {SCMP_SYS (ioctl), EPERM, &SCMP_A1 (SCMP_CMP_MASKED_EQ, 0xFFFFFFFFu, (int) TIOCSTI)},
   };
 
   struct
   {
     int                  scall;
+    int                  errnum;
     struct scmp_arg_cmp *arg;
   } syscall_nondevel_blocklist[] = {
     /* Profiling operations; we expect these to be done by tools from outside
      * the sandbox.  In particular perf has been the source of many CVEs.
      */
-    {SCMP_SYS (perf_event_open)},
+    {SCMP_SYS (perf_event_open), EPERM},
     /* Don't allow you to switch to bsd emulation or whatnot */
-    {SCMP_SYS (personality), &SCMP_A0 (SCMP_CMP_NE, allowed_personality)},
-    {SCMP_SYS (ptrace)}
+    {SCMP_SYS (personality), EPERM, &SCMP_A0 (SCMP_CMP_NE, allowed_personality)},
+    {SCMP_SYS (ptrace), EPERM}
   };
   /* Blocklist all but unix, inet, inet6 and netlink */
   struct
@@ -2244,10 +2246,14 @@ setup_seccomp (FlatpakBwrap   *bwrap,
   for (i = 0; i < G_N_ELEMENTS (syscall_blocklist); i++)
     {
       int scall = syscall_blocklist[i].scall;
+      int errnum = syscall_blocklist[i].errnum;
+
+      g_return_val_if_fail (errnum == EPERM || errnum == ENOSYS, FALSE);
+
       if (syscall_blocklist[i].arg)
-        r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 1, *syscall_blocklist[i].arg);
+        r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 1, *syscall_blocklist[i].arg);
       else
-        r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 0);
+        r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 0);
       if (r < 0 && r == -EFAULT /* unknown syscall */)
         return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to block syscall %d"), scall);
     }
@@ -2257,10 +2263,14 @@ setup_seccomp (FlatpakBwrap   *bwrap,
       for (i = 0; i < G_N_ELEMENTS (syscall_nondevel_blocklist); i++)
         {
           int scall = syscall_nondevel_blocklist[i].scall;
+          int errnum = syscall_nondevel_blocklist[i].errnum;
+
+          g_return_val_if_fail (errnum == EPERM || errnum == ENOSYS, FALSE);
+
           if (syscall_nondevel_blocklist[i].arg)
-            r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 1, *syscall_nondevel_blocklist[i].arg);
+            r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 1, *syscall_nondevel_blocklist[i].arg);
           else
-            r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 0);
+            r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 0);
 
           if (r < 0 && r == -EFAULT /* unknown syscall */)
             return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to block syscall %d"), scall);
-- 
2.31.1


From 96c181058292a4b4c9326b81e7fc8ba3bb052395 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Wed, 1 Sep 2021 12:44:04 +0100
Subject: [PATCH 04/13] run: Add cross-references for some other seccomp
 syscall filters

Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 89ae9fe74c6d445bb1b3a40e568d77cf5de47e48)
(cherry picked from commit ab95bdb1b3c82de80848f0f2a385878a68e97350)
---
 common/flatpak-run.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index f7f40100bd2b..4846324af304 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2100,6 +2100,10 @@ setup_seccomp (FlatpakBwrap   *bwrap,
    *  https://git.gnome.org/browse/linux-user-chroot
    *    in src/setup-seccomp.c
    *
+   * Other useful resources:
+   * https://github.com/systemd/systemd/blob/HEAD/src/shared/seccomp-util.c
+   * https://github.com/moby/moby/blob/HEAD/profiles/seccomp/default.json
+   *
    **** END NOTE ON CODE SHARING
    */
   struct
-- 
2.31.1


From 8351001f4a52466f6629390e6b0e94e2e15da4e6 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Wed, 1 Sep 2021 14:17:04 +0100
Subject: [PATCH 05/13] common: Add a list of recently-added Linux syscalls

Historically, syscalls could take arbitrarily-different values on
different architectures, but new syscalls are added with syscall numbers
that align on each architecture.

Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 26b12484eb8a6219b9e7aa287b298a894b2f34ca)
(cherry picked from commit e019d04faba1fb812996e8404b5ad05efb1bf439)
---
 common/Makefile.am.inc            |   1 +
 common/flatpak-run.c              |   2 +
 common/flatpak-syscalls-private.h | 197 ++++++++++++++++++++++++++++++
 3 files changed, 200 insertions(+)
 create mode 100644 common/flatpak-syscalls-private.h

diff --git a/common/Makefile.am.inc b/common/Makefile.am.inc
index 794bd4e348ff..623ef78be2c4 100644
--- a/common/Makefile.am.inc
+++ b/common/Makefile.am.inc
@@ -124,6 +124,7 @@ libflatpak_common_la_SOURCES = \
 	common/flatpak-installation.c \
 	common/flatpak-instance-private.h \
 	common/flatpak-instance.c \
+	common/flatpak-syscalls-private.h \
 	common/valgrind-private.h \
 	$(NULL)
 
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 4846324af304..5e655c13e7d2 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -33,6 +33,8 @@
 #include <unistd.h>
 #include <gio/gunixfdlist.h>
 
+#include "flatpak-syscalls-private.h"
+
 #ifdef ENABLE_SECCOMP
 #include <seccomp.h>
 #endif
diff --git a/common/flatpak-syscalls-private.h b/common/flatpak-syscalls-private.h
new file mode 100644
index 000000000000..04eb38ce3631
--- /dev/null
+++ b/common/flatpak-syscalls-private.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2021 Collabora Ltd.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <sys/syscall.h>
+
+#if defined(_MIPS_SIM)
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+#   define FLATPAK_MISSING_SYSCALL_BASE 4000
+# elif _MIPS_SIM == _MIPS_SIM_ABI64
+#   define FLATPAK_MISSING_SYSCALL_BASE 5000
+# elif _MIPS_SIM == _MIPS_SIM_NABI32
+#   define FLATPAK_MISSING_SYSCALL_BASE 6000
+# else
+#   error "Unknown MIPS ABI"
+# endif
+#endif
+
+#if defined(__ia64__)
+# define FLATPAK_MISSING_SYSCALL_BASE 1024
+#endif
+
+#if defined(__alpha__)
+# define FLATPAK_MISSING_SYSCALL_BASE 110
+#endif
+
+#if defined(__x86_64__) && defined(__ILP32__)
+# define FLATPAK_MISSING_SYSCALL_BASE 0x40000000
+#endif
+
+/*
+ * FLATPAK_MISSING_SYSCALL_BASE:
+ *
+ * Number to add to the syscall numbers of recently-added syscalls
+ * to get the appropriate syscall for the current ABI.
+ */
+#ifndef FLATPAK_MISSING_SYSCALL_BASE
+# define FLATPAK_MISSING_SYSCALL_BASE 0
+#endif
+
+#ifndef __NR_open_tree
+# define __NR_open_tree (FLATPAK_MISSING_SYSCALL_BASE + 428)
+#endif
+#ifndef __SNR_open_tree
+# define __SNR_open_tree __NR_open_tree
+#endif
+
+#ifndef __NR_move_mount
+# define __NR_move_mount (FLATPAK_MISSING_SYSCALL_BASE + 429)
+#endif
+#ifndef __SNR_move_mount
+# define __SNR_move_mount __NR_move_mount
+#endif
+
+#ifndef __NR_fsopen
+# define __NR_fsopen (FLATPAK_MISSING_SYSCALL_BASE + 430)
+#endif
+#ifndef __SNR_fsopen
+# define __SNR_fsopen __NR_fsopen
+#endif
+
+#ifndef __NR_fsconfig
+# define __NR_fsconfig (FLATPAK_MISSING_SYSCALL_BASE + 431)
+#endif
+#ifndef __SNR_fsconfig
+# define __SNR_fsconfig __NR_fsconfig
+#endif
+
+#ifndef __NR_fsmount
+# define __NR_fsmount (FLATPAK_MISSING_SYSCALL_BASE + 432)
+#endif
+#ifndef __SNR_fsmount
+# define __SNR_fsmount __NR_fsmount
+#endif
+
+#ifndef __NR_fspick
+# define __NR_fspick (FLATPAK_MISSING_SYSCALL_BASE + 433)
+#endif
+#ifndef __SNR_fspick
+# define __SNR_fspick __NR_fspick
+#endif
+
+#ifndef __NR_pidfd_open
+# define __NR_pidfd_open (FLATPAK_MISSING_SYSCALL_BASE + 434)
+#endif
+#ifndef __SNR_pidfd_open
+# define __SNR_pidfd_open __NR_pidfd_open
+#endif
+
+#ifndef __NR_clone3
+# define __NR_clone3 (FLATPAK_MISSING_SYSCALL_BASE + 435)
+#endif
+#ifndef __SNR_clone3
+# define __SNR_clone3 __NR_clone3
+#endif
+
+#ifndef __NR_close_range
+# define __NR_close_range (FLATPAK_MISSING_SYSCALL_BASE + 436)
+#endif
+#ifndef __SNR_close_range
+# define __SNR_close_range __NR_close_range
+#endif
+
+#ifndef __NR_openat2
+# define __NR_openat2 (FLATPAK_MISSING_SYSCALL_BASE + 437)
+#endif
+#ifndef __SNR_openat2
+# define __SNR_openat2 __NR_openat2
+#endif
+
+#ifndef __NR_pidfd_getfd
+# define __NR_pidfd_getfd (FLATPAK_MISSING_SYSCALL_BASE + 438)
+#endif
+#ifndef __SNR_pidfd_getfd
+# define __SNR_pidfd_getfd __NR_pidfd_getfd
+#endif
+
+#ifndef __NR_faccessat2
+# define __NR_faccessat2 (FLATPAK_MISSING_SYSCALL_BASE + 439)
+#endif
+#ifndef __SNR_faccessat2
+# define __SNR_faccessat2 __NR_faccessat2
+#endif
+
+#ifndef __NR_process_madvise
+# define __NR_process_madvise (FLATPAK_MISSING_SYSCALL_BASE + 440)
+#endif
+#ifndef __SNR_process_madvise
+# define __SNR_process_madvise __NR_process_madvise
+#endif
+
+#ifndef __NR_epoll_pwait2
+# define __NR_epoll_pwait2 (FLATPAK_MISSING_SYSCALL_BASE + 441)
+#endif
+#ifndef __SNR_epoll_pwait2
+# define __SNR_epoll_pwait2 __NR_epoll_pwait2
+#endif
+
+#ifndef __NR_mount_setattr
+# define __NR_mount_setattr (FLATPAK_MISSING_SYSCALL_BASE + 442)
+#endif
+#ifndef __SNR_mount_setattr
+# define __SNR_mount_setattr __NR_mount_setattr
+#endif
+
+#ifndef __NR_quotactl_fd
+# define __NR_quotactl_fd (FLATPAK_MISSING_SYSCALL_BASE + 443)
+#endif
+#ifndef __SNR_quotactl_fd
+# define __SNR_quotactl_fd __NR_quotactl_fd
+#endif
+
+#ifndef __NR_landlock_create_ruleset
+# define __NR_landlock_create_ruleset (FLATPAK_MISSING_SYSCALL_BASE + 444)
+#endif
+#ifndef __SNR_landlock_create_ruleset
+# define __SNR_landlock_create_ruleset __NR_landlock_create_ruleset
+#endif
+
+#ifndef __NR_landlock_add_rule
+# define __NR_landlock_add_rule (FLATPAK_MISSING_SYSCALL_BASE + 445)
+#endif
+#ifndef __SNR_landlock_add_rule
+# define __SNR_landlock_add_rule __NR_landlock_add_rule
+#endif
+
+#ifndef __NR_landlock_restrict_self
+# define __NR_landlock_restrict_self (FLATPAK_MISSING_SYSCALL_BASE + 446)
+#endif
+#ifndef __SNR_landlock_restrict_self
+# define __SNR_landlock_restrict_self __NR_landlock_restrict_self
+#endif
+
+#ifndef __NR_memfd_secret
+# define __NR_memfd_secret (FLATPAK_MISSING_SYSCALL_BASE + 447)
+#endif
+#ifndef __SNR_memfd_secret
+# define __SNR_memfd_secret __NR_memfd_secret
+#endif
+
+/* Last updated: Linux 5.14, syscall numbers < 448 */
-- 
2.31.1


From bd5735dac3ed31b1a95d999cbf0b117d6c23ad61 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Wed, 1 Sep 2021 11:59:00 +0100
Subject: [PATCH 06/13] run: Block clone3() in sandbox

clone3() can be used to implement clone() with CLONE_NEWUSER, allowing
a sandboxed process to get CAP_SYS_ADMIN in a new namespace and
manipulate its root directory. We need to block this so that AF_UNIX-based
socket servers (X11, Wayland, etc.) can rely on
/proc/PID/root/.flatpak-info existing for all Flatpak-sandboxed apps.

Partially fixes GHSA-67h7-w3jq-vh4q.

Thanks: an anonymous reporter
Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit a10f52a7565c549612c92b8e736a6698a53db330)
(cherry picked from commit 6be11da1b95d2751468edddba4fc2fddf0ae7d9d)
---
 common/flatpak-run.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 5e655c13e7d2..2cc06239df9e 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2153,6 +2153,12 @@ setup_seccomp (FlatpakBwrap   *bwrap,
 
     /* Don't allow faking input to the controlling tty (CVE-2017-5226) */
     {SCMP_SYS (ioctl), EPERM, &SCMP_A1 (SCMP_CMP_MASKED_EQ, 0xFFFFFFFFu, (int) TIOCSTI)},
+
+    /* seccomp can't look into clone3()'s struct clone_args to check whether
+     * the flags are OK, so we have no choice but to block clone3().
+     * Return ENOSYS so user-space will fall back to clone().
+     * (GHSA-67h7-w3jq-vh4q; see also https://github.com/moby/moby/commit/9f6b562d) */
+    {SCMP_SYS (clone3), ENOSYS},
   };
 
   struct
-- 
2.31.1


From 29c93b8a47ee73d2f2ff905004c41409a153cd57 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Wed, 1 Sep 2021 12:45:54 +0100
Subject: [PATCH 07/13] run: Disallow recently-added mount-manipulation
 syscalls

If we don't allow mount() then we shouldn't allow these either.

Partially fixes GHSA-67h7-w3jq-vh4q.

Thanks: an anonymous reporter
Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 9766ee05b1425db397d2cf23afd24c7f6146a69f)
(cherry picked from commit 5ffa56fe76354392c74eb5c8fcf6e7f8bf7fdea7)
---
 common/flatpak-run.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 2cc06239df9e..1ae758892051 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2159,6 +2159,18 @@ setup_seccomp (FlatpakBwrap   *bwrap,
      * Return ENOSYS so user-space will fall back to clone().
      * (GHSA-67h7-w3jq-vh4q; see also https://github.com/moby/moby/commit/9f6b562d) */
     {SCMP_SYS (clone3), ENOSYS},
+
+    /* New mount manipulation APIs can also change our VFS. There's no
+     * legitimate reason to do these in the sandbox, so block all of them
+     * rather than thinking about which ones might be dangerous.
+     * (GHSA-67h7-w3jq-vh4q) */
+    {SCMP_SYS (open_tree), ENOSYS},
+    {SCMP_SYS (move_mount), ENOSYS},
+    {SCMP_SYS (fsopen), ENOSYS},
+    {SCMP_SYS (fsconfig), ENOSYS},
+    {SCMP_SYS (fsmount), ENOSYS},
+    {SCMP_SYS (fspick), ENOSYS},
+    {SCMP_SYS (mount_setattr), ENOSYS},
   };
 
   struct
-- 
2.31.1


From 96b960d29ce4acf6bc983b97d7ff85e20fe1f2bb Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Wed, 1 Sep 2021 14:19:31 +0100
Subject: [PATCH 08/13] run: Block setns()

If we don't allow unshare() or clone() with CLONE_NEWUSER, we also
shouldn't allow joining an existing (but different) namespace.

Partially fixes GHSA-67h7-w3jq-vh4q.

Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 4c34815784e9ffda5733225c7d95824f96375e36)
(cherry picked from commit ab5232e6c3d896f72a623e798b8e6dfa6efcfd9b)
---
 common/flatpak-run.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 1ae758892051..0cae23d7809c 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2140,6 +2140,7 @@ setup_seccomp (FlatpakBwrap   *bwrap,
 
     /* Don't allow subnamespace setups: */
     {SCMP_SYS (unshare), EPERM},
+    {SCMP_SYS (setns), EPERM},
     {SCMP_SYS (mount), EPERM},
     {SCMP_SYS (pivot_root), EPERM},
 #if defined(__s390__) || defined(__s390x__) || defined(__CRIS__)
-- 
2.31.1


From 8d22d36cb8861d3391015f267222d4742bb6357c Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Wed, 1 Sep 2021 14:20:29 +0100
Subject: [PATCH 09/13] run: Don't allow unmounting filesystems

If we don't allow mounting filesystems, we shouldn't allow unmounting
either.

Partially fixes GHSA-67h7-w3jq-vh4q.

Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 1330662f33a55e88bfe18e76de28b7922d91a999)
(cherry picked from commit aa570112217ae6dfccaa8fe5db55e29b76c9db80)
---
 common/flatpak-run.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 0cae23d7809c..c4bd6fa84079 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2142,6 +2142,8 @@ setup_seccomp (FlatpakBwrap   *bwrap,
     {SCMP_SYS (unshare), EPERM},
     {SCMP_SYS (setns), EPERM},
     {SCMP_SYS (mount), EPERM},
+    {SCMP_SYS (umount), EPERM},
+    {SCMP_SYS (umount2), EPERM},
     {SCMP_SYS (pivot_root), EPERM},
 #if defined(__s390__) || defined(__s390x__) || defined(__CRIS__)
     /* Architectures with CONFIG_CLONE_BACKWARDS2: the child stack
-- 
2.31.1


From 07ded57a9e8b6b3afe50fea2fed0e1d0d9484bb4 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Wed, 1 Sep 2021 14:21:04 +0100
Subject: [PATCH 10/13] run: Don't allow chroot()

If we don't allow pivot_root() then there seems no reason why we should
allow chroot().

Partially fixes GHSA-67h7-w3jq-vh4q.

Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 462fca2c666e0cd2b60d6d2593a7216a83047aaf)
(cherry picked from commit 8d4281f19a56901c0801e3b2b1cc0bc3e0519d49)
---
 common/flatpak-run.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index c4bd6fa84079..b8d1cb0b8dc9 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2145,6 +2145,7 @@ setup_seccomp (FlatpakBwrap   *bwrap,
     {SCMP_SYS (umount), EPERM},
     {SCMP_SYS (umount2), EPERM},
     {SCMP_SYS (pivot_root), EPERM},
+    {SCMP_SYS (chroot), EPERM},
 #if defined(__s390__) || defined(__s390x__) || defined(__CRIS__)
     /* Architectures with CONFIG_CLONE_BACKWARDS2: the child stack
      * and flags arguments are reversed so the flags come second */
-- 
2.31.1


From 512680add1be8689e013565a3ace45e372d1a665 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Fri, 8 Oct 2021 17:05:07 +0100
Subject: [PATCH 11/13] run: Handle unknown syscalls as intended

The error-handling here was

    if (r < 0 && r == -EFAULT)

but Alex says it was almost certainly intended to be

    if (r < 0 && r != -EFAULT)

so that syscalls not known to libseccomp are not a fatal error.

Instead of literally making that change, emit a debug message on -EFAULT
so we can see what is going on.

This temporarily weakens our defence against CVE-2021-41133
(GHSA-67h7-w3jq-vh4q) in order to avoid regressions: if the installed
version of libseccomp does not know about the recently-added syscalls,
but the kernel does, then we will not prevent non-native executables
from using those syscalls.

Resolves: https://github.com/flatpak/flatpak/issues/4458
Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit d419fa67038370e4f4c3ce8c3b5f672d4876cfc8)
(cherry picked from commit 270701f900c8612cf1fc5e6f5a6e2eb6459708c1)
(cherry picked from commit a0055e4f849d5bb100f2af7e33f02ef9ac3fbdee)
(cherry picked from commit ed2c15d9964b17a7f6b64d3956a9adfbfd2b0834)
(cherry picked from commit 02498d636f8d3048cebde74bb1eb308149b8dd0b)
---
 common/flatpak-run.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index b8d1cb0b8dc9..7ad2626c9e3d 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2282,7 +2282,16 @@ setup_seccomp (FlatpakBwrap   *bwrap,
         r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 1, *syscall_blocklist[i].arg);
       else
         r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 0);
-      if (r < 0 && r == -EFAULT /* unknown syscall */)
+
+      /* EFAULT means "internal libseccomp error", but in practice we get
+       * this for syscall numbers added via flatpak-syscalls-private.h
+       * when trying to filter them on a non-native architecture, because
+       * libseccomp cannot map the syscall number to a name and back to a
+       * number for the non-native architecture. */
+      if (r == -EFAULT)
+        flatpak_debug2 ("Unable to block syscall %d: syscall not known to libseccomp?",
+                        scall);
+      else if (r < 0)
         return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to block syscall %d"), scall);
     }
 
@@ -2300,7 +2309,11 @@ setup_seccomp (FlatpakBwrap   *bwrap,
           else
             r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 0);
 
-          if (r < 0 && r == -EFAULT /* unknown syscall */)
+          /* See above for the meaning of EFAULT. */
+          if (errno == EFAULT)
+            flatpak_debug2 ("Unable to block syscall %d: syscall not known to libseccomp?",
+                            scall);
+          else if (r < 0)
             return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to block syscall %d"), scall);
         }
     }
-- 
2.31.1


From fd836c2eec26015efe904d48a81f13705bd578d5 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Fri, 8 Oct 2021 19:00:13 +0100
Subject: [PATCH 12/13] Fix handling of syscalls only allowed by --devel

This was incorrectly looking at errno instead of -r.

Fixes: 0b38b0f0 "run: Handle unknown syscalls as intended"
Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 3fc8c672676ae016f8e7cc90481b2feecbad9861)
(cherry picked from commit 97e128c2c1520202486b5e165e1734cbb421568a)
(cherry picked from commit da503e0d903f275e02c8932069a0badbf3946812)
(cherry picked from commit 68163fbc0b956e21fa6b2d5d854f0d1f81294d5d)
(cherry picked from commit cfc72b9694e295696743ed52361e29bc1f575d60)
---
 common/flatpak-run.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 7ad2626c9e3d..6ad11f5b25a9 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2310,7 +2310,7 @@ setup_seccomp (FlatpakBwrap   *bwrap,
             r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (errnum), scall, 0);
 
           /* See above for the meaning of EFAULT. */
-          if (errno == EFAULT)
+          if (r == -EFAULT)
             flatpak_debug2 ("Unable to block syscall %d: syscall not known to libseccomp?",
                             scall);
           else if (r < 0)
-- 
2.31.1


From 79a8fb7cf8ed8ac23dce5c3fdbd61e8fdc49110c Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Fri, 8 Oct 2021 19:06:13 +0100
Subject: [PATCH 13/13] run: Improve error handling/diagnostics for calls into
 libseccomp

Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 53bde36585b88a2b96bf896ed79b40ccb6a72c54)
(cherry picked from commit bd2c58fc27fa5e31029339dbce8eea10717015f3)
(cherry picked from commit adaa0259e807bee49d18495108fb0c4c6856213c)
(cherry picked from commit 2c82e9cc6e053fd3ec419da5f67a50d1ee50bf72)
(cherry picked from commit ad0e32e3477611383df1e7a6ad01276ad35c422d)
---
 common/flatpak-run.c | 46 ++++++++++++++++++++++++++++++++++++++------
 1 file changed, 40 insertions(+), 6 deletions(-)

diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 6ad11f5b25a9..fa9862a047ad 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2054,6 +2054,38 @@ static const uint32_t seccomp_x86_64_extra_arches[] = { SCMP_ARCH_X86, 0, };
 static const uint32_t seccomp_aarch64_extra_arches[] = { SCMP_ARCH_ARM, 0 };
 #endif
 
+/*
+ * @negative_errno: Result code as returned by libseccomp functions
+ *
+ * Translate a libseccomp error code into an error message. libseccomp
+ * mostly returns negative `errno` values such as `-ENOMEM`, but some
+ * standard `errno` values are used for non-standard purposes where their
+ * `strerror()` would be misleading.
+ *
+ * Returns: a string version of @negative_errno if possible
+ */
+static const char *
+flatpak_seccomp_strerror (int negative_errno)
+{
+  g_return_val_if_fail (negative_errno < 0, "Non-negative error value from libseccomp?");
+  g_return_val_if_fail (negative_errno > INT_MIN, "Out of range error value from libseccomp?");
+
+  switch (negative_errno)
+    {
+      case -EDOM:
+        return "Architecture specific failure";
+
+      case -EFAULT:
+        return "Internal libseccomp failure (unknown syscall?)";
+
+      case -ECANCELED:
+        return "System failure beyond the control of libseccomp";
+    }
+
+  /* e.g. -ENOMEM: the result of strerror() is good enough */
+  return g_strerror (-negative_errno);
+}
+
 static inline void
 cleanup_seccomp (void *p)
 {
@@ -2251,7 +2283,7 @@ setup_seccomp (FlatpakBwrap   *bwrap,
              couldn't continue running. */
           r = seccomp_arch_add (seccomp, arch_id);
           if (r < 0 && r != -EEXIST)
-            return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to add architecture to seccomp filter"));
+            return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to add architecture to seccomp filter: %s"), flatpak_seccomp_strerror (r));
 
           if (multiarch && extra_arches != NULL)
             {
@@ -2260,7 +2292,7 @@ setup_seccomp (FlatpakBwrap   *bwrap,
                 {
                   r = seccomp_arch_add (seccomp, extra_arches[i]);
                   if (r < 0 && r != -EEXIST)
-                    return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to add multiarch architecture to seccomp filter"));
+                    return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to add multiarch architecture to seccomp filter: %s"), flatpak_seccomp_strerror (r));
                 }
             }
         }
@@ -2292,7 +2324,7 @@ setup_seccomp (FlatpakBwrap   *bwrap,
         flatpak_debug2 ("Unable to block syscall %d: syscall not known to libseccomp?",
                         scall);
       else if (r < 0)
-        return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to block syscall %d"), scall);
+        return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to block syscall %d: %s"), scall, flatpak_seccomp_strerror (r));
     }
 
   if (!devel)
@@ -2314,7 +2346,7 @@ setup_seccomp (FlatpakBwrap   *bwrap,
             flatpak_debug2 ("Unable to block syscall %d: syscall not known to libseccomp?",
                             scall);
           else if (r < 0)
-            return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to block syscall %d"), scall);
+            return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to block syscall %d: %s"), scall, flatpak_seccomp_strerror (r));
         }
     }
 
@@ -2344,8 +2376,10 @@ setup_seccomp (FlatpakBwrap   *bwrap,
   if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &seccomp_tmpf, error))
     return FALSE;
 
-  if (seccomp_export_bpf (seccomp, seccomp_tmpf.fd) != 0)
-    return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to export bpf"));
+  r = seccomp_export_bpf (seccomp, seccomp_tmpf.fd);
+
+  if (r != 0)
+    return flatpak_fail_error (error, FLATPAK_ERROR_SETUP_FAILED, _("Failed to export bpf: %s"), flatpak_seccomp_strerror (r));
 
   lseek (seccomp_tmpf.fd, 0, SEEK_SET);
 
-- 
2.31.1