From: Marius Vlad Date: Wed, 10 Jun 2020 13:23:14 +0000 (+0300) Subject: policy: Add a deny-all policy as an example X-Git-Tag: 9.99.1~2 X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=commitdiff_plain;h=03f51daf2fcf82f4f3de6371aa6fb8a58555d5d2;p=src%2Fagl-compositor.git policy: Add a deny-all policy as an example Note this will deny any binding to the private extensions by default, if the compositor is not built with SMACK support. Defines a potential lists of applications permitted to create/display/activate surfaces/applications. Bug-AGL: SPEC-3413 Signed-off-by: Marius Vlad Change-Id: I2dbd3b3ef0d519fde7952f97e0303ff2b151aaa0 --- diff --git a/meson.build b/meson.build index ad996e8..9dd9673 100644 --- a/meson.build +++ b/meson.build @@ -139,7 +139,6 @@ srcs_agl_compositor = [ 'src/desktop.c', 'src/layout.c', 'src/policy.c', - 'src/policy-default.c', 'src/shell.c', 'shared/option-parser.c', 'shared/os-compatibility.c', @@ -150,6 +149,16 @@ srcs_agl_compositor = [ xdg_shell_protocol_c, ] +policy_to_install = get_option('policy-default') +if policy_to_install == 'auto' or policy_to_install == 'allow-all' + srcs_agl_compositor += 'src/policy-default.c' + message('Installing allow all policy') +elif policy_to_install == 'deny-all' + srcs_agl_compositor += 'src/policy-deny.c' + message('Installing deny all policy') +endif + + # From meson documentation: # In order to look for headers in a specific directory you can use args : # '-I/extra/include/dir, but this should only be used in exceptional cases for diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..72a0365 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,7 @@ +option( + 'policy-default', + type: 'combo', + choices: [ 'auto', 'allow-all', 'deny-all' ], + value: 'allow-all', + description: 'Default policy when no specific policy was set' +) diff --git a/src/policy-deny.c b/src/policy-deny.c new file mode 100644 index 0000000..5b2336a --- /dev/null +++ b/src/policy-deny.c @@ -0,0 +1,203 @@ +/* + * Copyright © 2020 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "ivi-compositor.h" +#include "policy.h" + +#ifdef HAVE_SMACK +#include +#endif + +#include +#include "shared/helpers.h" + + +static const char *const applications_permitted[] = { "homescreen", "alexa-viewer", + "launcher", "hvac", + "navigation", "mediaplayer" }; + +/* helper start searches the applications_permitted for the + * app_id + */ +static bool +ivi_policy_verify_permitted_app(const char *app_id) +{ + for (size_t i = 0; i < ARRAY_LENGTH(applications_permitted); i++) + if (strcmp(app_id, applications_permitted[i]) == 0) + return true; + + return false; +} + +static bool +ivi_policy_verify_ivi_surface(struct ivi_surface *surf) +{ + const char *app_id = weston_desktop_surface_get_app_id(surf->dsurface); + return ivi_policy_verify_permitted_app(app_id); +} + +/* + * deny-all policy implementation allows every action to be denied + * + * This is an example, that implements the API + * + * For injecting rules back in the compositor one should use ivi_policy_add() + * - policy_rule_allow_to_add is required in order to add further policy rules + * - policy_rule_try_event will be callback executed when handling the state + * change + */ +static bool +ivi_policy_default_surface_create(struct ivi_surface *surf, void *user_data) +{ + return ivi_policy_verify_ivi_surface(surf); +} + +static bool +ivi_policy_default_surface_commmited(struct ivi_surface *surf, void *user_data) +{ + return ivi_policy_verify_ivi_surface(surf); +} + +static bool +ivi_policy_default_surface_activate(struct ivi_surface *surf, void *user_data) +{ + return ivi_policy_verify_ivi_surface(surf); +} + +static bool +ivi_policy_default_surface_deactivate(struct ivi_surface *surf, void *user_data) +{ + return ivi_policy_verify_ivi_surface(surf); +} + +static bool +ivi_policy_default_surface_activate_default(struct ivi_surface *surf, void *user_data) +{ + return ivi_policy_verify_ivi_surface(surf); +} + +static bool +ivi_policy_default_surface_advertise_state_change(struct ivi_surface *surf, void *user_data) +{ + return ivi_policy_verify_ivi_surface(surf); +} + +#ifdef HAVE_SMACK +static bool +ivi_policy_default_shell_bind_interface(void *client, void *interface) +{ + struct wl_interface *shell_interface = interface; + struct wl_client *conn_client = client; + + pid_t pid, uid, gid; + int client_fd; + char *label; + bool ret = false; + + wl_client_get_credentials(conn_client, &pid, &uid, &gid); + + client_fd = wl_client_get_fd(conn_client); + if (smack_new_label_from_socket(client_fd, &label) < 0) { + return ret; + } + + if (strcmp(shell_interface->name, "agl_shell") == 0) + if (strcmp(label, "User::App::homescreen") == 0) + ret = true; + + if (strcmp(shell_interface->name, "agl_shell_desktop") == 0) + if (strcmp(label, "User::App::launcher") == 0 || + strcmp(label, "User::App::alexa-viewer") == 0 || + strcmp(label, "User::App::tbtnavi") == 0 || + strcmp(label, "User::App::hvac") == 0) + ret = true; + + if (ret) + weston_log("Client with pid %d, uid %d, gid %d, allowed " + "to bind to %s for label %s\n", pid, uid, gid, + shell_interface->name, label); + + /* client responsible for free'ing */ + free(label); + return ret; +} +#else +static bool +ivi_policy_default_shell_bind_interface(void *client, void *interface) +{ + return false; +} +#endif + +static bool +ivi_policy_default_allow_to_add(void *user_data) +{ + /* verify that policy rules can be added with ivi_policy_add() */ + return true; +} + +/* + * Policy rules added by ivi_policy_add() will be handled by this callback, and + * should be treated depending on the event. Note this is just an example. + */ +static void +ivi_policy_default_try_event(struct ivi_a_policy *a_policy) +{ + uint32_t event = a_policy->event; + + switch (event) { + case AGL_SHELL_POLICY_EVENT_SHOW: + ivi_layout_activate(a_policy->output, a_policy->app_id); + break; + case AGL_SHELL_POLICY_EVENT_HIDE: + ivi_layout_deactivate(a_policy->policy->ivi, a_policy->app_id); + default: + break; + } +} + +static const struct ivi_policy_api policy_api = { + .struct_size = sizeof(policy_api), + .surface_create = ivi_policy_default_surface_create, + .surface_commited = ivi_policy_default_surface_commmited, + .surface_activate = ivi_policy_default_surface_activate, + .surface_deactivate = ivi_policy_default_surface_deactivate, + .surface_activate_by_default = ivi_policy_default_surface_activate_default, + .surface_advertise_state_change = ivi_policy_default_surface_advertise_state_change, + .shell_bind_interface = ivi_policy_default_shell_bind_interface, + .policy_rule_allow_to_add = ivi_policy_default_allow_to_add, + .policy_rule_try_event = ivi_policy_default_try_event, +}; + +int +ivi_policy_init(struct ivi_compositor *ivi) +{ + ivi->policy = ivi_policy_create(ivi, &policy_api, ivi); + if (!ivi->policy) + return -1; + + weston_log("Installing 'deny-all' policy engine\n"); + return 0; +}