aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerek Foreman <derek.foreman.samsung@gmail.com>2018-08-17 12:46:39 -0400
committerMike Blumenkrantz <zmike@samsung.com>2018-08-17 12:46:39 -0400
commit6fe7e1155db768dcafa9f24af8f6b98230974813 (patch)
tree9105e2f493021cac492f5859df3c7ab727f374af
parentecore_pipe: remove null check condition and fix segfualt on Windows (diff)
downloadefl-6fe7e1155db768dcafa9f24af8f6b98230974813.tar.gz
efl_wl: 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: devilhorns Subscribers: cedric, #reviewers, #committers, zmike Tags: #efl Differential Revision: https://phab.enlightenment.org/D6862
-rw-r--r--src/lib/efl_wl/Efl_Wl.h5
-rw-r--r--src/lib/efl_wl/efl_wl.c110
2 files changed, 63 insertions, 52 deletions
diff --git a/src/lib/efl_wl/Efl_Wl.h b/src/lib/efl_wl/Efl_Wl.h
index 9124926373..f73e57f6e3 100644
--- a/src/lib/efl_wl/Efl_Wl.h
+++ b/src/lib/efl_wl/Efl_Wl.h
@@ -204,12 +204,11 @@ EAPI Evas_Object *efl_wl_extracted_surface_extracted_parent_get(Evas_Object *sur
* @param seat The seat to set the keymap for, NULL to set the keymap for all seats
* @param keymap The xkb_keymap object to use
* @param state The xkb_state object to use
- * @param fd The fd created from a mmapped xkb_keymap
- * @param size The size of the xkb_keymap memory
+ * @param str The string containing the keymap
* @param wl_key_array A pointer to the wl_array in which keys are stored
* @since 1.21
*/
-EAPI void efl_wl_seat_keymap_set(Evas_Object *obj, Eo *seat, void *state, int fd, size_t size, void *wl_key_array);
+EAPI void efl_wl_seat_keymap_set(Evas_Object *obj, Eo *seat, void *state, char *str, void *wl_key_array);
/**
* Set the key repeat rate for a seat in the compositor
diff --git a/src/lib/efl_wl/efl_wl.c b/src/lib/efl_wl/efl_wl.c
index 0da7d8c374..15e2ec0465 100644
--- a/src/lib/efl_wl/efl_wl.c
+++ b/src/lib/efl_wl/efl_wl.c
@@ -205,9 +205,8 @@ typedef struct Comp_Seat
struct xkb_context *context;
struct xkb_keymap *keymap;
struct xkb_state *state;
- char *keymap_mem;
- int keymap_mem_size;
- int keymap_fd;
+ char *keymap_str;
+ int keymap_str_size;
int repeat_rate;
int repeat_delay;
Eina_Hash *resources;
@@ -3677,6 +3676,48 @@ seat_update_caps(Comp_Seat *s, struct wl_resource *res)
wl_seat_send_capabilities(res, caps);
}
+static int
+anonymous_fd_get(off_t size)
+{
+ Eina_Tmpstr *file;
+ int fd;
+
+ fd = eina_file_mkstemp("comp-keymapXXXXXX", &file);
+ if (fd < 0)
+ {
+ EINA_LOG_ERR("mkstemp failed!\n");
+ return - 1;
+ }
+ if (!eina_file_close_on_exec(fd, 1))
+ {
+ EINA_LOG_ERR("Failed to set CLOEXEC on fd %d\n", fd);
+ close(fd);
+ return - 1;
+ }
+ ftruncate(fd, size);
+ eina_file_unlink(file);
+ eina_tmpstr_del(file);
+
+ return fd;
+}
+
+static void
+_keymap_send(Comp_Seat *s, struct wl_resource *res)
+{
+ char *mem;
+ int fd;
+
+ fd = anonymous_fd_get(s->kbd.keymap_str_size);
+ EINA_SAFETY_ON_TRUE_RETURN(fd == -1);
+
+ mem = mmap(NULL, s->kbd.keymap_str_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ memcpy(mem, s->kbd.keymap_str, s->kbd.keymap_str_size);
+ munmap(mem, s->kbd.keymap_str_size);
+ wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, s->kbd.keymap_str_size);
+ close(fd);
+}
+
static void
seat_keymap_send(Comp_Seat *s)
{
@@ -3688,7 +3729,7 @@ seat_keymap_send(Comp_Seat *s)
Eina_List *ll;
struct wl_resource *res;
EINA_LIST_FOREACH(l, ll, res)
- wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, s->kbd.keymap_fd, s->kbd.keymap_mem_size);
+ _keymap_send(s, res);
}
eina_iterator_free(it);
}
@@ -3733,12 +3774,10 @@ seat_kbd_external_init(Comp_Seat *s)
static void
seat_keymap_update(Comp_Seat *s)
{
- char *str;
- Eina_Tmpstr *file;
xkb_mod_mask_t latched = 0, locked = 0;
- if (s->kbd.keymap_mem) munmap(s->kbd.keymap_mem, s->kbd.keymap_mem_size);
- if (s->kbd.keymap_fd > -1) close(s->kbd.keymap_fd);
+ s->kbd.keymap_str = NULL;
+ s->kbd.keymap_str_size = 0;
#ifdef HAVE_ECORE_X
if (!x11_kbd_keymap)
@@ -3753,8 +3792,8 @@ seat_keymap_update(Comp_Seat *s)
if (!s->kbd.keymap)
{
s->kbd.state = NULL;
- s->kbd.keymap_fd = -1;
- s->kbd.keymap_mem = NULL;
+ s->kbd.keymap_str = NULL;
+ s->kbd.keymap_str_size = 0;
return;
}
@@ -3763,36 +3802,8 @@ seat_keymap_update(Comp_Seat *s)
#ifdef HAVE_ECORE_X
}
#endif
- str = xkb_map_get_as_string(s->kbd.keymap);
- s->kbd.keymap_mem_size = strlen(str) + 1;
- s->kbd.keymap_fd = eina_file_mkstemp("comp-keymapXXXXXX", &file);
- if (s->kbd.keymap_fd < 0)
- {
- EINA_LOG_ERR("mkstemp failed!\n");
- s->kbd.keymap_fd = -1;
- xkb_state_unref(s->kbd.state);
- s->kbd.state = NULL;
- return;
- }
- if (!eina_file_close_on_exec(s->kbd.keymap_fd, 1))
- {
- EINA_LOG_ERR("Failed to set CLOEXEC on fd %d\n", s->kbd.keymap_fd);
- close(s->kbd.keymap_fd);
- s->kbd.keymap_fd = -1;
- xkb_state_unref(s->kbd.state);
- s->kbd.state = NULL;
- return;
- }
- ftruncate(s->kbd.keymap_fd, s->kbd.keymap_mem_size);
- eina_file_unlink(file);
- eina_tmpstr_del(file);
- s->kbd.keymap_mem =
- mmap(NULL, s->kbd.keymap_mem_size + 1,
- PROT_READ | PROT_WRITE, MAP_SHARED, s->kbd.keymap_fd, 0);
-
- memcpy(s->kbd.keymap_mem, str, s->kbd.keymap_mem_size);
- s->kbd.keymap_mem[s->kbd.keymap_mem_size] = 0;
- free(str);
+ s->kbd.keymap_str = xkb_map_get_as_string(s->kbd.keymap);
+ s->kbd.keymap_str_size = strlen(s->kbd.keymap_str) + 1;
seat_keymap_send(s);
}
@@ -3859,7 +3870,7 @@ seat_kbd_create(struct wl_client *client, struct wl_resource *resource, uint32_t
if (!s->kbd.resources) s->kbd.resources = eina_hash_pointer_new(NULL);
eina_hash_list_append(s->kbd.resources, &client, res);
- wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, s->kbd.keymap_fd, s->kbd.keymap_mem_size);
+ _keymap_send(s, res);
if (wl_resource_get_version(res) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
wl_keyboard_send_repeat_info(res, s->kbd.repeat_rate, s->kbd.repeat_delay);
@@ -4086,8 +4097,8 @@ seat_kbd_destroy(Comp_Seat *s)
#ifdef HAVE_ECORE_X
}
#endif
- if (s->kbd.keymap_mem) munmap(s->kbd.keymap_mem, s->kbd.keymap_mem_size);
- if (s->kbd.keymap_fd > -1) close(s->kbd.keymap_fd);
+ s->kbd.keymap_str = NULL;
+ s->kbd.keymap_str_size = 0;
wl_array_release(&s->kbd.keys);
}
@@ -4481,7 +4492,6 @@ comp_seats_proxy(Comp *c)
s = calloc(1, sizeof(Comp_Seat));
s->c = c;
s->dev = dev;
- s->kbd.keymap_fd = -1;
efl_ref(s->dev);
if (c->parent_disp)
comp_seat_proxy_update(s);
@@ -5945,7 +5955,7 @@ efl_wl_extracted_surface_extracted_parent_get(Evas_Object *surface)
}
void
-efl_wl_seat_keymap_set(Evas_Object *obj, Eo *seat, void *state, int fd, size_t size, void *key_array)
+efl_wl_seat_keymap_set(Evas_Object *obj, Eo *seat, void *state, char *str, void *key_array)
{
Comp *c;
Comp_Seat *s;
@@ -5954,7 +5964,7 @@ efl_wl_seat_keymap_set(Evas_Object *obj, Eo *seat, void *state, int fd, size_t s
c = evas_object_smart_data_get(obj);
EINA_INLIST_FOREACH(c->seats, s)
{
- if (!seat) efl_wl_seat_keymap_set(obj, s->dev, state, fd, size, key_array);
+ if (!seat) efl_wl_seat_keymap_set(obj, s->dev, state, str, key_array);
else if (s->dev == seat) break;
}
if (!seat) return;
@@ -5963,11 +5973,13 @@ efl_wl_seat_keymap_set(Evas_Object *obj, Eo *seat, void *state, int fd, size_t s
s->kbd.external = 1;
s->kbd.keys_external = key_array;
s->kbd.state = state;
- s->kbd.keymap_fd = fd;
- s->kbd.keymap_mem_size = size;
+ s->kbd.keymap_str = str;
+ if (str)
+ s->kbd.keymap_str_size = strlen(str) + 1;
+ else
+ s->kbd.keymap_str_size = 0;
s->kbd.context = NULL;
s->kbd.keymap = NULL;
- s->kbd.keymap_mem = NULL;
if (s->keyboard)
seat_kbd_external_init(s);
}