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
|
# 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).
|
# host identity that should be managed elsewhere (e.g. /etc/hostname).
|
||||||
_SYSCTL_VOLATILE_KEYS = {
|
_SYSCTL_VOLATILE_KEYS = {
|
||||||
|
"fs.binfmt_misc.status",
|
||||||
"kernel.domainname",
|
"kernel.domainname",
|
||||||
"kernel.hostname",
|
"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",
|
"kernel.ns_last_pid",
|
||||||
"net.ipv4.route.flush",
|
"net.ipv4.route.flush",
|
||||||
"net.ipv6.route.flush",
|
"net.ipv6.route.flush",
|
||||||
|
|
@ -1131,6 +1137,21 @@ _SYSCTL_VOLATILE_KEYS = {
|
||||||
"vm.stat_refresh",
|
"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:
|
def _sysctl_proc_path(key: str) -> str:
|
||||||
return "/proc/sys/" + key.replace(".", "/")
|
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]:
|
def _sysctl_key_is_persistable(key: str) -> tuple[bool, str]:
|
||||||
if not key or not _SYSCTL_KEY_RE.fullmatch(key):
|
if not key or not _SYSCTL_KEY_RE.fullmatch(key):
|
||||||
return False, "invalid 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"
|
return False, "volatile/action key"
|
||||||
|
|
||||||
proc_path = _sysctl_proc_path(key)
|
proc_path = _sysctl_proc_path(key)
|
||||||
|
|
@ -1155,6 +1178,17 @@ def _sysctl_key_is_persistable(key: str) -> tuple[bool, str]:
|
||||||
return True, ""
|
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(
|
def _parse_sysctl_a_output(
|
||||||
text: str,
|
text: str,
|
||||||
*,
|
*,
|
||||||
|
|
@ -1199,7 +1233,7 @@ def _parse_sysctl_a_output(
|
||||||
skipped["duplicate"] += 1
|
skipped["duplicate"] += 1
|
||||||
continue
|
continue
|
||||||
if require_persistable:
|
if require_persistable:
|
||||||
ok, _reason = _sysctl_key_is_persistable(key)
|
ok, _reason = _sysctl_entry_is_persistable(key, value)
|
||||||
if not ok:
|
if not ok:
|
||||||
skipped["non_persistable"] += 1
|
skipped["non_persistable"] += 1
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -327,6 +327,52 @@ def test_parse_sysctl_a_output_keeps_persistable_values(monkeypatch):
|
||||||
assert skipped["duplicate"] == 1
|
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):
|
def test_collect_sysctl_snapshot_writes_generated_artifact(monkeypatch, tmp_path: Path):
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
h,
|
h,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue