commit e1550e3aacad5f9f5ea391c1f8f47a83bce03633
parent e105833bad483467d09617514c297c99c7681eb9
Author: Dylan Araps <dylan.araps@gmail.com>
Date: Thu, 23 Apr 2020 16:25:31 +0300
flatpak: Drop libcap dependency (used only when suid which isn't required)
Diffstat:
6 files changed, 285 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
@@ -14,8 +14,6 @@ INSTRUCTIONS
```
# NOTE: You must have user namespaces enabled in your kernel.
-# Your other alternative is to give bubblewrap suid.
-# chmod u+s /usr/libexec/flatpak-bwrap
# NOTE: The community repository must also be enabled.
-> git clone https://github.com/dylanaraps/kiss-flatpak
diff --git a/flatpak/flatpak/build b/flatpak/flatpak/build
@@ -1,7 +1,14 @@
#!/bin/sh -e
-patch -p1 < fix-musl.patch
-patch -p1 < bubblewrap-musl.patch
+for patch in *.patch; do
+ patch -p1 < "$patch"
+done
+
+# Remove libcap dependency (used solely when bwrap is suid
+# root). User namespaces are much better, should be used
+# in place of libcap and are free.
+sed -i 's/as_fn_error.*libcap/: "/g' configure
+sed -i 's/as_fn_error.*capability\.h/: "/g' configure
# Remove fuse2 dependency (used solely with root "system-helper"
# daemon for file transfer. Unneeded in our case and drops the
diff --git a/flatpak/flatpak/checksums b/flatpak/flatpak/checksums
@@ -2,3 +2,4 @@
c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 pyparsing-2.4.7.tar.gz
c2e8b0430715aa8d1a43be79d8279e1cd088a925ba6d375b0707aeda3f5408d2 fix-musl.patch
1f9f2f55965041953ce0ed4e436e181d73f8decc36457a923c6bc42442718da1 bubblewrap-musl.patch
+f5c88cbb5597f70f1bad07f6f50332850e8c37aceb7a3d8e5e735b1ae4a40418 no-libcap.patch
diff --git a/flatpak/flatpak/depends b/flatpak/flatpak/depends
@@ -3,7 +3,6 @@ gdk-pixbuf
glib
gpgme
libarchive
-libcap
libsoup
libxml2
ostree
diff --git a/flatpak/flatpak/patches/no-libcap.patch b/flatpak/flatpak/patches/no-libcap.patch
@@ -0,0 +1,274 @@
+diff --git a/app/flatpak-builtins-enter.c b/app/flatpak-builtins-enter.c
+index 4a7c51d..3cd365f 100644
+--- a/app/flatpak-builtins-enter.c
++++ b/app/flatpak-builtins-enter.c
+@@ -36,21 +36,11 @@
+ #include "flatpak-dbus-generated.h"
+ #include "flatpak-run-private.h"
+ #include "flatpak-instance.h"
+-#include <sys/capability.h>
+
+ static GOptionEntry options[] = {
+ { NULL }
+ };
+
+-static void
+-drop_all_caps (void)
+-{
+- struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 };
+- struct __user_cap_data_struct data[2] = { { 0 } };
+-
+- capset (&hdr, data);
+-}
+-
+ gboolean
+ flatpak_builtin_enter (int argc,
+ char **argv,
+@@ -226,8 +216,6 @@ flatpak_builtin_enter (int argc,
+ if (setuid (uid))
+ return flatpak_fail (error, _("Can't switch uid"));
+
+- drop_all_caps ();
+-
+ envp_array = g_ptr_array_new_with_free_func (g_free);
+ for (e = environment; e < environment + environment_len; e = e + strlen (e) + 1)
+ {
+diff --git a/bubblewrap/bubblewrap.c b/bubblewrap/bubblewrap.c
+index b3d52bc..59b0076 100644
+--- a/bubblewrap/bubblewrap.c
++++ b/bubblewrap/bubblewrap.c
+@@ -28,7 +28,6 @@
+ #include <sys/eventfd.h>
+ #include <sys/fsuid.h>
+ #include <sys/signalfd.h>
+-#include <sys/capability.h>
+ #include <sys/prctl.h>
+ #include <linux/sched.h>
+ #include <linux/seccomp.h>
+@@ -586,70 +585,17 @@ static uint32_t requested_caps[2] = {0, 0};
+ static void
+ set_required_caps (void)
+ {
+- struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 };
+- struct __user_cap_data_struct data[2] = { { 0 } };
+-
+- /* Drop all non-require capabilities */
+- data[0].effective = REQUIRED_CAPS_0;
+- data[0].permitted = REQUIRED_CAPS_0;
+- data[0].inheritable = 0;
+- data[1].effective = REQUIRED_CAPS_1;
+- data[1].permitted = REQUIRED_CAPS_1;
+- data[1].inheritable = 0;
+- if (capset (&hdr, data) < 0)
+- die_with_error ("capset failed");
+ }
+
+ static void
+ drop_all_caps (bool keep_requested_caps)
+ {
+- struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 };
+- struct __user_cap_data_struct data[2] = { { 0 } };
+-
+- if (keep_requested_caps)
+- {
+- /* Avoid calling capset() unless we need to; currently
+- * systemd-nspawn at least is known to install a seccomp
+- * policy denying capset() for dubious reasons.
+- * <https://github.com/projectatomic/bubblewrap/pull/122>
+- */
+- if (!opt_cap_add_or_drop_used && real_uid == 0)
+- {
+- assert (!is_privileged);
+- return;
+- }
+- data[0].effective = requested_caps[0];
+- data[0].permitted = requested_caps[0];
+- data[0].inheritable = requested_caps[0];
+- data[1].effective = requested_caps[1];
+- data[1].permitted = requested_caps[1];
+- data[1].inheritable = requested_caps[1];
+- }
+-
+- if (capset (&hdr, data) < 0)
+- {
+- /* While the above logic ensures we don't call capset() for the primary
+- * process unless configured to do so, we still try to drop privileges for
+- * the init process unconditionally. Since due to the systemd seccomp
+- * filter that will fail, let's just ignore it.
+- */
+- if (errno == EPERM && real_uid == 0 && !is_privileged)
+- return;
+- else
+- die_with_error ("capset failed");
+- }
+ }
+
+ static bool
+ has_caps (void)
+ {
+- struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 };
+- struct __user_cap_data_struct data[2] = { { 0 } };
+-
+- if (capget (&hdr, data) < 0)
+- die_with_error ("capget failed");
+-
+- return data[0].permitted != 0 || data[1].permitted != 0;
++ return 0;
+ }
+
+ /* Most of the code here is used both to add caps to the ambient capabilities
+@@ -659,49 +605,6 @@ has_caps (void)
+ static void
+ prctl_caps (uint32_t *caps, bool do_cap_bounding, bool do_set_ambient)
+ {
+- unsigned long cap;
+-
+- /* We ignore both EINVAL and EPERM, as we are actually relying
+- * on PR_SET_NO_NEW_PRIVS to ensure the right capabilities are
+- * available. EPERM in particular can happen with old, buggy
+- * kernels. See:
+- * https://github.com/projectatomic/bubblewrap/pull/175#issuecomment-278051373
+- * https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/security/commoncap.c?id=160da84dbb39443fdade7151bc63a88f8e953077
+- */
+- for (cap = 0; cap <= CAP_LAST_CAP; cap++)
+- {
+- bool keep = FALSE;
+- if (cap < 32)
+- {
+- if (CAP_TO_MASK_0 (cap) & caps[0])
+- keep = TRUE;
+- }
+- else
+- {
+- if (CAP_TO_MASK_1 (cap) & caps[1])
+- keep = TRUE;
+- }
+-
+- if (keep && do_set_ambient)
+- {
+-#ifdef PR_CAP_AMBIENT
+- int res = prctl (PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0);
+- if (res == -1 && !(errno == EINVAL || errno == EPERM))
+- die_with_error ("Adding ambient capability %ld", cap);
+-#else
+- /* We ignore the EINVAL that results from not having PR_CAP_AMBIENT
+- * in the current kernel at runtime, so also ignore not having it
+- * in the current kernel headers at compile-time */
+-#endif
+- }
+-
+- if (!keep && do_cap_bounding)
+- {
+- int res = prctl (PR_CAPBSET_DROP, cap, 0, 0, 0);
+- if (res == -1 && !(errno == EINVAL || errno == EPERM))
+- die_with_error ("Dropping capability %ld from bounds", cap);
+- }
+- }
+ }
+
+ static void
+@@ -748,10 +651,6 @@ acquire_privs (void)
+ /* Are we setuid ? */
+ if (real_uid != euid)
+ {
+- if (euid != 0)
+- die ("Unexpected setuid user %d, should be 0", euid);
+-
+- is_privileged = TRUE;
+ /* We want to keep running as euid=0 until at the clone()
+ * operation because doing so will make the user namespace be
+ * owned by root, which makes it not ptrace:able by the user as
+@@ -763,19 +662,7 @@ acquire_privs (void)
+ * escalated filesystem access before the clone(), so we set
+ * fsuid to the uid.
+ */
+- if (setfsuid (real_uid) < 0)
+- die_with_error ("Unable to set fsuid");
+-
+- /* setfsuid can't properly report errors, check that it worked (as per manpage) */
+- new_fsuid = setfsuid (-1);
+- if (new_fsuid != real_uid)
+- die ("Unable to set fsuid (was %d)", (int)new_fsuid);
+-
+- /* We never need capabilities after execve(), so lets drop everything from the bounding set */
+- drop_cap_bounding_set (TRUE);
+-
+- /* Keep only the required capabilities for setup */
+- set_required_caps ();
++ die_with_error ("suid disabled, enable user namespaces in the kernel.");
+ }
+ else if (real_uid != 0 && has_caps ())
+ {
+@@ -786,18 +673,6 @@ acquire_privs (void)
+ }
+ else if (real_uid == 0)
+ {
+- /* If our uid is 0, default to inheriting all caps; the caller
+- * can drop them via --cap-drop. This is used by at least rpm-ostree.
+- * Note this needs to happen before the argument parsing of --cap-drop.
+- */
+- struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 };
+- struct __user_cap_data_struct data[2] = { { 0 } };
+-
+- if (capget (&hdr, data) < 0)
+- die_with_error ("capget (for uid == 0) failed");
+-
+- requested_caps[0] = data[0].effective;
+- requested_caps[1] = data[1].effective;
+ }
+
+ /* Else, we try unprivileged user namespaces */
+@@ -2043,52 +1918,16 @@ parse_args_recurse (int *argcp,
+ }
+ else if (strcmp (arg, "--cap-add") == 0)
+ {
+- cap_value_t cap;
+ if (argc < 2)
+ die ("--cap-add takes an argument");
+
+- opt_cap_add_or_drop_used = TRUE;
+-
+- if (strcasecmp (argv[1], "ALL") == 0)
+- {
+- requested_caps[0] = requested_caps[1] = 0xFFFFFFFF;
+- }
+- else
+- {
+- if (cap_from_name (argv[1], &cap) < 0)
+- die ("unknown cap: %s", argv[1]);
+-
+- if (cap < 32)
+- requested_caps[0] |= CAP_TO_MASK_0 (cap);
+- else
+- requested_caps[1] |= CAP_TO_MASK_1 (cap - 32);
+- }
+-
+ argv += 1;
+ argc -= 1;
+ }
+ else if (strcmp (arg, "--cap-drop") == 0)
+ {
+- cap_value_t cap;
+ if (argc < 2)
+- die ("--cap-drop takes an argument");
+-
+- opt_cap_add_or_drop_used = TRUE;
+-
+- if (strcasecmp (argv[1], "ALL") == 0)
+- {
+- requested_caps[0] = requested_caps[1] = 0;
+- }
+- else
+- {
+- if (cap_from_name (argv[1], &cap) < 0)
+- die ("unknown cap: %s", argv[1]);
+-
+- if (cap < 32)
+- requested_caps[0] &= ~CAP_TO_MASK_0 (cap);
+- else
+- requested_caps[1] &= ~CAP_TO_MASK_1 (cap - 32);
+- }
++ die ("--cap-add takes an argument");
+
+ argv += 1;
+ argc -= 1;
diff --git a/flatpak/flatpak/sources b/flatpak/flatpak/sources
@@ -2,3 +2,4 @@ https://github.com/flatpak/flatpak/releases/download/1.7.2/flatpak-1.7.2.tar.xz
https://github.com/pyparsing/pyparsing/releases/download/pyparsing_2.4.7/pyparsing-2.4.7.tar.gz pyparsing
patches/fix-musl.patch
patches/bubblewrap-musl.patch
+patches/no-libcap.patch