1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0 3# 4# Copyright (c) 2025 Intel Corporation 5# 6# This contains kselftest framework adapted common functions for testing 7# mitigation for x86 bugs. 8 9import os, sys, re, shutil 10 11sys.path.insert(0, '../../kselftest') 12import ksft 13 14def read_file(path): 15 if not os.path.exists(path): 16 return None 17 with open(path, 'r') as file: 18 return file.read().strip() 19 20def cpuinfo_has(arg): 21 cpuinfo = read_file('/proc/cpuinfo') 22 if arg in cpuinfo: 23 return True 24 return False 25 26def cmdline_has(arg): 27 cmdline = read_file('/proc/cmdline') 28 if arg in cmdline: 29 return True 30 return False 31 32def cmdline_has_either(args): 33 cmdline = read_file('/proc/cmdline') 34 for arg in args: 35 if arg in cmdline: 36 return True 37 return False 38 39def cmdline_has_none(args): 40 return not cmdline_has_either(args) 41 42def cmdline_has_all(args): 43 cmdline = read_file('/proc/cmdline') 44 for arg in args: 45 if arg not in cmdline: 46 return False 47 return True 48 49def get_sysfs(bug): 50 return read_file("/sys/devices/system/cpu/vulnerabilities/" + bug) 51 52def sysfs_has(bug, mitigation): 53 status = get_sysfs(bug) 54 if mitigation in status: 55 return True 56 return False 57 58def sysfs_has_either(bugs, mitigations): 59 for bug in bugs: 60 for mitigation in mitigations: 61 if sysfs_has(bug, mitigation): 62 return True 63 return False 64 65def sysfs_has_none(bugs, mitigations): 66 return not sysfs_has_either(bugs, mitigations) 67 68def sysfs_has_all(bugs, mitigations): 69 for bug in bugs: 70 for mitigation in mitigations: 71 if not sysfs_has(bug, mitigation): 72 return False 73 return True 74 75def bug_check_pass(bug, found): 76 ksft.print_msg(f"\nFound: {found}") 77 # ksft.print_msg(f"\ncmdline: {read_file('/proc/cmdline')}") 78 ksft.test_result_pass(f'{bug}: {found}') 79 80def bug_check_fail(bug, found, expected): 81 ksft.print_msg(f'\nFound:\t {found}') 82 ksft.print_msg(f'Expected:\t {expected}') 83 ksft.print_msg(f"\ncmdline: {read_file('/proc/cmdline')}") 84 ksft.test_result_fail(f'{bug}: {found}') 85 86def bug_status_unknown(bug, found): 87 ksft.print_msg(f'\nUnknown status: {found}') 88 ksft.print_msg(f"\ncmdline: {read_file('/proc/cmdline')}") 89 ksft.test_result_fail(f'{bug}: {found}') 90 91def basic_checks_sufficient(bug, mitigation): 92 if not mitigation: 93 bug_status_unknown(bug, "None") 94 return True 95 elif mitigation == "Not affected": 96 ksft.test_result_pass(bug) 97 return True 98 elif mitigation == "Vulnerable": 99 if cmdline_has_either([f'{bug}=off', 'mitigations=off']): 100 bug_check_pass(bug, mitigation) 101 return True 102 return False 103 104def get_section_info(vmlinux, section_name): 105 from elftools.elf.elffile import ELFFile 106 with open(vmlinux, 'rb') as f: 107 elffile = ELFFile(f) 108 section = elffile.get_section_by_name(section_name) 109 if section is None: 110 ksft.print_msg("Available sections in vmlinux:") 111 for sec in elffile.iter_sections(): 112 ksft.print_msg(sec.name) 113 raise ValueError(f"Section {section_name} not found in {vmlinux}") 114 return section['sh_addr'], section['sh_offset'], section['sh_size'] 115 116def get_patch_sites(vmlinux, offset, size): 117 import struct 118 output = [] 119 with open(vmlinux, 'rb') as f: 120 f.seek(offset) 121 i = 0 122 while i < size: 123 data = f.read(4) # s32 124 if not data: 125 break 126 sym_offset = struct.unpack('<i', data)[0] + i 127 i += 4 128 output.append(sym_offset) 129 return output 130 131def get_instruction_from_vmlinux(elffile, section, virtual_address, target_address): 132 from capstone import Cs, CS_ARCH_X86, CS_MODE_64 133 section_start = section['sh_addr'] 134 section_end = section_start + section['sh_size'] 135 136 if not (section_start <= target_address < section_end): 137 return None 138 139 offset = target_address - section_start 140 code = section.data()[offset:offset + 16] 141 142 cap = init_capstone() 143 for instruction in cap.disasm(code, target_address): 144 if instruction.address == target_address: 145 return instruction 146 return None 147 148def init_capstone(): 149 from capstone import Cs, CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT 150 cap = Cs(CS_ARCH_X86, CS_MODE_64) 151 cap.syntax = CS_OPT_SYNTAX_ATT 152 return cap 153 154def get_runtime_kernel(): 155 import drgn 156 return drgn.program_from_kernel() 157 158def check_dependencies_or_skip(modules, script_name="unknown test"): 159 for mod in modules: 160 try: 161 __import__(mod) 162 except ImportError: 163 ksft.test_result_skip(f"Skipping {script_name}: missing module '{mod}'") 164 ksft.finished() 165