localed: validate xkb keymaps

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.
This commit is contained in:
David Herrmann 2014-11-24 15:12:42 +01:00
parent 8a52210c93
commit d4f5a1f47d
4 changed files with 80 additions and 1 deletions

View 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

7
NEWS
View File

@ -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

View 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}

View File

@ -41,6 +41,10 @@
#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;