summaryrefslogtreecommitdiffstats
path: root/src/locale
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-03-04 11:27:05 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-03-04 11:44:20 +0100
commit9ef70c06c663a05f7646d690e00e4b4a73af8c61 (patch)
tree23c0eaec0e0f0d9389098736efa0bbfc5c26cb4e /src/locale
parentshared/kbd-util: return error on resource errors (diff)
downloadsystemd-9ef70c06c663a05f7646d690e00e4b4a73af8c61.tar.xz
systemd-9ef70c06c663a05f7646d690e00e4b4a73af8c61.zip
localed: refuse to set a keymap which is not installed
In https://bugzilla.redhat.com/show_bug.cgi?id=1933873 a keymap was set without the package that provides it being installed (it2 is in kbd-legacy, which is not installed by default). Setting a non-installed keymap is problematic, because it results in nasty failures afterward (*). So let's to the same as e.g. for locale data, and refuse a setting if the definition doesn't exists in the filesystem. The implementation using nftw() is not the most efficient, but I think it's OK in this case. This is definitely not in any kind of hot path, and I prefer not to duplicate the filename manipulation logic in a second function. (*) If the keymap is not found, vconsole-setup.service will fail. dracut-cmdline-ask.service has Requires=vconsole-setup.service, so it will also fail, and this breaks boot. dracut-cmdline-ask.service having a hard dependency is appropriate though: we sadly don't display what the keymap is, and with a wrong keymap, any attempts to enter a password are likely to fail.
Diffstat (limited to 'src/locale')
-rw-r--r--src/locale/localed.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/src/locale/localed.c b/src/locale/localed.c
index 9c97313edc..f44c0bab2a 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -19,6 +19,7 @@
#include "bus-polkit.h"
#include "def.h"
#include "dlfcn-util.h"
+#include "kbd-util.h"
#include "keymap-util.h"
#include "locale-util.h"
#include "macro.h"
@@ -474,7 +475,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_error *error) {
Context *c = userdata;
- const char *keymap, *keymap_toggle;
+ const char *name, *keymap, *keymap_toggle;
int convert, interactive, r;
assert(m);
@@ -490,17 +491,23 @@ static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_erro
r = vconsole_read_data(c, m);
if (r < 0) {
log_error_errno(r, "Failed to read virtual console keymap data: %m");
- return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to read virtual console keymap data");
+ return sd_bus_error_set_errnof(error, r, "Failed to read virtual console keymap data: %m");
+ }
+
+ FOREACH_STRING(name, keymap ?: keymap_toggle, keymap ? keymap_toggle : NULL) {
+ r = keymap_exists(name); /* This also verifies that the keymap name is kosher. */
+ if (r < 0) {
+ log_error_errno(r, "Failed to check keymap %s: %m", name);
+ return sd_bus_error_set_errnof(error, r, "Failed to check keymap %s: %m", name);
+ }
+ if (r == 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Keymap %s is not installed.", name);
}
if (streq_ptr(keymap, c->vc_keymap) &&
streq_ptr(keymap_toggle, c->vc_keymap_toggle))
return sd_bus_reply_method_return(m, NULL);
- if ((keymap && (!filename_is_valid(keymap) || !string_is_safe(keymap))) ||
- (keymap_toggle && (!filename_is_valid(keymap_toggle) || !string_is_safe(keymap_toggle))))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Received invalid keymap data");
-
r = bus_verify_polkit_async(
m,
CAP_SYS_ADMIN,