Filter out more sysctl params that throw Invalid argument when executed on the fly
This commit is contained in:
parent
9546e1b8ed
commit
e682aae41e
2 changed files with 82 additions and 2 deletions
|
|
@ -1121,8 +1121,14 @@ _SYSCTL_GENERATED_SRC_REL = "sysctl/99-enroll.conf"
|
|||
# config. This avoids generating a file that tries to replay one-shot triggers or
|
||||
# host identity that should be managed elsewhere (e.g. /etc/hostname).
|
||||
_SYSCTL_VOLATILE_KEYS = {
|
||||
"fs.binfmt_misc.status",
|
||||
"kernel.domainname",
|
||||
"kernel.hostname",
|
||||
"kernel.kexec_load_disabled",
|
||||
"kernel.kexec_load_limit_panic",
|
||||
"kernel.kexec_load_limit_reboot",
|
||||
"kernel.max_rcu_stall_to_panic",
|
||||
"kernel.modules_disabled",
|
||||
"kernel.ns_last_pid",
|
||||
"net.ipv4.route.flush",
|
||||
"net.ipv6.route.flush",
|
||||
|
|
@ -1131,6 +1137,21 @@ _SYSCTL_VOLATILE_KEYS = {
|
|||
"vm.stat_refresh",
|
||||
}
|
||||
|
||||
_SYSCTL_VOLATILE_PREFIXES = (
|
||||
"fs.binfmt_misc.",
|
||||
"kernel.sched_domain.",
|
||||
)
|
||||
|
||||
# These are paired with ratio/byte counterparts. The inactive side appears as 0
|
||||
# when read; replaying that 0 through sysctl -p is noisy and can be rejected by
|
||||
# kernels that enforce minimum values.
|
||||
_SYSCTL_SKIP_ZERO_VALUE_KEYS = {
|
||||
"vm.dirty_background_bytes",
|
||||
"vm.dirty_background_ratio",
|
||||
"vm.dirty_bytes",
|
||||
"vm.dirty_ratio",
|
||||
}
|
||||
|
||||
|
||||
def _sysctl_proc_path(key: str) -> str:
|
||||
return "/proc/sys/" + key.replace(".", "/")
|
||||
|
|
@ -1139,7 +1160,9 @@ def _sysctl_proc_path(key: str) -> str:
|
|||
def _sysctl_key_is_persistable(key: str) -> tuple[bool, str]:
|
||||
if not key or not _SYSCTL_KEY_RE.fullmatch(key):
|
||||
return False, "invalid key"
|
||||
if key in _SYSCTL_VOLATILE_KEYS:
|
||||
if key in _SYSCTL_VOLATILE_KEYS or any(
|
||||
key.startswith(prefix) for prefix in _SYSCTL_VOLATILE_PREFIXES
|
||||
):
|
||||
return False, "volatile/action key"
|
||||
|
||||
proc_path = _sysctl_proc_path(key)
|
||||
|
|
@ -1155,6 +1178,17 @@ def _sysctl_key_is_persistable(key: str) -> tuple[bool, str]:
|
|||
return True, ""
|
||||
|
||||
|
||||
def _sysctl_entry_is_persistable(key: str, value: str) -> tuple[bool, str]:
|
||||
ok, reason = _sysctl_key_is_persistable(key)
|
||||
if not ok:
|
||||
return ok, reason
|
||||
|
||||
if key in _SYSCTL_SKIP_ZERO_VALUE_KEYS and str(value).strip() == "0":
|
||||
return False, "inactive mutually-exclusive zero value"
|
||||
|
||||
return True, ""
|
||||
|
||||
|
||||
def _parse_sysctl_a_output(
|
||||
text: str,
|
||||
*,
|
||||
|
|
@ -1199,7 +1233,7 @@ def _parse_sysctl_a_output(
|
|||
skipped["duplicate"] += 1
|
||||
continue
|
||||
if require_persistable:
|
||||
ok, _reason = _sysctl_key_is_persistable(key)
|
||||
ok, _reason = _sysctl_entry_is_persistable(key, value)
|
||||
if not ok:
|
||||
skipped["non_persistable"] += 1
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -327,6 +327,52 @@ def test_parse_sysctl_a_output_keeps_persistable_values(monkeypatch):
|
|||
assert skipped["duplicate"] == 1
|
||||
|
||||
|
||||
def test_sysctl_filter_skips_non_replayable_runtime_keys(monkeypatch):
|
||||
for key in (
|
||||
"fs.binfmt_misc.status",
|
||||
"fs.binfmt_misc.register",
|
||||
"kernel.kexec_load_disabled",
|
||||
"kernel.kexec_load_limit_panic",
|
||||
"kernel.kexec_load_limit_reboot",
|
||||
"kernel.max_rcu_stall_to_panic",
|
||||
"kernel.modules_disabled",
|
||||
"kernel.sched_domain.cpu0.domain0.flags",
|
||||
):
|
||||
ok, reason = h._sysctl_key_is_persistable(key)
|
||||
assert ok is False
|
||||
assert reason == "volatile/action key"
|
||||
|
||||
monkeypatch.setattr(h, "_sysctl_key_is_persistable", lambda key: (True, ""))
|
||||
for key in (
|
||||
"vm.dirty_background_bytes",
|
||||
"vm.dirty_background_ratio",
|
||||
"vm.dirty_bytes",
|
||||
"vm.dirty_ratio",
|
||||
):
|
||||
ok, reason = h._sysctl_entry_is_persistable(key, "0")
|
||||
assert ok is False
|
||||
assert reason == "inactive mutually-exclusive zero value"
|
||||
assert h._sysctl_entry_is_persistable(key, "10")[0] is True
|
||||
|
||||
|
||||
def test_parse_sysctl_a_output_skips_non_replayable_values(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
h,
|
||||
"_sysctl_key_is_persistable",
|
||||
lambda key: (key != "kernel.modules_disabled", "volatile/action key"),
|
||||
)
|
||||
|
||||
params, skipped = h._parse_sysctl_a_output(
|
||||
"kernel.modules_disabled = 0\n"
|
||||
"vm.dirty_background_bytes = 0\n"
|
||||
"vm.dirty_ratio = 20\n"
|
||||
"net.ipv4.ip_forward = 1\n"
|
||||
)
|
||||
|
||||
assert params == {"net.ipv4.ip_forward": "1", "vm.dirty_ratio": "20"}
|
||||
assert skipped["non_persistable"] == 2
|
||||
|
||||
|
||||
def test_collect_sysctl_snapshot_writes_generated_artifact(monkeypatch, tmp_path: Path):
|
||||
monkeypatch.setattr(
|
||||
h,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue