chiark / gitweb /
localed: validate xkb keymaps
authorDavid Herrmann <dh.herrmann@gmail.com>
Mon, 24 Nov 2014 14:12:42 +0000 (15:12 +0100)
committerDavid Herrmann <dh.herrmann@gmail.com>
Mon, 24 Nov 2014 14:16:33 +0000 (15:16 +0100)
Introduce a new optional dependency on libxkbcommon for systemd-localed.
Whenever the x11 keymap settings are changed, use libxkbcommon to compile
the keymap. If the compilation fails, print a warning so users will get
notified.

On compilation failure, we still update the keymap settings for now. This
patch just introduces the xkbcommon infrastructure to have keymap
validation in place. We can later decide if/how we want to enforce this.

Makefile.am
NEWS
configure.ac
src/locale/localed.c

index 3f9f3fab379541bbc881eebacf925064894bbcb5..1674f6195af3d63838a6abc32c0612438823039f 100644 (file)
@@ -4626,7 +4626,12 @@ systemd_localed_SOURCES = \
 systemd_localed_LDADD = \
        libsystemd-label.la \
        libsystemd-internal.la \
-       libsystemd-shared.la
+       libsystemd-shared.la \
+       $(XKBCOMMON_LIBS)
+
+systemd_localed_CFLAGS = \
+       $(AM_CFLAGS) \
+       $(XKBCOMMON_CFLAGS)
 
 nodist_systemunit_DATA += \
        units/systemd-localed.service
diff --git a/NEWS b/NEWS
index f621752d64475826763cee50cfb9e0e58e491613..0d3ab2b48b78e9e4d1522eb7b481344e3709cbed 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,12 @@
 systemd System and Service Manager
 
+CHANGES WITH 218:
+
+        * If compiled with --enable-xkbcommon, systemd-localed will
+          verify x11 keymap settings by compiling the given keymap. It
+          will spew out warnings if the compilation fails. This
+          requires libxkbcommon to be installed.
+
 CHANGES WITH 217:
 
         * journalctl gained the new options -t/--identifier= to match
index 2c8be53dd3bf8796a70b05922c71e056813c55a2..bd3cc0ea61b353af63c4ecd86aaedd67e210afd8 100644 (file)
@@ -414,6 +414,18 @@ if test "x$enable_kmod" != "xno"; then
 fi
 AM_CONDITIONAL(HAVE_KMOD, [test "$have_kmod" = "yes"])
 
+# ------------------------------------------------------------------------------
+have_xkbcommon=no
+AC_ARG_ENABLE(xkbcommon, AS_HELP_STRING([--disable-xkbcommon], [disable xkbcommon keymap support]))
+if test "x$enable_xkbcommon" != "xno"; then
+        PKG_CHECK_MODULES(XKBCOMMON, [ xkbcommon >= 0.3.0 ],
+                [AC_DEFINE(HAVE_XKBCOMMON, 1, [Define if libxkbcommon is available]) have_xkbcommon=yes], have_xkbcommon=no)
+        if test "x$have_xkbcommon" = xno -a "x$enable_xkbcommon" = xyes; then
+                AC_MSG_ERROR([*** xkbcommon support requested but libraries not found])
+        fi
+fi
+AM_CONDITIONAL(HAVE_XKBCOMMON, [test "$have_xkbcommon" = "yes"])
+
 # ------------------------------------------------------------------------------
 have_blkid=no
 AC_ARG_ENABLE(blkid, AS_HELP_STRING([--disable-blkid], [disable blkid support]))
@@ -1374,6 +1386,7 @@ AC_MSG_RESULT([
         polkit:                  ${have_polkit}
         efi:                     ${have_efi}
         kmod:                    ${have_kmod}
+        xkbcommon:               ${have_xkbcommon}
         blkid:                   ${have_blkid}
         dbus:                    ${have_dbus}
         nss-myhostname:          ${have_myhostname}
index 9377ce5015eeaf3d3b8beabcf5e3b2edc4f23df9..4e56382f4f2365d6bd4acd2cd7c72cec7981808b 100644 (file)
 #include "event-util.h"
 #include "locale-util.h"
 
+#ifdef HAVE_XKBCOMMON
+#include <xkbcommon/xkbcommon.h>
+#endif
+
 enum {
         /* We don't list LC_ALL here on purpose. People should be
          * using LANG instead. */
@@ -1005,6 +1009,51 @@ static int method_set_vc_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata
         return sd_bus_reply_method_return(m, NULL);
 }
 
+#ifdef HAVE_XKBCOMMON
+static void log_xkb(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) {
+        /* suppress xkb messages for now */
+}
+
+static int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) {
+        const struct xkb_rule_names rmlvo = {
+                .model          = model,
+                .layout         = layout,
+                .variant        = variant,
+                .options        = options,
+        };
+        struct xkb_context *ctx = NULL;
+        struct xkb_keymap *km = NULL;
+        int r;
+
+        /* compile keymap from RMLVO information to check out its validity */
+
+        ctx = xkb_context_new(XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
+        if (!ctx) {
+                r = -ENOMEM;
+                goto exit;
+        }
+
+        xkb_context_set_log_fn(ctx, log_xkb);
+
+        km = xkb_keymap_new_from_names(ctx, &rmlvo, XKB_KEYMAP_COMPILE_NO_FLAGS);
+        if (!km) {
+                r = -EINVAL;
+                goto exit;
+        }
+
+        r = 0;
+
+exit:
+        xkb_keymap_unref(km);
+        xkb_context_unref(ctx);
+        return r;
+}
+#else
+static int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) {
+        return 0;
+}
+#endif
+
 static int method_set_x11_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
         Context *c = userdata;
         const char *layout, *model, *variant, *options;
@@ -1038,6 +1087,11 @@ static int method_set_x11_keyboard(sd_bus *bus, sd_bus_message *m, void *userdat
                     (options && !string_is_safe(options)))
                         return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keyboard data");
 
+                r = verify_xkb_rmlvo(model, layout, variant, options);
+                if (r < 0)
+                        log_warning("Cannot compile XKB keymap for new x11 keyboard layout ('%s' / '%s' / '%s' / '%s'): %s",
+                                    strempty(model), strempty(layout), strempty(variant), strempty(options), strerror(-r));
+
                 r = bus_verify_polkit_async(m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-keyboard", interactive, &c->polkit_registry, error);
                 if (r < 0)
                         return r;