def cpu_vulnerabilities(): """ Query sysfs for CPU vulnerabilities mitigation. :return: A dict where 'vendor': "Vendor ID" field returned by lscpu. Possible values: GenuineIntel, AuthenticAMD, ARM. 'vulnerable': False if not vulnerable, True if vulnerable, None if in doubt. Present if vendor is GenuineIntel. 'mitigations_disabled': whether any mitigation was disabled in kernel cmdline. Present if vulnerable is None. """ from sh import lscpu os.environ[ 'LC_ALL'] = 'en_US' # switch language to English to be able to parse lscpu output. vendor_id = None for line in lscpu().stdout.decode().split('\n'): param = line.split(':', 1) if param and param[0] == 'Vendor ID': vendor_id = param[1].strip() break # TODO: switch LC_ALL back? res = {'vendor': vendor_id} if vendor_id != "GenuineIntel": # Not an Intel CPU, most probably not vulnerable return res sys_vulnerabilities = Path('/sys/devices/system/cpu/vulnerabilities') if not sys_vulnerabilities.is_dir(): # Directory does not exist: either smth is bind-mounted over it or the kernel is too old. vulnerable = None else: vulnerable = False vulns = ['l1tf', 'meltdown', 'spectre_v1', 'spectre_v2'] if detect_cloud() != CloudProvider.AMAZON: # AWS reports no mitigation for those vulnerabilities, as if they are not mitigated at all. # But we decided to trust AWS and assume it's not vulnerable. vulns += ['spec_store_bypass', 'mds'] for name in vulns: status_file = sys_vulnerabilities / name if status_file.is_file(): # If CPU is not prone to this vulnerability the status file will start with # 'Not affected' or 'Mitigation: ...'. Otherwise it will start with 'Vulnerable: ...'. if status_file.read_text().startswith('Vulnerable'): vulnerable = True break else: # Status file does not exist: smth is bind-mounted over it or the kernel is not completely patched. vulnerable = None break res['vulnerable'] = vulnerable # If we can't confidently tell if CPU is vulnerable we search cmdline for mitigation disablement params and let # the server do the rest. if vulnerable is None: mitigations_disabled = False mitigation_cmdline_params = { 'nopti': '', 'nospectre_v1': '', 'nospectre_v2': '', 'mds': 'off', 'pti': 'off', 'mitigations': 'off', 'spectre_v2': 'off', 'spectre_v2_user': '******', 'spec_store_bypass_disable': 'off' } cmdline = kernel_cmdline() for pname, pvalue in mitigation_cmdline_params.items(): if cmdline.get(pname) == pvalue: mitigations_disabled = True break res['mitigations_disabled'] = mitigations_disabled return res
def ui_command_lscpu(self): """ lscpu - CPU architecture information helper. """ print sh.lscpu()