mirror of
https://github.com/flatpak/flatpak.git
synced 2026-04-16 04:51:43 -04:00
Add generic static permissions to metadata
This allows you do do something like flatpak build-finish --add-policy=subsystem.key=v1 --add-policy=subsystem.key=v2 Which maps to this metadata keys: [Policy subsystem] key=v1;v2; You can also --remove-policy to remove values from a key. The policy values are parsed from the app and runtime metadata, and are overridable by per-app overrides and on the command line, however the values are never used by flatpak. They do end up in the flatpak-info file for the running application though, so external agents can look at them. These
This commit is contained in:
@@ -130,6 +130,7 @@ struct FlatpakContext
|
||||
GHashTable *filesystems;
|
||||
GHashTable *session_bus_policy;
|
||||
GHashTable *system_bus_policy;
|
||||
GHashTable *generic_policy;
|
||||
};
|
||||
|
||||
FlatpakContext *
|
||||
@@ -143,6 +144,8 @@ flatpak_context_new (void)
|
||||
context->filesystems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
context->session_bus_policy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
context->system_bus_policy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
context->generic_policy = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, (GDestroyNotify)g_strfreev);
|
||||
|
||||
return context;
|
||||
}
|
||||
@@ -155,6 +158,7 @@ flatpak_context_free (FlatpakContext *context)
|
||||
g_hash_table_destroy (context->filesystems);
|
||||
g_hash_table_destroy (context->session_bus_policy);
|
||||
g_hash_table_destroy (context->system_bus_policy);
|
||||
g_hash_table_destroy (context->generic_policy);
|
||||
g_slice_free (FlatpakContext, context);
|
||||
}
|
||||
|
||||
@@ -477,6 +481,38 @@ flatpak_context_set_system_bus_policy (FlatpakContext *context,
|
||||
g_hash_table_insert (context->system_bus_policy, g_strdup (name), GINT_TO_POINTER (policy));
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_context_apply_generic_policy (FlatpakContext *context,
|
||||
const char *key,
|
||||
const char *value)
|
||||
{
|
||||
GPtrArray *new = g_ptr_array_new ();
|
||||
const char **old_v;
|
||||
int i;
|
||||
|
||||
g_assert (strchr (key, '.') != NULL);
|
||||
|
||||
old_v = g_hash_table_lookup (context->generic_policy, key);
|
||||
for (i = 0; old_v != NULL && old_v[i] != NULL; i++)
|
||||
{
|
||||
const char *old = old_v[i];
|
||||
const char *cmp1 = old;
|
||||
const char *cmp2 = value;
|
||||
if (*cmp1 == '!')
|
||||
cmp1++;
|
||||
if (*cmp2 == '!')
|
||||
cmp2++;
|
||||
if (strcmp (cmp1, cmp2) != 0)
|
||||
g_ptr_array_add (new, g_strdup (old));
|
||||
}
|
||||
|
||||
g_ptr_array_add (new, g_strdup (value));
|
||||
g_ptr_array_add (new, NULL);
|
||||
|
||||
g_hash_table_insert (context->generic_policy, g_strdup (key),
|
||||
g_ptr_array_free (new, FALSE));
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_context_set_persistent (FlatpakContext *context,
|
||||
const char *path)
|
||||
@@ -693,6 +729,21 @@ flatpak_context_merge (FlatpakContext *context,
|
||||
g_hash_table_iter_init (&iter, other->system_bus_policy);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
g_hash_table_insert (context->system_bus_policy, g_strdup (key), value);
|
||||
|
||||
g_hash_table_iter_init (&iter, other->system_bus_policy);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
g_hash_table_insert (context->system_bus_policy, g_strdup (key), value);
|
||||
|
||||
g_hash_table_iter_init (&iter, other->generic_policy);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
const char **policy_values = (const char **)value;
|
||||
int i;
|
||||
|
||||
for (i = 0; policy_values[i] != NULL; i++)
|
||||
flatpak_context_apply_generic_policy (context, (char *)key, policy_values[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -950,6 +1001,63 @@ option_system_talk_name_cb (const gchar *option_name,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
option_add_generic_policy_cb (const gchar *option_name,
|
||||
const gchar *value,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
FlatpakContext *context = data;
|
||||
char *t;
|
||||
g_autofree char *key = NULL;
|
||||
const char *policy_value;
|
||||
|
||||
t = strchr (value, '=');
|
||||
if (t == NULL)
|
||||
return flatpak_fail (error, "--policy arguments must be in the form SUBSYSTEM.KEY=[!]VALUE");
|
||||
policy_value = t + 1;
|
||||
key = g_strndup (value, t - value);
|
||||
if (strchr (key, '.') == NULL)
|
||||
return flatpak_fail (error, "--policy arguments must be in the form SUBSYSTEM.KEY=[!]VALUE");
|
||||
|
||||
if (policy_value[0] == '!')
|
||||
return flatpak_fail (error, "--policy values can't start with \"!\"");
|
||||
|
||||
flatpak_context_apply_generic_policy (context, key, policy_value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
option_remove_generic_policy_cb (const gchar *option_name,
|
||||
const gchar *value,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
FlatpakContext *context = data;
|
||||
char *t;
|
||||
g_autofree char *key = NULL;
|
||||
const char *policy_value;
|
||||
g_autofree char *extended_value = NULL;
|
||||
|
||||
t = strchr (value, '=');
|
||||
if (t == NULL)
|
||||
return flatpak_fail (error, "--policy arguments must be in the form SUBSYSTEM.KEY=[!]VALUE");
|
||||
policy_value = t + 1;
|
||||
key = g_strndup (value, t - value);
|
||||
if (strchr (key, '.') == NULL)
|
||||
return flatpak_fail (error, "--policy arguments must be in the form SUBSYSTEM.KEY=[!]VALUE");
|
||||
|
||||
if (policy_value[0] == '!')
|
||||
return flatpak_fail (error, "--policy values can't start with \"!\"");
|
||||
|
||||
extended_value = g_strconcat ("!", policy_value, NULL);
|
||||
|
||||
flatpak_context_apply_generic_policy (context, key, extended_value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
option_persist_cb (const gchar *option_name,
|
||||
const gchar *value,
|
||||
@@ -980,6 +1088,8 @@ static GOptionEntry context_options[] = {
|
||||
{ "talk-name", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_talk_name_cb, N_("Allow app to talk to name on the session bus"), N_("DBUS_NAME") },
|
||||
{ "system-own-name", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_system_own_name_cb, N_("Allow app to own name on the system bus"), N_("DBUS_NAME") },
|
||||
{ "system-talk-name", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_system_talk_name_cb, N_("Allow app to talk to name on the system bus"), N_("DBUS_NAME") },
|
||||
{ "add-policy", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_add_generic_policy_cb, N_("Add generic policy option"), N_("SUBSYSTEM.KEY=VALUE") },
|
||||
{ "remove-policy", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_remove_generic_policy_cb, N_("Remove generic policy option"), N_("SUBSYSTEM.KEY=VALUE") },
|
||||
{ "persist", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_persist_cb, N_("Persist home directory"), N_("FILENAME") },
|
||||
/* This is not needed/used anymore, so hidden, but we accept it for backwards compat */
|
||||
{ "no-desktop", 0, G_OPTION_FLAG_IN_MAIN | G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &option_no_desktop_deprecated, N_("Don't require a running session (no cgroups creation)"), NULL },
|
||||
@@ -1031,6 +1141,7 @@ flatpak_context_load_metadata (FlatpakContext *context,
|
||||
GError **error)
|
||||
{
|
||||
gboolean remove;
|
||||
g_auto(GStrv) groups = NULL;
|
||||
int i;
|
||||
|
||||
if (g_key_file_has_key (metakey, FLATPAK_METADATA_GROUP_CONTEXT, FLATPAK_METADATA_KEY_SHARED, NULL))
|
||||
@@ -1204,6 +1315,33 @@ flatpak_context_load_metadata (FlatpakContext *context,
|
||||
}
|
||||
}
|
||||
|
||||
groups = g_key_file_get_groups (metakey, NULL);
|
||||
for (i = 0; groups[i] != NULL; i++)
|
||||
{
|
||||
const char *group = groups[i];
|
||||
const char *subsystem;
|
||||
int j;
|
||||
|
||||
if (g_str_has_prefix (group, FLATPAK_METADATA_GROUP_PREFIX_POLICY))
|
||||
{
|
||||
g_auto(GStrv) keys = NULL;
|
||||
subsystem = group + strlen (FLATPAK_METADATA_GROUP_PREFIX_POLICY);
|
||||
keys = g_key_file_get_keys (metakey, group, NULL, NULL);
|
||||
for (j = 0; keys != NULL && keys[j] != NULL; j++)
|
||||
{
|
||||
const char *key = keys[j];
|
||||
g_autofree char *policy_key = g_strdup_printf ("%s.%s", subsystem, key);
|
||||
g_auto(GStrv) values = NULL;
|
||||
int k;
|
||||
|
||||
values = g_key_file_get_string_list (metakey, group, key, NULL, NULL);
|
||||
for (k = 0; values != NULL && values[k] != NULL; k++)
|
||||
flatpak_context_apply_generic_policy (context, policy_key,
|
||||
values[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1226,6 +1364,8 @@ flatpak_context_save_metadata (FlatpakContext *context,
|
||||
FlatpakContextDevices devices_valid = context->devices_valid;
|
||||
FlatpakContextFeatures features_mask = context->features;
|
||||
FlatpakContextFeatures features_valid = context->features;
|
||||
g_auto(GStrv) groups = NULL;
|
||||
int i;
|
||||
|
||||
if (flatten)
|
||||
{
|
||||
@@ -1387,6 +1527,42 @@ flatpak_context_save_metadata (FlatpakContext *context,
|
||||
FLATPAK_METADATA_GROUP_ENVIRONMENT,
|
||||
(char *) key, (char *) value);
|
||||
}
|
||||
|
||||
|
||||
groups = g_key_file_get_groups (metakey, NULL);
|
||||
for (i = 0; groups[i] != NULL; i++)
|
||||
{
|
||||
const char *group = groups[i];
|
||||
if (g_str_has_prefix (group, FLATPAK_METADATA_GROUP_PREFIX_POLICY))
|
||||
g_key_file_remove_group (metakey, group, NULL);
|
||||
}
|
||||
|
||||
g_hash_table_iter_init (&iter, context->generic_policy);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
g_auto(GStrv) parts = g_strsplit ((const char *)key, ".", 2);
|
||||
g_autofree char *group = NULL;
|
||||
g_assert (parts[1] != NULL);
|
||||
const char **policy_values = (const char **)value;
|
||||
g_autoptr(GPtrArray) new = g_ptr_array_new ();
|
||||
|
||||
for (i = 0; policy_values[i] != NULL; i++)
|
||||
{
|
||||
const char *policy_value = policy_values[i];
|
||||
|
||||
if (!flatten || policy_value[0] != '!')
|
||||
g_ptr_array_add (new, (char *)policy_value);
|
||||
}
|
||||
|
||||
if (new->len > 0)
|
||||
{
|
||||
group = g_strconcat (FLATPAK_METADATA_GROUP_PREFIX_POLICY,
|
||||
parts[0], NULL);
|
||||
g_key_file_set_string_list (metakey, group, parts[1],
|
||||
(const char * const*)new->pdata,
|
||||
new->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -32,6 +32,7 @@ gboolean flatpak_run_in_transient_unit (const char *app_id,
|
||||
#define FLATPAK_METADATA_GROUP_CONTEXT "Context"
|
||||
#define FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY "Session Bus Policy"
|
||||
#define FLATPAK_METADATA_GROUP_SYSTEM_BUS_POLICY "System Bus Policy"
|
||||
#define FLATPAK_METADATA_GROUP_PREFIX_POLICY "Policy "
|
||||
#define FLATPAK_METADATA_GROUP_ENVIRONMENT "Environment"
|
||||
#define FLATPAK_METADATA_KEY_SHARED "shared"
|
||||
#define FLATPAK_METADATA_KEY_SOCKETS "sockets"
|
||||
|
||||
Reference in New Issue
Block a user