X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=kernel_hardening_checker%2Fengine.py;h=ee56d637b9b763e0dec0e9cfc41d38fcab3827cc;hb=d38ec317bd74b6144164346314599ddf391f2a32;hp=1c1f0c6ceb6a66388fef52008a452b51589124b1;hpb=ac56b1d1b46e28fd4296a21c17e725b069ed4aec;p=kconfig-hardened-check.git diff --git a/kernel_hardening_checker/engine.py b/kernel_hardening_checker/engine.py old mode 100644 new mode 100755 index 1c1f0c6..ee56d63 --- a/kernel_hardening_checker/engine.py +++ b/kernel_hardening_checker/engine.py @@ -9,15 +9,15 @@ This module is the engine of checks. """ # pylint: disable=missing-class-docstring,missing-function-docstring -# pylint: disable=line-too-long,invalid-name,too-many-branches +# pylint: disable=line-too-long,too-many-branches from __future__ import annotations import sys -from typing import Union, Optional, List, Dict, OrderedDict, Tuple +from typing import Union, Optional, List, Dict, Tuple StrOrNone = Optional[str] -TupleOrNone = Optional[Tuple] -TupleOrOrderedDict = Union[Tuple, OrderedDict[str, str]] +TupleOrNone = Optional[Tuple[int, ...]] +DictOrTuple = Union[Dict[str, str], Tuple[int, ...]] StrOrBool = Union[str, bool] GREEN_COLOR = '\x1b[32m' @@ -126,15 +126,15 @@ class OptCheck: "reason": self.reason, } # type: Dict[str, StrOrBool] if with_results: - assert self.result, f'unexpected empty result in {self.name}' + assert(self.result), f'unexpected empty result in {self.name}' dump["check_result"] = self.result dump["check_result_bool"] = self.result.startswith('OK') return dump class KconfigCheck(OptCheck): - def __init__(self, *args, **kwargs) -> None: - super().__init__(*args, **kwargs) + def __init__(self, *args: str) -> None: + super().__init__(*args) self.name = f'CONFIG_{self.name}' @property @@ -161,16 +161,18 @@ class VersionCheck: assert(all(map(lambda x: isinstance(x, int), ver_expected))), \ f'invalid expected version "{ver_expected}" for VersionCheck (2)' self.ver_expected = ver_expected - self.ver = (0, 0, 0) # type: Tuple[int, int, int] + self.ver = (0, 0, 0) # type: Tuple[int, ...] self.result = None # type: str | None @property def opt_type(self) -> str: return 'version' - def set_state(self, data: Tuple) -> None: + def set_state(self, data: Tuple[int, ...]) -> None: assert(data and isinstance(data, tuple) and len(data) >= 3), \ - f'invalid version "{data}" for VersionCheck' + f'invalid version "{data}" for VersionCheck (1)' + assert(all(map(lambda x: isinstance(x, int), data))), \ + f'invalid version "{data}" for VersionCheck (2)' self.ver = data[:3] def check(self) -> None: @@ -246,7 +248,7 @@ class ComplexOptCheck: dump = self.opts[0].json_dump(False) if with_results: # Add the 'check_result' and 'check_result_bool' keys to the dictionary - assert self.result, f'unexpected empty result in {self.name}' + assert(self.result), f'unexpected empty result in {self.name}' dump["check_result"] = self.result dump["check_result_bool"] = self.result.startswith('OK') return dump @@ -338,7 +340,7 @@ ChecklistObjType = Union[KconfigCheck, CmdlineCheck, SysctlCheck, OR, AND] AnyOptCheckType = Union[KconfigCheck, CmdlineCheck, SysctlCheck, VersionCheck, OR, AND] -def populate_simple_opt_with_data(opt: SimpleOptCheckType, data: TupleOrOrderedDict, data_type: str) -> None: +def populate_simple_opt_with_data(opt: SimpleOptCheckType, data: DictOrTuple, data_type: str) -> None: assert(opt.opt_type != 'complex'), f'unexpected opt_type "{opt.opt_type}" for {opt}' assert(opt.opt_type in SIMPLE_OPTION_TYPES), f'invalid opt_type "{opt.opt_type}"' assert(data_type in SIMPLE_OPTION_TYPES), f'invalid data_type "{data_type}"' @@ -348,7 +350,7 @@ def populate_simple_opt_with_data(opt: SimpleOptCheckType, data: TupleOrOrderedD return if data_type in ('kconfig', 'cmdline', 'sysctl'): - assert(isinstance(data, OrderedDict)), \ + assert(isinstance(data, dict)), \ f'unexpected data with data_type {data_type}' assert(isinstance(opt, SimpleNamedOptCheckTypes)), \ f'unexpected VersionCheck with opt_type "{opt.opt_type}"' @@ -361,7 +363,7 @@ def populate_simple_opt_with_data(opt: SimpleOptCheckType, data: TupleOrOrderedD opt.set_state(data) -def populate_opt_with_data(opt: AnyOptCheckType, data: TupleOrOrderedDict, data_type: str) -> None: +def populate_opt_with_data(opt: AnyOptCheckType, data: DictOrTuple, data_type: str) -> None: assert(opt.opt_type != 'version'), 'a single VersionCheck is useless' if opt.opt_type != 'complex': assert(isinstance(opt, SimpleOptCheckTypes)), \ @@ -380,39 +382,43 @@ def populate_opt_with_data(opt: AnyOptCheckType, data: TupleOrOrderedDict, data_ populate_opt_with_data(o, data, data_type) -def populate_with_data(checklist: List, data: TupleOrOrderedDict, data_type: str) -> None: +def populate_with_data(checklist: List[ChecklistObjType], data: DictOrTuple, data_type: str) -> None: for opt in checklist: populate_opt_with_data(opt, data, data_type) -def override_expected_value(checklist: List, name: str, new_val: str) -> None: +def override_expected_value(checklist: List[ChecklistObjType], name: str, new_val: str) -> None: for opt in checklist: if opt.name == name: - assert(opt.opt_type in ('kconfig', 'cmdline', 'sysctl')), \ - f'overriding an expected value for "{opt.opt_type}" checks is not supported yet' + assert(isinstance(opt, SimpleNamedOptCheckTypes)), \ + f'overriding an expected value for {opt}" is not supported yet' opt.expected = new_val -def perform_checks(checklist: List) -> None: +def perform_checks(checklist: List[ChecklistObjType]) -> None: for opt in checklist: opt.check() -def print_unknown_options(checklist: List, parsed_options: OrderedDict[str, str], opt_type: str) -> None: +def print_unknown_options(checklist: List[ChecklistObjType], parsed_options: Dict[str, str], opt_type: str) -> None: known_options = [] for o1 in checklist: - if o1.opt_type != 'complex': + if isinstance(o1, SimpleOptCheckTypes): + assert(o1.opt_type != 'complex'), f'{o1} with complex opt_type' + assert(not isinstance(o1, VersionCheck)), 'single VersionCheck in checklist' known_options.append(o1.name) continue for o2 in o1.opts: - if o2.opt_type != 'complex': + if isinstance(o2, SimpleOptCheckTypes): + assert(o2.opt_type != 'complex'), f'{o2} with complex opt_type' if hasattr(o2, 'name'): known_options.append(o2.name) continue for o3 in o2.opts: - assert(o3.opt_type != 'complex'), \ + assert(isinstance(o3, SimpleOptCheckTypes)), \ f'unexpected ComplexOptCheck inside {o2.name}' + assert(o3.opt_type != 'complex'), f'{o3} with complex opt_type' if hasattr(o3, 'name'): known_options.append(o3.name)