X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=kconfig_hardened_check%2F__init__.py;h=3e3997d867dbccb6f6f115dd791745b01e6e926c;hb=0a9d3d0f700260d38a39cc1735ee5bd63d3e8f36;hp=3e503490d50f38991f623ef4f497b34ebc7d30c7;hpb=cfb4075cf996cba050abbf56f7c6284c63145042;p=kconfig-hardened-check.git diff --git a/kconfig_hardened_check/__init__.py b/kconfig_hardened_check/__init__.py index 3e50349..3e3997d 100644 --- a/kconfig_hardened_check/__init__.py +++ b/kconfig_hardened_check/__init__.py @@ -77,12 +77,30 @@ SIMPLE_OPTION_TYPES = ('kconfig', 'version', 'cmdline') class OptCheck: # Constructor without the 'expected' parameter is for option presence checks (any value is OK) def __init__(self, reason, decision, name, expected=None): - assert(reason and decision and name), \ - 'invalid {} check for "{}"'.format(self.__class__.__name__, name) + assert(name and name == name.strip() and len(name.split()) == 1), \ + 'invalid name "{}" for {}'.format(name, self.__class__.__name__) self.name = name - self.expected = expected + + assert(decision and decision == decision.strip() and len(decision.split()) == 1), \ + 'invalid decision "{}" for "{}" check'.format(decision, name) self.decision = decision + + assert(reason and reason == reason.strip() and len(reason.split()) == 1), \ + 'invalid reason "{}" for "{}" check'.format(reason, name) self.reason = reason + + if expected: + assert(expected == expected.strip()), \ + 'invalid expected value "{}" for "{}" check (1)'.format(expected, name) + val_len = len(expected.split()) + if val_len == 3: + assert(expected == 'is not set' or expected == 'is not off'), \ + 'invalid expected value "{}" for "{}" check (2)'.format(expected, name) + else: + assert(val_len == 1), \ + 'invalid expected value "{}" for "{}" check (3)'.format(expected, name) + self.expected = expected + self.state = None self.result = None @@ -94,19 +112,29 @@ class OptCheck: # handle the option presence check if self.expected is None: if self.state is None: - self.result = 'FAIL: not present' + self.result = 'FAIL: is not present' else: self.result = 'OK: is present' return + # handle the 'is not off' option check + if self.expected == 'is not off': + if self.state == 'off': + self.result = 'FAIL: is off' + elif self.state is None: + self.result = 'FAIL: is off, not found' + else: + self.result = 'OK: is not off, "' + self.state + '"' + return + # handle the option value check if self.expected == self.state: self.result = 'OK' elif self.state is None: if self.expected == 'is not set': - self.result = 'OK: not found' + self.result = 'OK: is not found' else: - self.result = 'FAIL: not found' + self.result = 'FAIL: is not found' else: self.result = 'FAIL: "' + self.state + '"' @@ -144,6 +172,8 @@ class CmdlineCheck(OptCheck): class VersionCheck: def __init__(self, ver_expected): + assert(ver_expected and isinstance(ver_expected, tuple) and len(ver_expected) == 2), \ + 'invalid version "{}" for VersionCheck'.format(ver_expected) self.ver_expected = ver_expected self.ver = () self.result = None @@ -228,11 +258,13 @@ class OR(ComplexOptCheck): # Add more info for additional checks: if i != 0: if opt.result == 'OK': - self.result = 'OK: {} "{}"'.format(opt.name, opt.expected) - elif opt.result == 'OK: not found': - self.result = 'OK: {} not found'.format(opt.name) + self.result = 'OK: {} is "{}"'.format(opt.name, opt.expected) + elif opt.result == 'OK: is not found': + self.result = 'OK: {} is not found'.format(opt.name) elif opt.result == 'OK: is present': self.result = 'OK: {} is present'.format(opt.name) + elif opt.result.startswith('OK: is not off'): + self.result = 'OK: {} is not off'.format(opt.name) else: # VersionCheck provides enough info assert(opt.result.startswith('OK: version')), \ @@ -257,10 +289,14 @@ class AND(ComplexOptCheck): # This FAIL is caused by additional checks, # and not by the main option that this AND-check is about. # Describe the reason of the FAIL. - if opt.result.startswith('FAIL: \"') or opt.result == 'FAIL: not found': - self.result = 'FAIL: {} not "{}"'.format(opt.name, opt.expected) - elif opt.result == 'FAIL: not present': - self.result = 'FAIL: {} not present'.format(opt.name) + if opt.result.startswith('FAIL: \"') or opt.result == 'FAIL: is not found': + self.result = 'FAIL: {} is not "{}"'.format(opt.name, opt.expected) + elif opt.result == 'FAIL: is not present': + self.result = 'FAIL: {} is not present'.format(opt.name) + elif opt.result == 'FAIL: is off': + self.result = 'FAIL: {} is off'.format(opt.name) + elif opt.result == 'FAIL: is off, not found': + self.result = 'FAIL: {} is off, not found'.format(opt.name) else: # VersionCheck provides enough info self.result = opt.result @@ -387,6 +423,7 @@ def add_kconfig_checks(l, arch): l += [KconfigCheck('self_protection', 'defconfig', 'ARM64_PAN', 'y')] l += [KconfigCheck('self_protection', 'defconfig', 'ARM64_EPAN', 'y')] l += [KconfigCheck('self_protection', 'defconfig', 'UNMAP_KERNEL_AT_EL0', 'y')] + l += [KconfigCheck('self_protection', 'defconfig', 'ARM64_E0PD', 'y')] l += [OR(KconfigCheck('self_protection', 'defconfig', 'HARDEN_EL2_VECTORS', 'y'), AND(KconfigCheck('self_protection', 'defconfig', 'RANDOMIZE_BASE', 'y'), VersionCheck((5, 9))))] # HARDEN_EL2_VECTORS was included in RANDOMIZE_BASE in v5.9