keylime/0002-fix-crash-empty-max-workers-config.patch
Anderson Toshiyuki Sasaki 61287d22a1
Rebase to Keylime release v7.14.3
Resolves: RHEL-180613
Resolves: RHEL-189524
Resolves: RHEL-170880
Resolves: RHEL-168794
Resolves: RHEL-155023
Resolves: RHEL-193538

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
2026-07-16 09:28:28 +02:00

96 lines
4.6 KiB
Diff

From 87d8867b1e668007592aefb53f6022a5df80554f Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Thu, 9 Jul 2026 09:54:07 +0200
Subject: [PATCH] fix: handle invalid config values for typed server options
When a typed configuration option (int, float, bool) contains an empty
or invalid value, configparser raises ValueError instead of using the
fallback. This causes the verifier to crash on startup when e.g.
max_workers has an empty value after a config upgrade.
Catch ValueError in _set_option for typed config reads and fall back to
the caller-provided default with a warning. Also add a default fallback
of 0 for max_workers (meaning use all CPUs).
Fixes: keylime/keylime#1929
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
---
keylime/web/base/server.py | 42 +++++++++++++++++++++++++++++---------
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/keylime/web/base/server.py b/keylime/web/base/server.py
index fe9ccbf6d..1bced714f 100644
--- a/keylime/web/base/server.py
+++ b/keylime/web/base/server.py
@@ -449,9 +449,34 @@ def _use_config(self, component: str) -> None:
"""Sets config component (i.e., namespace) used to locate config values when setting server options."""
self.__config_component = component
+ _TYPED_CONFIG_GETTERS: dict[type, Callable[..., Any]] = {
+ int: config.getint,
+ float: config.getfloat,
+ bool: config.getboolean,
+ }
+
+ def _get_typed_config_value(self, config_name: str, data_type: type, fallback: Any) -> Any:
+ """Read a typed config value, falling back gracefully on ValueError."""
+ getter = self._TYPED_CONFIG_GETTERS[data_type]
+ try:
+ return getter(self.config_component, config_name, fallback=fallback) # type: ignore
+ except ValueError:
+ if fallback is None:
+ raise
+ raw_value = config.get(self.config_component, config_name, fallback="<unknown>") # type: ignore[arg-type]
+ logger.warning(
+ "Cannot parse '%s' as %s for option '%s' (component: %s), using fallback: %s",
+ raw_value,
+ data_type.__name__,
+ config_name,
+ self.config_component,
+ fallback,
+ )
+ return fallback
+
def _set_option(self, name: str, **kwargs: Any) -> None:
"""Sets server option by name either from given value or by obtaining it from user config. If the value is
- falsy, uses the given fallback value instead or ``None`` if no fallback is provided. Examples::
+ ``None``, uses the given fallback value instead. Examples::
# Set option using provided value
self._set_option("bind_interface", value="0.0.0.0")
@@ -487,19 +512,13 @@ def _set_option(self, name: str, **kwargs: Any) -> None:
case {"from_config": (config_name, data_type)} if data_type is str:
value = config.get(self.config_component, config_name, fallback=fallback) # type: ignore
- case {"from_config": (config_name, data_type)} if data_type is int:
- value = config.getint(self.config_component, config_name, fallback=fallback) # type: ignore
-
- case {"from_config": (config_name, data_type)} if data_type is float:
- value = config.getfloat(self.config_component, config_name, fallback=fallback) # type: ignore
-
- case {"from_config": (config_name, data_type)} if data_type is bool:
- value = config.getboolean(self.config_component, config_name, fallback=fallback) # type: ignore
+ case {"from_config": (config_name, data_type)} if data_type in self._TYPED_CONFIG_GETTERS:
+ value = self._get_typed_config_value(config_name, data_type, fallback)
case _:
raise TypeError(f"invalid arguments given when setting option '{name}' for {self.__class__.__name__}")
- setattr(self, attr_name, value or fallback)
+ setattr(self, attr_name, value if value is not None else fallback)
def _set_operating_mode(self, **kwargs: Any) -> None:
"""Sets operating mode of the server (push or pull)."""
@@ -574,6 +593,9 @@ def _set_max_workers(self, **kwargs: Any) -> None:
if "from_config" in kwargs:
kwargs.update({"from_config": (kwargs["from_config"], int)})
+ if "fallback" not in kwargs:
+ kwargs.update({"fallback": 0})
+
self._set_option("max_workers", **kwargs)
def _set_ssl_ctx(self, **kwargs: Any) -> None: