no-libcap.patch (8974B)
1 diff --git a/app/flatpak-builtins-enter.c b/app/flatpak-builtins-enter.c 2 index 44e14e9..26ea6b0 100644 3 --- a/app/flatpak-builtins-enter.c 4 +++ b/app/flatpak-builtins-enter.c 5 @@ -36,21 +36,11 @@ 6 #include "flatpak-dbus-generated.h" 7 #include "flatpak-run-private.h" 8 #include "flatpak-instance.h" 9 -#include <sys/capability.h> 10 11 static GOptionEntry options[] = { 12 { NULL } 13 }; 14 15 -static void 16 -drop_all_caps (void) 17 -{ 18 - struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 }; 19 - struct __user_cap_data_struct data[2] = { { 0 } }; 20 - 21 - capset (&hdr, data); 22 -} 23 - 24 gboolean 25 flatpak_builtin_enter (int argc, 26 char **argv, 27 @@ -242,8 +232,6 @@ flatpak_builtin_enter (int argc, 28 if (setuid (uid)) 29 return flatpak_fail (error, _("Can't switch uid")); 30 31 - drop_all_caps (); 32 - 33 envp_array = g_ptr_array_new_with_free_func (g_free); 34 for (e = environment; e < environment + environment_len; e = e + strlen (e) + 1) 35 { 36 diff --git a/subprojects/bubblewrap/bubblewrap.c b/subprojects/bubblewrap/bubblewrap.c 37 index fc2edbb..704e9e8 100644 38 --- a/subprojects/bubblewrap/bubblewrap.c 39 +++ b/subprojects/bubblewrap/bubblewrap.c 40 @@ -28,7 +28,6 @@ 41 #include <sys/eventfd.h> 42 #include <sys/fsuid.h> 43 #include <sys/signalfd.h> 44 -#include <sys/capability.h> 45 #include <sys/prctl.h> 46 #include <linux/sched.h> 47 #include <linux/seccomp.h> 48 @@ -593,70 +592,17 @@ static uint32_t requested_caps[2] = {0, 0}; 49 static void 50 set_required_caps (void) 51 { 52 - struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 }; 53 - struct __user_cap_data_struct data[2] = { { 0 } }; 54 - 55 - /* Drop all non-require capabilities */ 56 - data[0].effective = REQUIRED_CAPS_0; 57 - data[0].permitted = REQUIRED_CAPS_0; 58 - data[0].inheritable = 0; 59 - data[1].effective = REQUIRED_CAPS_1; 60 - data[1].permitted = REQUIRED_CAPS_1; 61 - data[1].inheritable = 0; 62 - if (capset (&hdr, data) < 0) 63 - die_with_error ("capset failed"); 64 } 65 66 static void 67 drop_all_caps (bool keep_requested_caps) 68 { 69 - struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 }; 70 - struct __user_cap_data_struct data[2] = { { 0 } }; 71 - 72 - if (keep_requested_caps) 73 - { 74 - /* Avoid calling capset() unless we need to; currently 75 - * systemd-nspawn at least is known to install a seccomp 76 - * policy denying capset() for dubious reasons. 77 - * <https://github.com/projectatomic/bubblewrap/pull/122> 78 - */ 79 - if (!opt_cap_add_or_drop_used && real_uid == 0) 80 - { 81 - assert (!is_privileged); 82 - return; 83 - } 84 - data[0].effective = requested_caps[0]; 85 - data[0].permitted = requested_caps[0]; 86 - data[0].inheritable = requested_caps[0]; 87 - data[1].effective = requested_caps[1]; 88 - data[1].permitted = requested_caps[1]; 89 - data[1].inheritable = requested_caps[1]; 90 - } 91 - 92 - if (capset (&hdr, data) < 0) 93 - { 94 - /* While the above logic ensures we don't call capset() for the primary 95 - * process unless configured to do so, we still try to drop privileges for 96 - * the init process unconditionally. Since due to the systemd seccomp 97 - * filter that will fail, let's just ignore it. 98 - */ 99 - if (errno == EPERM && real_uid == 0 && !is_privileged) 100 - return; 101 - else 102 - die_with_error ("capset failed"); 103 - } 104 } 105 106 static bool 107 has_caps (void) 108 { 109 - struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 }; 110 - struct __user_cap_data_struct data[2] = { { 0 } }; 111 - 112 - if (capget (&hdr, data) < 0) 113 - die_with_error ("capget failed"); 114 - 115 - return data[0].permitted != 0 || data[1].permitted != 0; 116 + return 0; 117 } 118 119 /* Most of the code here is used both to add caps to the ambient capabilities 120 @@ -666,49 +612,6 @@ has_caps (void) 121 static void 122 prctl_caps (uint32_t *caps, bool do_cap_bounding, bool do_set_ambient) 123 { 124 - unsigned long cap; 125 - 126 - /* We ignore both EINVAL and EPERM, as we are actually relying 127 - * on PR_SET_NO_NEW_PRIVS to ensure the right capabilities are 128 - * available. EPERM in particular can happen with old, buggy 129 - * kernels. See: 130 - * https://github.com/projectatomic/bubblewrap/pull/175#issuecomment-278051373 131 - * https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/security/commoncap.c?id=160da84dbb39443fdade7151bc63a88f8e953077 132 - */ 133 - for (cap = 0; cap <= CAP_LAST_CAP; cap++) 134 - { 135 - bool keep = FALSE; 136 - if (cap < 32) 137 - { 138 - if (CAP_TO_MASK_0 (cap) & caps[0]) 139 - keep = TRUE; 140 - } 141 - else 142 - { 143 - if (CAP_TO_MASK_1 (cap) & caps[1]) 144 - keep = TRUE; 145 - } 146 - 147 - if (keep && do_set_ambient) 148 - { 149 -#ifdef PR_CAP_AMBIENT 150 - int res = prctl (PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0); 151 - if (res == -1 && !(errno == EINVAL || errno == EPERM)) 152 - die_with_error ("Adding ambient capability %ld", cap); 153 -#else 154 - /* We ignore the EINVAL that results from not having PR_CAP_AMBIENT 155 - * in the current kernel at runtime, so also ignore not having it 156 - * in the current kernel headers at compile-time */ 157 -#endif 158 - } 159 - 160 - if (!keep && do_cap_bounding) 161 - { 162 - int res = prctl (PR_CAPBSET_DROP, cap, 0, 0, 0); 163 - if (res == -1 && !(errno == EINVAL || errno == EPERM)) 164 - die_with_error ("Dropping capability %ld from bounds", cap); 165 - } 166 - } 167 } 168 169 static void 170 @@ -755,10 +658,6 @@ acquire_privs (void) 171 /* Are we setuid ? */ 172 if (real_uid != euid) 173 { 174 - if (euid != 0) 175 - die ("Unexpected setuid user %d, should be 0", euid); 176 - 177 - is_privileged = TRUE; 178 /* We want to keep running as euid=0 until at the clone() 179 * operation because doing so will make the user namespace be 180 * owned by root, which makes it not ptrace:able by the user as 181 @@ -770,19 +669,7 @@ acquire_privs (void) 182 * escalated filesystem access before the clone(), so we set 183 * fsuid to the uid. 184 */ 185 - if (setfsuid (real_uid) < 0) 186 - die_with_error ("Unable to set fsuid"); 187 - 188 - /* setfsuid can't properly report errors, check that it worked (as per manpage) */ 189 - new_fsuid = setfsuid (-1); 190 - if (new_fsuid != real_uid) 191 - die ("Unable to set fsuid (was %d)", (int)new_fsuid); 192 - 193 - /* We never need capabilities after execve(), so lets drop everything from the bounding set */ 194 - drop_cap_bounding_set (TRUE); 195 - 196 - /* Keep only the required capabilities for setup */ 197 - set_required_caps (); 198 + die_with_error ("suid disabled, enable user namespaces in the kernel."); 199 } 200 else if (real_uid != 0 && has_caps ()) 201 { 202 @@ -793,18 +680,6 @@ acquire_privs (void) 203 } 204 else if (real_uid == 0) 205 { 206 - /* If our uid is 0, default to inheriting all caps; the caller 207 - * can drop them via --cap-drop. This is used by at least rpm-ostree. 208 - * Note this needs to happen before the argument parsing of --cap-drop. 209 - */ 210 - struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 }; 211 - struct __user_cap_data_struct data[2] = { { 0 } }; 212 - 213 - if (capget (&hdr, data) < 0) 214 - die_with_error ("capget (for uid == 0) failed"); 215 - 216 - requested_caps[0] = data[0].effective; 217 - requested_caps[1] = data[1].effective; 218 } 219 220 /* Else, we try unprivileged user namespaces */ 221 @@ -2187,53 +2062,17 @@ parse_args_recurse (int *argcp, 222 } 223 else if (strcmp (arg, "--cap-add") == 0) 224 { 225 - cap_value_t cap; 226 if (argc < 2) 227 die ("--cap-add takes an argument"); 228 229 - opt_cap_add_or_drop_used = TRUE; 230 - 231 - if (strcasecmp (argv[1], "ALL") == 0) 232 - { 233 - requested_caps[0] = requested_caps[1] = 0xFFFFFFFF; 234 - } 235 - else 236 - { 237 - if (cap_from_name (argv[1], &cap) < 0) 238 - die ("unknown cap: %s", argv[1]); 239 - 240 - if (cap < 32) 241 - requested_caps[0] |= CAP_TO_MASK_0 (cap); 242 - else 243 - requested_caps[1] |= CAP_TO_MASK_1 (cap - 32); 244 - } 245 - 246 argv += 1; 247 argc -= 1; 248 } 249 else if (strcmp (arg, "--cap-drop") == 0) 250 { 251 - cap_value_t cap; 252 if (argc < 2) 253 die ("--cap-drop takes an argument"); 254 255 - opt_cap_add_or_drop_used = TRUE; 256 - 257 - if (strcasecmp (argv[1], "ALL") == 0) 258 - { 259 - requested_caps[0] = requested_caps[1] = 0; 260 - } 261 - else 262 - { 263 - if (cap_from_name (argv[1], &cap) < 0) 264 - die ("unknown cap: %s", argv[1]); 265 - 266 - if (cap < 32) 267 - requested_caps[0] &= ~CAP_TO_MASK_0 (cap); 268 - else 269 - requested_caps[1] &= ~CAP_TO_MASK_1 (cap - 32); 270 - } 271 - 272 argv += 1; 273 argc -= 1; 274 }