From 6667e1d3613d002cf0a0366bafef13f9ca7c1c8a Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Fri, 5 Dec 2025 15:34:18 +0100 Subject: [PATCH] context: Use the new permission system for shares and features This gives us conditionals for shares and features. So far we have no use case for this, but the system already exists, it makes the code simpler, and when we need this in the future, we don't have to wait for it to roll out. --- app/flatpak-builtins-build.c | 15 +- common/flatpak-context-private.h | 16 +- common/flatpak-context.c | 320 +++++++------------------------ common/flatpak-dir.c | 2 +- common/flatpak-run-private.h | 6 +- common/flatpak-run.c | 39 +++- doc/flatpak-metadata.xml | 10 + tests/test-exports.c | 21 +- tests/test-override.sh | 4 +- 9 files changed, 146 insertions(+), 287 deletions(-) diff --git a/app/flatpak-builtins-build.c b/app/flatpak-builtins-build.c index d0aa436e..6b549dd8 100644 --- a/app/flatpak-builtins-build.c +++ b/app/flatpak-builtins-build.c @@ -215,8 +215,10 @@ flatpak_builtin_build (int argc, char **argv, GCancellable *cancellable, GError char pid_str[64]; g_autofree char *pid_path = NULL; g_autoptr(GFile) app_id_dir = NULL; + FlatpakContextShares shares; FlatpakContextDevices devices; FlatpakContextSockets sockets; + FlatpakContextFeatures features; context = g_option_context_new (_("DIRECTORY [COMMAND [ARGUMENT…]] - Build in directory")); g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); @@ -440,6 +442,11 @@ flatpak_builtin_build (int argc, char **argv, GCancellable *cancellable, GError flatpak_context_merge (app_context, arg_context); + shares = flatpak_run_compute_allowed_shares (app_context); + devices = flatpak_run_compute_allowed_devices (app_context); + sockets = flatpak_run_compute_allowed_sockets (app_context); + features = flatpak_run_compute_allowed_features (app_context); + minimal_envp = flatpak_run_get_minimal_env (TRUE, FALSE); bwrap = flatpak_bwrap_new (minimal_envp); flatpak_bwrap_add_args (bwrap, flatpak_get_bwrap (), NULL); @@ -452,7 +459,7 @@ flatpak_builtin_build (int argc, char **argv, GCancellable *cancellable, GError if (custom_usr) run_flags |= FLATPAK_RUN_FLAG_WRITABLE_ETC; - run_flags |= flatpak_context_get_run_flags (app_context); + run_flags |= flatpak_context_features_to_run_flags (features); /* Unless manually specified, we disable dbus proxy */ if (!flatpak_context_get_needs_session_bus_proxy (arg_context)) @@ -553,9 +560,6 @@ flatpak_builtin_build (int argc, char **argv, GCancellable *cancellable, GError "--bind", flatpak_file_get_path_cached (res_files), extension_point, NULL); - devices = flatpak_run_compute_allowed_devices (app_context); - sockets = flatpak_run_compute_allowed_sockets (app_context); - if (!flatpak_run_add_app_info_args (bwrap, app_files, app_files, NULL, app_extensions, runtime_files, runtime_files, runtime_deploy_data, runtime_extensions, @@ -571,7 +575,8 @@ flatpak_builtin_build (int argc, char **argv, GCancellable *cancellable, GError return FALSE; if (!flatpak_run_add_environment_args (bwrap, app_info_path, run_flags, id, - app_context, devices, sockets, + app_context, + shares, devices, sockets, features, app_id_dir, NULL, -1, instance_id, NULL, cancellable, error)) return FALSE; diff --git a/common/flatpak-context-private.h b/common/flatpak-context-private.h index 3c893adc..b8385b5a 100644 --- a/common/flatpak-context-private.h +++ b/common/flatpak-context-private.h @@ -89,12 +89,10 @@ typedef enum { struct FlatpakContext { - FlatpakContextShares shares; - FlatpakContextShares shares_valid; + GHashTable *shares_permissions; GHashTable *socket_permissions; GHashTable *device_permissions; - FlatpakContextFeatures features; - FlatpakContextFeatures features_valid; + GHashTable *features_permissions; GHashTable *env_vars; GHashTable *persistent; GHashTable *filesystems; @@ -148,7 +146,7 @@ char * flatpak_context_devices_to_usb_list (GHashTable *devices, gboolean hidden); void flatpak_context_to_args (FlatpakContext *context, GPtrArray *args); -FlatpakRunFlags flatpak_context_get_run_flags (FlatpakContext *context); +FlatpakRunFlags flatpak_context_features_to_run_flags (FlatpakContextFeatures features); void flatpak_context_add_bus_filters (FlatpakContext *context, const char *app_id, FlatpakBus bus, @@ -164,9 +162,6 @@ void flatpak_context_reset_permissions (FlatpakContext *context); void flatpak_context_reset_non_permissions (FlatpakContext *context); void flatpak_context_make_sandboxed (FlatpakContext *context); -gboolean flatpak_context_allows_features (FlatpakContext *context, - FlatpakContextFeatures features); - FlatpakContext *flatpak_context_load_for_deploy (FlatpakDeploy *deploy, GError **error); @@ -208,9 +203,14 @@ gboolean flatpak_context_get_allowed_exports (FlatpakContext *context, char ***allowed_prefixes_out, gboolean *require_exact_match_out); + +FlatpakContextShares flatpak_context_compute_allowed_shares (FlatpakContext *context, + FlatpakContextConditionEvaluator evaluator); FlatpakContextSockets flatpak_context_compute_allowed_sockets (FlatpakContext *context, FlatpakContextConditionEvaluator evaluator); FlatpakContextDevices flatpak_context_compute_allowed_devices (FlatpakContext *context, FlatpakContextConditionEvaluator evaluator); +FlatpakContextFeatures flatpak_context_compute_allowed_features (FlatpakContext *context, + FlatpakContextConditionEvaluator evaluator); #endif /* __FLATPAK_CONTEXT_H__ */ diff --git a/common/flatpak-context.c b/common/flatpak-context.c index a0b4bf7d..99c8e3e7 100644 --- a/common/flatpak-context.c +++ b/common/flatpak-context.c @@ -161,6 +161,10 @@ flatpak_permission_dup (FlatpakPermission *permission) FlatpakPermission *copy = NULL; copy = flatpak_permission_new (); + + if (!permission) + return copy; + copy->allowed = permission->allowed; copy->reset = permission->reset; @@ -1192,8 +1196,10 @@ flatpak_context_new (void) g_free, (GDestroyNotify) flatpak_usb_query_free); context->hidden_usb_devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) flatpak_usb_query_free); + context->shares_permissions = flatpak_permissions_new (); context->socket_permissions = flatpak_permissions_new (); context->device_permissions = flatpak_permissions_new (); + context->features_permissions = flatpak_permissions_new (); return context; } @@ -1210,8 +1216,10 @@ flatpak_context_free (FlatpakContext *context) g_hash_table_destroy (context->generic_policy); g_hash_table_destroy (context->enumerable_usb_devices); g_hash_table_destroy (context->hidden_usb_devices); + g_hash_table_destroy (context->shares_permissions); g_hash_table_destroy (context->device_permissions); g_hash_table_destroy (context->socket_permissions); + g_hash_table_destroy (context->features_permissions); g_slice_free (FlatpakContext, context); } @@ -1229,49 +1237,6 @@ flatpak_context_bitmask_from_string (const char *name, const char **names) return 0; } -static void -flatpak_context_bitmask_to_string (guint32 enabled, - guint32 valid, - const char **names, - GPtrArray *array) -{ - guint32 i; - - for (i = 0; names[i] != NULL; i++) - { - guint32 bitmask = 1 << i; - - if (valid & bitmask) - { - if (enabled & bitmask) - g_ptr_array_add (array, g_strdup (names[i])); - else - g_ptr_array_add (array, g_strdup_printf ("!%s", names[i])); - } - } -} - -static void -flatpak_context_bitmask_to_args (guint32 enabled, guint32 valid, const char **names, - const char *enable_arg, const char *disable_arg, - GPtrArray *args) -{ - guint32 i; - - for (i = 0; names[i] != NULL; i++) - { - guint32 bitmask = 1 << i; - if (valid & bitmask) - { - if (enabled & bitmask) - g_ptr_array_add (args, g_strdup_printf ("%s=%s", enable_arg, names[i])); - else - g_ptr_array_add (args, g_strdup_printf ("%s=%s", disable_arg, names[i])); - } - } -} - - static FlatpakContextShares flatpak_context_share_from_string (const char *string, GError **error) { @@ -1287,30 +1252,6 @@ flatpak_context_share_from_string (const char *string, GError **error) return shares; } -static char ** -flatpak_context_shared_to_string (FlatpakContextShares shares, - FlatpakContextShares valid) -{ - g_autoptr (GPtrArray) array = g_ptr_array_new_with_free_func (g_free); - - flatpak_context_bitmask_to_string (shares, valid, - flatpak_context_shares, - array); - - g_ptr_array_add (array, NULL); - return (char **) g_ptr_array_free (g_steal_pointer (&array), FALSE); -} - -static void -flatpak_context_shared_to_args (FlatpakContext *context, - GPtrArray *args) -{ - flatpak_context_bitmask_to_args (context->shares, context->shares_valid, - flatpak_context_shares, - "--share", "--unshare", - args); -} - static FlatpakPolicy flatpak_policy_from_string (const char *string, GError **error) { @@ -1412,61 +1353,6 @@ flatpak_context_feature_from_string (const char *string, GError **error) return feature; } -static char ** -flatpak_context_features_to_string (FlatpakContextFeatures features, FlatpakContextFeatures valid) -{ - g_autoptr (GPtrArray) array = g_ptr_array_new_with_free_func (g_free); - - flatpak_context_bitmask_to_string (features, valid, - flatpak_context_features, - array); - - g_ptr_array_add (array, NULL); - return (char **) g_ptr_array_free (g_steal_pointer (&array), FALSE); -} - -static void -flatpak_context_features_to_args (FlatpakContext *context, - GPtrArray *args) -{ - flatpak_context_bitmask_to_args (context->features, context->features_valid, - flatpak_context_features, - "--allow", "--disallow", - args); -} - -static void -flatpak_context_add_shares (FlatpakContext *context, - FlatpakContextShares shares) -{ - context->shares_valid |= shares; - context->shares |= shares; -} - -static void -flatpak_context_remove_shares (FlatpakContext *context, - FlatpakContextShares shares) -{ - context->shares_valid |= shares; - context->shares &= ~shares; -} - -static void -flatpak_context_add_features (FlatpakContext *context, - FlatpakContextFeatures features) -{ - context->features_valid |= features; - context->features |= features; -} - -static void -flatpak_context_remove_features (FlatpakContext *context, - FlatpakContextFeatures features) -{ - context->features_valid |= features; - context->features &= ~features; -} - static void flatpak_context_set_env_var (FlatpakContext *context, const char *name, @@ -2097,17 +1983,14 @@ flatpak_context_merge (FlatpakContext *context, GHashTableIter iter; gpointer key, value; - context->shares &= ~other->shares_valid; - context->shares |= other->shares; - context->shares_valid |= other->shares_valid; - context->features &= ~other->features_valid; - context->features |= other->features; - context->features_valid |= other->features_valid; - + flatpak_permissions_merge (context->shares_permissions, + other->shares_permissions); flatpak_permissions_merge (context->socket_permissions, other->socket_permissions); flatpak_permissions_merge (context->device_permissions, other->device_permissions); + flatpak_permissions_merge (context->features_permissions, + other->features_permissions); g_hash_table_iter_init (&iter, other->env_vars); while (g_hash_table_iter_next (&iter, &key, &value)) @@ -2173,7 +2056,7 @@ option_share_cb (const gchar *option_name, if (share == 0) return FALSE; - flatpak_context_add_shares (context, share); + flatpak_permissions_set_allowed (context->shares_permissions, value); return TRUE; } @@ -2191,7 +2074,7 @@ option_unshare_cb (const gchar *option_name, if (share == 0) return FALSE; - flatpak_context_remove_shares (context, share); + flatpak_permissions_set_not_allowed (context->shares_permissions, value); return TRUE; } @@ -2374,7 +2257,7 @@ option_allow_cb (const gchar *option_name, if (feature == 0) return FALSE; - flatpak_context_add_features (context, feature); + flatpak_permissions_set_allowed (context->features_permissions, value); return TRUE; } @@ -2392,7 +2275,7 @@ option_disallow_cb (const gchar *option_name, if (feature == 0) return FALSE; - flatpak_context_remove_features (context, feature); + flatpak_permissions_set_not_allowed (context->features_permissions, value); return TRUE; } @@ -2862,52 +2745,6 @@ parse_negated (const char *option, gboolean *negated) return option; } -static void -flatpak_context_load_share (FlatpakContext *context, - const char *share_str) -{ - FlatpakContextShares share; - gboolean remove; - - share = - flatpak_context_share_from_string (parse_negated (share_str, &remove), - NULL); - - if (share == 0) - { - g_info ("Unknown share type %s", share_str); - return; - } - - if (remove) - flatpak_context_remove_shares (context, share); - else - flatpak_context_add_shares (context, share); -} - -static void -flatpak_context_load_feature (FlatpakContext *context, - const char *feature_str) -{ - FlatpakContextFeatures feature; - gboolean remove; - - feature = - flatpak_context_feature_from_string (parse_negated (feature_str, &remove), - NULL); - - if (feature == 0) - { - g_info ("Unknown feature type %s", feature_str); - return; - } - - if (remove) - flatpak_context_remove_features (context, feature); - else - flatpak_context_add_features (context, feature); -} - /* * Merge the FLATPAK_METADATA_GROUP_CONTEXT, * FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY, @@ -2933,8 +2770,8 @@ flatpak_context_load_metadata (FlatpakContext *context, if (shares == NULL) return FALSE; - for (i = 0; shares[i] != NULL; i++) - flatpak_context_load_share (context, shares[i]); + if (!flatpak_permissions_from_strv (context->shares_permissions, (const char **)shares, error)) + return FALSE; } if (g_key_file_has_key (metakey, FLATPAK_METADATA_GROUP_CONTEXT, FLATPAK_METADATA_KEY_SOCKETS, NULL)) @@ -2967,8 +2804,8 @@ flatpak_context_load_metadata (FlatpakContext *context, if (features == NULL) return FALSE; - for (i = 0; features[i] != NULL; i++) - flatpak_context_load_feature (context, features[i]); + if (!flatpak_permissions_from_strv (context->features_permissions, (const char **)features, error)) + return FALSE; } if (g_key_file_has_key (metakey, FLATPAK_METADATA_GROUP_CONTEXT, FLATPAK_METADATA_KEY_FILESYSTEMS, NULL)) @@ -3221,34 +3058,14 @@ flatpak_context_save_metadata (FlatpakContext *context, g_autoptr(GPtrArray) unset_env = NULL; GHashTableIter iter; gpointer key, value; - FlatpakContextShares shares_mask = context->shares; - FlatpakContextShares shares_valid = context->shares_valid; - FlatpakContextFeatures features_mask = context->features; - FlatpakContextFeatures features_valid = context->features_valid; g_auto(GStrv) groups = NULL; int i; - if (flatten) - { - /* A flattened format means we don't expect this to be merged on top of - another context. In that case we never need to negate any flags. - We calculate this by removing the zero parts of the mask from the valid set. - */ - /* First we make sure only the valid parts of the mask are set, in case we - got some leftover */ - shares_mask &= shares_valid; - features_mask &= features_valid; - - /* Then just set the valid set to be the mask set */ - shares_valid = shares_mask; - features_valid = features_mask; - } - - shared = flatpak_context_shared_to_string (shares_mask, shares_valid); + shared = flatpak_permissions_to_strv (context->shares_permissions, flatten); g_autoptr(GHashTable) socket_permissions = flatpak_decanonicalize_x11_permissions (context->socket_permissions); sockets = flatpak_permissions_to_strv (socket_permissions, flatten); devices = flatpak_permissions_to_strv (context->device_permissions, flatten); - features = flatpak_context_features_to_string (features_mask, features_valid); + features = flatpak_permissions_to_strv (context->features_permissions, flatten); if (shared[0] != NULL) { @@ -3503,12 +3320,6 @@ flatpak_context_get_needs_system_bus_proxy (FlatpakContext *context) return g_hash_table_size (context->system_bus_policy) > 0; } -static gboolean -adds_flags (guint32 old_flags, guint32 new_flags) -{ - return (new_flags & ~old_flags) != 0; -} - static gboolean adds_bus_policy (GHashTable *old, GHashTable *new) { @@ -3608,18 +3419,15 @@ gboolean flatpak_context_adds_permissions (FlatpakContext *old, FlatpakContext *new) { + g_autoptr(GHashTable) old_features_permissions = NULL; g_autoptr(GHashTable) old_socket_permissions = NULL; - guint32 harmless_features; + old_features_permissions = flatpak_permissions_dup (old->features_permissions); /* We allow upgrade to multiarch, that is really not a huge problem. * Similarly, having sensible semantics for /dev/shm is * not a security concern. */ - harmless_features = (FLATPAK_CONTEXT_FEATURE_MULTIARCH | - FLATPAK_CONTEXT_FEATURE_PER_APP_DEV_SHM); - - if (adds_flags (old->shares & old->shares_valid, - new->shares & new->shares_valid)) - return TRUE; + flatpak_permissions_set_allowed (old_features_permissions, "multiarch"); + flatpak_permissions_set_allowed (old_features_permissions, "per-app-dev-shm"); old_socket_permissions = flatpak_permissions_dup (old->socket_permissions); /* If we used to allow X11, also allow new fallback X11, @@ -3627,6 +3435,10 @@ flatpak_context_adds_permissions (FlatpakContext *old, if (flatpak_permissions_allows_unconditionally (old_socket_permissions, "x11")) flatpak_permissions_set_allowed (old_socket_permissions, "fallback-x11"); + if (flatpak_permissions_adds_permissions (old->shares_permissions, + new->shares_permissions)) + return TRUE; + if (flatpak_permissions_adds_permissions (old_socket_permissions, new->socket_permissions)) return TRUE; @@ -3635,9 +3447,9 @@ flatpak_context_adds_permissions (FlatpakContext *old, new->device_permissions)) return TRUE; - if (adds_flags ((old->features & old->features_valid) | harmless_features, - new->features & new->features_valid)) - return TRUE; + if (flatpak_permissions_adds_permissions (old_features_permissions, + new->features_permissions)) + return TRUE; if (adds_bus_policy (old->session_bus_policy, new->session_bus_policy)) return TRUE; @@ -3660,13 +3472,6 @@ flatpak_context_adds_permissions (FlatpakContext *old, return FALSE; } -gboolean -flatpak_context_allows_features (FlatpakContext *context, - FlatpakContextFeatures features) -{ - return (context->features & features) == features; -} - char * flatpak_context_devices_to_usb_list (GHashTable *devices, gboolean hidden) @@ -3695,8 +3500,10 @@ flatpak_context_to_args (FlatpakContext *context, gpointer key, value; char *usb_list = NULL; - flatpak_context_shared_to_args (context, args); - flatpak_context_features_to_args (context, args); + flatpak_permissions_to_args (context->features_permissions, + "allow", "disallow", args); + flatpak_permissions_to_args (context->shares_permissions, + "share", "unshare", args); flatpak_permissions_to_args (context->device_permissions, "device", "nodevice", args); flatpak_permissions_to_args (context->socket_permissions, @@ -3839,14 +3646,10 @@ flatpak_context_reset_non_permissions (FlatpakContext *context) void flatpak_context_reset_permissions (FlatpakContext *context) { - context->shares_valid = 0; - context->features_valid = 0; - - context->shares = 0; - context->features = 0; - + g_hash_table_remove_all (context->shares_permissions); g_hash_table_remove_all (context->socket_permissions); g_hash_table_remove_all (context->device_permissions); + g_hash_table_remove_all (context->features_permissions); g_hash_table_remove_all (context->persistent); g_hash_table_remove_all (context->filesystems); g_hash_table_remove_all (context->session_bus_policy); @@ -3861,14 +3664,20 @@ flatpak_context_make_sandboxed (FlatpakContext *context) /* We drop almost everything from the app permission, except * multiarch which is inherited, to make sure app code keeps * running. */ - context->shares_valid &= 0; - context->features_valid &= FLATPAK_CONTEXT_FEATURE_MULTIARCH; - - context->shares &= context->shares_valid; - context->features &= context->features_valid; + FlatpakPermission *multiarch = + g_hash_table_lookup (context->features_permissions, "multiarch"); + g_hash_table_remove_all (context->shares_permissions); g_hash_table_remove_all (context->socket_permissions); g_hash_table_remove_all (context->device_permissions); + g_hash_table_remove_all (context->features_permissions); + + if (multiarch) + { + g_hash_table_insert (context->features_permissions, + g_strdup ("multiarch"), + flatpak_permission_dup (multiarch)); + } g_hash_table_remove_all (context->persistent); g_hash_table_remove_all (context->filesystems); @@ -4214,20 +4023,20 @@ flatpak_context_get_exports (FlatpakContext *context, } FlatpakRunFlags -flatpak_context_get_run_flags (FlatpakContext *context) +flatpak_context_features_to_run_flags (FlatpakContextFeatures features) { FlatpakRunFlags flags = 0; - if (flatpak_context_allows_features (context, FLATPAK_CONTEXT_FEATURE_DEVEL)) + if (features & FLATPAK_CONTEXT_FEATURE_DEVEL) flags |= FLATPAK_RUN_FLAG_DEVEL; - if (flatpak_context_allows_features (context, FLATPAK_CONTEXT_FEATURE_MULTIARCH)) + if (features & FLATPAK_CONTEXT_FEATURE_MULTIARCH) flags |= FLATPAK_RUN_FLAG_MULTIARCH; - if (flatpak_context_allows_features (context, FLATPAK_CONTEXT_FEATURE_BLUETOOTH)) + if (features & FLATPAK_CONTEXT_FEATURE_BLUETOOTH) flags |= FLATPAK_RUN_FLAG_BLUETOOTH; - if (flatpak_context_allows_features (context, FLATPAK_CONTEXT_FEATURE_CANBUS)) + if (features & FLATPAK_CONTEXT_FEATURE_CANBUS) flags |= FLATPAK_RUN_FLAG_CANBUS; return flags; @@ -4634,6 +4443,15 @@ flatpak_context_dump (FlatpakContext *context, } } +FlatpakContextShares +flatpak_context_compute_allowed_shares (FlatpakContext *context, + FlatpakContextConditionEvaluator evaluator) +{ + return flatpak_permissions_compute_allowed (context->shares_permissions, + flatpak_context_shares, + evaluator); +} + FlatpakContextSockets flatpak_context_compute_allowed_sockets (FlatpakContext *context, FlatpakContextConditionEvaluator evaluator) @@ -4651,3 +4469,13 @@ flatpak_context_compute_allowed_devices (FlatpakContext *conte flatpak_context_devices, evaluator); } + + +FlatpakContextFeatures +flatpak_context_compute_allowed_features (FlatpakContext *context, + FlatpakContextConditionEvaluator evaluator) +{ + return flatpak_permissions_compute_allowed (context->features_permissions, + flatpak_context_features, + evaluator); +} diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index f1e29de5..c15e993d 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -9321,7 +9321,7 @@ apply_extra_data (FlatpakDir *self, app_context = flatpak_context_new (); if (!flatpak_run_add_environment_args (bwrap, NULL, run_flags, id, - app_context, 0, 0, + app_context, 0, 0, 0, 0, NULL, NULL, -1, NULL, NULL, cancellable, error)) return FALSE; diff --git a/common/flatpak-run-private.h b/common/flatpak-run-private.h index 2dc08acf..d46996de 100644 --- a/common/flatpak-run-private.h +++ b/common/flatpak-run-private.h @@ -51,8 +51,10 @@ gboolean flatpak_run_add_environment_args (FlatpakBwrap *bwrap, FlatpakRunFlags flags, const char *app_id, FlatpakContext *context, + FlatpakContextShares shares, FlatpakContextDevices devices, FlatpakContextSockets sockets, + FlatpakContextFeatures features, GFile *app_id_dir, GPtrArray *previous_app_id_dirs, int per_app_dir_lock_fd, @@ -125,8 +127,10 @@ gboolean flatpak_run_app (FlatpakDecomposed *app_ref, GCancellable *cancellable, GError **error); -FlatpakContextDevices flatpak_run_compute_allowed_devices (FlatpakContext *context); +FlatpakContextShares flatpak_run_compute_allowed_shares (FlatpakContext *context); +FlatpakContextDevices flatpak_run_compute_allowed_devices (FlatpakContext *context); FlatpakContextSockets flatpak_run_compute_allowed_sockets (FlatpakContext *context); +FlatpakContextFeatures flatpak_run_compute_allowed_features (FlatpakContext *context); #endif /* __FLATPAK_RUN_H__ */ diff --git a/common/flatpak-run.c b/common/flatpak-run.c index 15f59065..6c319231 100644 --- a/common/flatpak-run.c +++ b/common/flatpak-run.c @@ -288,8 +288,10 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap, FlatpakRunFlags flags, const char *app_id, FlatpakContext *context, + FlatpakContextShares shares, FlatpakContextDevices devices, FlatpakContextSockets sockets, + FlatpakContextFeatures features, GFile *app_id_dir, GPtrArray *previous_app_id_dirs, int per_app_dir_lock_fd, @@ -305,13 +307,13 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap, gboolean home_access = FALSE; gboolean sandboxed = (flags & FLATPAK_RUN_FLAG_SANDBOX) != 0; - if ((context->shares & FLATPAK_CONTEXT_SHARED_IPC) == 0) + if ((shares & FLATPAK_CONTEXT_SHARED_IPC) == 0) { g_info ("Disallowing ipc access"); flatpak_bwrap_add_args (bwrap, "--unshare-ipc", NULL); } - if ((context->shares & FLATPAK_CONTEXT_SHARED_NETWORK) == 0) + if ((shares & FLATPAK_CONTEXT_SHARED_NETWORK) == 0) { g_info ("Disallowing network access"); flatpak_bwrap_add_args (bwrap, "--unshare-net", NULL); @@ -331,7 +333,7 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap, * shared /dev. The host and all sandboxes and subsandboxes * all share /dev/shm */ } - else if ((context->features & FLATPAK_CONTEXT_FEATURE_PER_APP_DEV_SHM) + else if ((features & FLATPAK_CONTEXT_FEATURE_PER_APP_DEV_SHM) && per_app_dir_lock_fd >= 0) { g_autofree char *shared_dev_shm = NULL; @@ -374,7 +376,7 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap, "--bind", "/run/shm", "/run/shm", NULL); } - else if ((context->features & FLATPAK_CONTEXT_FEATURE_PER_APP_DEV_SHM) + else if ((features & FLATPAK_CONTEXT_FEATURE_PER_APP_DEV_SHM) && per_app_dir_lock_fd >= 0) { g_autofree char *shared_dev_shm = NULL; @@ -477,7 +479,7 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap, if (real_dev_shm != NULL) flatpak_bwrap_add_args (bwrap, "--bind", real_dev_shm, "/dev/shm", NULL); } - else if ((context->features & FLATPAK_CONTEXT_FEATURE_PER_APP_DEV_SHM) + else if ((features & FLATPAK_CONTEXT_FEATURE_PER_APP_DEV_SHM) && per_app_dir_lock_fd >= 0) { g_autofree char *shared_dev_shm = NULL; @@ -530,7 +532,7 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap, flatpak_context_append_bwrap_filesystem (context, bwrap, app_id, app_id_dir, exports, xdg_dirs_conf, home_access); - flatpak_run_add_socket_args_environment (bwrap, context->shares, sockets, app_id, instance_id); + flatpak_run_add_socket_args_environment (bwrap, shares, sockets, app_id, instance_id); flatpak_run_add_session_dbus_args (bwrap, proxy_arg_bwrap, sockets, context, flags, app_id); flatpak_run_add_system_dbus_args (bwrap, proxy_arg_bwrap, sockets, context, flags); flatpak_run_add_a11y_dbus_args (bwrap, proxy_arg_bwrap, context, flags, app_id); @@ -2947,6 +2949,13 @@ open_namespace_fd_if_needed (const char *path, return -1; } +FlatpakContextShares +flatpak_run_compute_allowed_shares (FlatpakContext *context) +{ + return flatpak_context_compute_allowed_shares (context, + flatpak_run_evaluate_conditions); +} + FlatpakContextDevices flatpak_run_compute_allowed_devices (FlatpakContext *context) { @@ -2961,6 +2970,13 @@ flatpak_run_compute_allowed_sockets (FlatpakContext *context) flatpak_run_evaluate_conditions); } +FlatpakContextFeatures +flatpak_run_compute_allowed_features (FlatpakContext *context) +{ + return flatpak_context_compute_allowed_features (context, + flatpak_run_evaluate_conditions); +} + gboolean flatpak_run_app (FlatpakDecomposed *app_ref, FlatpakDeploy *app_deploy, @@ -3032,8 +3048,10 @@ flatpak_run_app (FlatpakDecomposed *app_ref, const char *app_target_path = "/app"; const char *runtime_target_path = "/usr"; struct stat s; + FlatpakContextShares shares; FlatpakContextDevices devices; FlatpakContextSockets sockets; + FlatpakContextFeatures features; g_assert (run_environ != NULL); @@ -3164,8 +3182,10 @@ flatpak_run_app (FlatpakDecomposed *app_ref, flatpak_context_dump (app_context, "Final context"); + shares = flatpak_run_compute_allowed_shares (app_context); devices = flatpak_run_compute_allowed_devices (app_context); sockets = flatpak_run_compute_allowed_sockets (app_context); + features = flatpak_run_compute_allowed_features (app_context); original_runtime_files = flatpak_deploy_get_files (runtime_deploy); @@ -3441,7 +3461,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref, flatpak_bwrap_add_fd (bwrap, ld_so_fd); } - flags |= flatpak_context_get_run_flags (app_context); + flags |= flatpak_context_features_to_run_flags (features); if (!flatpak_run_setup_base_argv (bwrap, runtime_files, app_id_dir, app_arch, flags, error)) return FALSE; @@ -3504,7 +3524,8 @@ flatpak_run_app (FlatpakDecomposed *app_ref, add_document_portal_args (bwrap, app_id, &doc_mount_path); if (!flatpak_run_add_environment_args (bwrap, app_info_path, flags, - app_id, app_context, devices, sockets, + app_id, app_context, + shares, devices, sockets, features, app_id_dir, previous_app_id_dirs, per_app_dir_lock_fd, instance_id, &exports, cancellable, error)) @@ -3520,7 +3541,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref, NULL); } - flatpak_run_add_socket_args_late (bwrap, app_context->shares); + flatpak_run_add_socket_args_late (bwrap, shares); add_font_path_args (bwrap); add_icon_path_args (bwrap); diff --git a/doc/flatpak-metadata.xml b/doc/flatpak-metadata.xml index 6a8f5e67..92bb02b1 100644 --- a/doc/flatpak-metadata.xml +++ b/doc/flatpak-metadata.xml @@ -244,6 +244,11 @@ sockets=!x11;x11;if:x11:!has-wayland; List of subsystems to share with the host system. Possible subsystems: network, ipc. Available since 0.3. + + This option supports conditional permissions. + See Conditional Permissions + for details on how to share subsystem access conditionally + based on runtime conditions. @@ -663,6 +668,11 @@ sockets=!x11;x11;if:x11:!has-wayland; indicate the absence of that feature, for example if development and debugging are not allowed. + + This option supports conditional permissions. + See Conditional Permissions + for details on how to allow features based + conditionally on runtime conditions. diff --git a/tests/test-exports.c b/tests/test-exports.c index a93bfe05..851be370 100644 --- a/tests/test-exports.c +++ b/tests/test-exports.c @@ -177,13 +177,10 @@ test_empty_context (void) g_assert_cmpuint (g_hash_table_size (context->session_bus_policy), ==, 0); g_assert_cmpuint (g_hash_table_size (context->system_bus_policy), ==, 0); g_assert_cmpuint (g_hash_table_size (context->generic_policy), ==, 0); + g_assert_cmpuint (g_hash_table_size (context->shares_permissions), ==, 0); g_assert_cmpuint (g_hash_table_size (context->socket_permissions), ==, 0); g_assert_cmpuint (g_hash_table_size (context->device_permissions), ==, 0); - g_assert_cmpuint (context->shares, ==, 0); - g_assert_cmpuint (context->shares_valid, ==, 0); - g_assert_cmpuint (context->features, ==, 0); - g_assert_cmpuint (context->features_valid, ==, 0); - g_assert_cmpuint (flatpak_context_get_run_flags (context), ==, 0); + g_assert_cmpuint (g_hash_table_size (context->features_permissions), ==, 0); exports = flatpak_context_get_exports (context, "com.example.App"); g_assert_nonnull (exports); @@ -266,10 +263,10 @@ test_full_context (void) flatpak_context_load_metadata (context, keyfile, &error); g_assert_no_error (error); - g_assert_cmpuint (context->shares, ==, + FlatpakContextShares shares = flatpak_context_compute_allowed_shares (context, NULL); + g_assert_cmpuint (shares, ==, (FLATPAK_CONTEXT_SHARED_NETWORK | FLATPAK_CONTEXT_SHARED_IPC)); - g_assert_cmpuint (context->shares_valid, ==, context->shares); FlatpakContextDevices devices = flatpak_context_compute_allowed_devices (context, NULL); g_assert_cmpuint (devices, ==, (FLATPAK_CONTEXT_DEVICE_DRI | @@ -286,19 +283,13 @@ test_full_context (void) FLATPAK_CONTEXT_SOCKET_SSH_AUTH | FLATPAK_CONTEXT_SOCKET_PCSC | FLATPAK_CONTEXT_SOCKET_CUPS)); - g_assert_cmpuint (context->features, ==, + FlatpakContextFeatures features = flatpak_context_compute_allowed_features (context, NULL); + g_assert_cmpuint (features, ==, (FLATPAK_CONTEXT_FEATURE_DEVEL | FLATPAK_CONTEXT_FEATURE_MULTIARCH | FLATPAK_CONTEXT_FEATURE_BLUETOOTH | FLATPAK_CONTEXT_FEATURE_CANBUS | FLATPAK_CONTEXT_FEATURE_PER_APP_DEV_SHM)); - g_assert_cmpuint (context->features_valid, ==, context->features); - - g_assert_cmpuint (flatpak_context_get_run_flags (context), ==, - (FLATPAK_RUN_FLAG_DEVEL | - FLATPAK_RUN_FLAG_MULTIARCH | - FLATPAK_RUN_FLAG_BLUETOOTH | - FLATPAK_RUN_FLAG_CANBUS)); g_assert_cmpuint (g_hash_table_size (context->env_vars), ==, 3); g_assert_true (g_hash_table_contains (context->env_vars, "LD_AUDIT")); diff --git a/tests/test-override.sh b/tests/test-override.sh index 8c9c719b..3de3ddf0 100755 --- a/tests/test-override.sh +++ b/tests/test-override.sh @@ -61,7 +61,7 @@ ${FLATPAK} override --user --unshare=ipc org.test.Hello ${FLATPAK} override --user --show org.test.Hello > override assert_file_has_content override "^\[Context\]$" -assert_file_has_content override "^shared=network;!ipc;$" +assert_file_has_content override "^shared=!ipc;network;$" ok "override --share" @@ -85,7 +85,7 @@ ${FLATPAK} override --user --disallow=bluetooth org.test.Hello ${FLATPAK} override --user --show org.test.Hello > override assert_file_has_content override "^\[Context\]$" -assert_file_has_content override "^features=multiarch;!bluetooth;$" +assert_file_has_content override "^features=!bluetooth;multiarch;$" ok "override --allow"