Send unique keymap fds to clients

Summary:
Prevent wayland clients from being able to destroy the compositor's
singleton keymap by making individual copies for each client.

Reviewers: zmike, devilhorns

Reviewed By: zmike, devilhorns

Subscribers: cedric

Tags: #enlightenment-git

Differential Revision: https://phab.enlightenment.org/D6861
This commit is contained in:
Derek Foreman 2018-08-17 12:28:49 -05:00 committed by Derek Foreman
parent 0fd5552c3b
commit a037001031
5 changed files with 51 additions and 51 deletions

View File

@ -266,9 +266,8 @@ struct _E_Comp_Wl_Data
struct xkb_keymap *keymap;
struct xkb_context *context;
struct xkb_state *state;
int fd;
size_t size;
char *area;
char *map_string;
int map_size;
} xkb;
E_Comp_Wl_Extension_Data *extensions;
@ -447,6 +446,8 @@ e_policy_wl_aux_message_send(E_Client *ec,
const char *val,
Eina_List *options);
E_API void e_comp_wl_input_keymap_send(struct wl_resource *res);
# ifndef HAVE_WAYLAND_ONLY
EINTERN void e_comp_wl_xwayland_client_queue(E_Client *ec);
static inline E_Comp_X_Client_Data *

View File

@ -227,8 +227,7 @@ _e_comp_wl_input_cb_keyboard_get(struct wl_client *client, struct wl_resource *r
wl_keyboard_send_repeat_info(res, e_config->keyboard.repeat_rate, e_config->keyboard.repeat_delay);
/* send current keymap */
wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
e_comp_wl->xkb.fd, e_comp_wl->xkb.size);
e_comp_wl_input_keymap_send(res);
/* if the client owns the focused surface, we need to send an enter */
focused = e_client_focused_get();
@ -317,13 +316,14 @@ _e_comp_wl_input_cb_bind_seat(struct wl_client *client, void *data EINA_UNUSED,
wl_seat_send_name(res, e_comp_wl->seat.name);
}
static int
_e_comp_wl_input_keymap_fd_get(off_t size)
int
_e_comp_wl_input_keymap_fd_get(void)
{
int fd = 0, blen = 0, len = 0;
const char *path;
char tmp[PATH_MAX];
long flags;
void *mm;
blen = sizeof(tmp) - 1;
@ -354,13 +354,25 @@ _e_comp_wl_input_keymap_fd_get(off_t size)
return -1;
}
if (ftruncate(fd, size) < 0)
if (ftruncate(fd, e_comp_wl->xkb.map_size) < 0)
{
close(fd);
return -1;
}
unlink(tmp);
mm = mmap(NULL, e_comp_wl->xkb.map_size, (PROT_READ | PROT_WRITE),
MAP_SHARED, fd, 0);
if (mm == MAP_FAILED)
{
ERR("Failed to mmap keymap area: %m");
close(fd);
return -1;
}
memcpy(mm, e_comp_wl->xkb.map_string, e_comp_wl->xkb.map_size);
munmap(mm, e_comp_wl->xkb.map_size);
return fd;
}
@ -389,6 +401,21 @@ _e_comp_wl_input_state_update(void)
0, 0);
}
void
e_comp_wl_input_keymap_send(struct wl_resource *res)
{
int fd;
fd = _e_comp_wl_input_keymap_fd_get();
if (fd == -1)
return;
wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
fd, e_comp_wl->xkb.map_size);
close(fd);
}
static void
nested_keymap_update(void)
{
@ -396,13 +423,12 @@ nested_keymap_update(void)
Evas_Object *obj;
EINA_LIST_FOREACH(e_comp_wl->efl_wls, l, obj)
efl_wl_seat_keymap_set(obj, NULL, e_comp_wl->xkb.state, e_comp_wl->xkb.fd, e_comp_wl->xkb.size, &e_comp_wl->kbd.keys);
efl_wl_seat_keymap_set(obj, NULL, e_comp_wl->xkb.state, e_comp_wl->xkb.map_string, &e_comp_wl->kbd.keys);
}
static void
_e_comp_wl_input_keymap_update(struct xkb_keymap *keymap)
{
char *tmp;
struct wl_resource *res;
Eina_List *l;
@ -410,11 +436,9 @@ _e_comp_wl_input_keymap_update(struct xkb_keymap *keymap)
if (e_comp_wl->xkb.keymap)
xkb_map_unref(e_comp_wl->xkb.keymap);
/* unmap any existing keyboard area */
if (e_comp_wl->xkb.area)
munmap(e_comp_wl->xkb.area, e_comp_wl->xkb.size);
if (e_comp_wl->xkb.fd >= 0) close(e_comp_wl->xkb.fd);
/* free any existing keyboard map string */
free(e_comp_wl->xkb.map_string);
e_comp_wl->xkb.map_string = NULL;
/* increment keymap reference */
e_comp_wl->xkb.keymap = keymap;
@ -422,39 +446,17 @@ _e_comp_wl_input_keymap_update(struct xkb_keymap *keymap)
/* update the state */
_e_comp_wl_input_state_update();
if (!(tmp = xkb_map_get_as_string(keymap)))
if (!(e_comp_wl->xkb.map_string = xkb_map_get_as_string(keymap)))
{
ERR("Could not get keymap string");
return;
}
e_comp_wl->xkb.size = strlen(tmp) + 1;
e_comp_wl->xkb.fd =
_e_comp_wl_input_keymap_fd_get(e_comp_wl->xkb.size);
if (e_comp_wl->xkb.fd < 0)
{
ERR("Could not create keymap file");
free(tmp);
return;
}
e_comp_wl->xkb.area =
mmap(NULL, e_comp_wl->xkb.size, (PROT_READ | PROT_WRITE),
MAP_SHARED, e_comp_wl->xkb.fd, 0);
if (e_comp_wl->xkb.area == MAP_FAILED)
{
ERR("Failed to mmap keymap area: %m");
free(tmp);
return;
}
strcpy(e_comp_wl->xkb.area, tmp);
free(tmp);
e_comp_wl->xkb.map_size = strlen(e_comp_wl->xkb.map_string) + 1;
/* send updated keymap */
EINA_LIST_FOREACH(e_comp_wl->kbd.resources, l, res)
wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
e_comp_wl->xkb.fd, e_comp_wl->xkb.size);
e_comp_wl_input_keymap_send(res);
/* update modifiers */
e_comp_wl_input_keyboard_modifiers_update();
@ -468,8 +470,6 @@ e_comp_wl_input_init(void)
if (!e_comp_wl->seat.name)
e_comp_wl->seat.name = "seat0";
e_comp_wl->xkb.fd = -1;
/* create the global resource for input seat */
e_comp_wl->seat.global =
wl_global_create(e_comp_wl->wl.disp, &wl_seat_interface, 4,
@ -524,10 +524,8 @@ e_comp_wl_input_shutdown(void)
/* destroy e_comp_wl->kbd.keys array */
wl_array_release(&e_comp_wl->kbd.keys);
/* unmap any existing keyboard area */
if (e_comp_wl->xkb.area)
munmap(e_comp_wl->xkb.area, e_comp_wl->xkb.size);
if (e_comp_wl->xkb.fd >= 0) close(e_comp_wl->xkb.fd);
/* free the string copy of the keyboard map */
free(e_comp_wl->xkb.map_string);
/* unreference any existing keyboard state */
if (e_comp_wl->xkb.state)

View File

@ -36,5 +36,8 @@ E_API void e_comp_wl_input_keymap_index_set(xkb_layout_index_t index);
E_API void e_comp_wl_input_keymap_set(const char *rules, const char *model, const char *layout, const char *variant, const char *options);
E_API void e_comp_wl_input_keyboard_event_generate(const char *key, int mods, Eina_Bool up);
EINTERN int _e_comp_wl_input_keymap_fd_get(void);
# endif
#endif

View File

@ -786,7 +786,7 @@ popup_added(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
static void
seat_added(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
efl_wl_seat_keymap_set(obj, NULL, e_comp_wl->xkb.state, e_comp_wl->xkb.fd, e_comp_wl->xkb.size, &e_comp_wl->kbd.keys);
efl_wl_seat_keymap_set(obj, NULL, e_comp_wl->xkb.state, e_comp_wl->xkb.map_string, &e_comp_wl->kbd.keys);
efl_wl_seat_key_repeat_set(obj, NULL, e_config->keyboard.repeat_rate, e_config->keyboard.repeat_delay);
}
@ -875,7 +875,7 @@ gadget_create(Evas_Object *parent, Config_Item *ci, int *id, E_Gadget_Site_Orien
inst->obj = efl_wl_add(e_comp->evas);
if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
{
efl_wl_seat_keymap_set(inst->obj, NULL, e_comp_wl->xkb.state, e_comp_wl->xkb.fd, e_comp_wl->xkb.size, &e_comp_wl->kbd.keys);
efl_wl_seat_keymap_set(inst->obj, NULL, e_comp_wl->xkb.state, e_comp_wl->xkb.map_string, &e_comp_wl->kbd.keys);
efl_wl_seat_key_repeat_set(inst->obj, NULL, e_config->keyboard.repeat_rate, e_config->keyboard.repeat_delay);
e_comp_wl->efl_wls = eina_list_append(e_comp_wl->efl_wls, inst->obj);
}

View File

@ -324,9 +324,7 @@ _e_text_input_method_context_cb_keyboard_grab(struct wl_client *client, struct w
wl_resource_set_implementation(new_resource, NULL, context,
_e_text_input_method_context_keyboard_unbind);
wl_keyboard_send_keymap(new_resource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
e_comp_wl->xkb.fd,
e_comp_wl->xkb.size);
e_comp_wl_input_keymap_send(new_resource);
context->kbd.resource = new_resource;