| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- #!/usr/bin/env python3
- # SPDX-License-Identifier: GPL-2.0
- #
- # Copyright (c) 2025 Intel Corporation
- #
- # This contains kselftest framework adapted common functions for testing
- # mitigation for x86 bugs.
- import os, sys, re, shutil
- sys.path.insert(0, '../../kselftest')
- import ksft
- def read_file(path):
- if not os.path.exists(path):
- return None
- with open(path, 'r') as file:
- return file.read().strip()
- def cpuinfo_has(arg):
- cpuinfo = read_file('/proc/cpuinfo')
- if arg in cpuinfo:
- return True
- return False
- def cmdline_has(arg):
- cmdline = read_file('/proc/cmdline')
- if arg in cmdline:
- return True
- return False
- def cmdline_has_either(args):
- cmdline = read_file('/proc/cmdline')
- for arg in args:
- if arg in cmdline:
- return True
- return False
- def cmdline_has_none(args):
- return not cmdline_has_either(args)
- def cmdline_has_all(args):
- cmdline = read_file('/proc/cmdline')
- for arg in args:
- if arg not in cmdline:
- return False
- return True
- def get_sysfs(bug):
- return read_file("/sys/devices/system/cpu/vulnerabilities/" + bug)
- def sysfs_has(bug, mitigation):
- status = get_sysfs(bug)
- if mitigation in status:
- return True
- return False
- def sysfs_has_either(bugs, mitigations):
- for bug in bugs:
- for mitigation in mitigations:
- if sysfs_has(bug, mitigation):
- return True
- return False
- def sysfs_has_none(bugs, mitigations):
- return not sysfs_has_either(bugs, mitigations)
- def sysfs_has_all(bugs, mitigations):
- for bug in bugs:
- for mitigation in mitigations:
- if not sysfs_has(bug, mitigation):
- return False
- return True
- def bug_check_pass(bug, found):
- ksft.print_msg(f"\nFound: {found}")
- # ksft.print_msg(f"\ncmdline: {read_file('/proc/cmdline')}")
- ksft.test_result_pass(f'{bug}: {found}')
- def bug_check_fail(bug, found, expected):
- ksft.print_msg(f'\nFound:\t {found}')
- ksft.print_msg(f'Expected:\t {expected}')
- ksft.print_msg(f"\ncmdline: {read_file('/proc/cmdline')}")
- ksft.test_result_fail(f'{bug}: {found}')
- def bug_status_unknown(bug, found):
- ksft.print_msg(f'\nUnknown status: {found}')
- ksft.print_msg(f"\ncmdline: {read_file('/proc/cmdline')}")
- ksft.test_result_fail(f'{bug}: {found}')
- def basic_checks_sufficient(bug, mitigation):
- if not mitigation:
- bug_status_unknown(bug, "None")
- return True
- elif mitigation == "Not affected":
- ksft.test_result_pass(bug)
- return True
- elif mitigation == "Vulnerable":
- if cmdline_has_either([f'{bug}=off', 'mitigations=off']):
- bug_check_pass(bug, mitigation)
- return True
- return False
- def get_section_info(vmlinux, section_name):
- from elftools.elf.elffile import ELFFile
- with open(vmlinux, 'rb') as f:
- elffile = ELFFile(f)
- section = elffile.get_section_by_name(section_name)
- if section is None:
- ksft.print_msg("Available sections in vmlinux:")
- for sec in elffile.iter_sections():
- ksft.print_msg(sec.name)
- raise ValueError(f"Section {section_name} not found in {vmlinux}")
- return section['sh_addr'], section['sh_offset'], section['sh_size']
- def get_patch_sites(vmlinux, offset, size):
- import struct
- output = []
- with open(vmlinux, 'rb') as f:
- f.seek(offset)
- i = 0
- while i < size:
- data = f.read(4) # s32
- if not data:
- break
- sym_offset = struct.unpack('<i', data)[0] + i
- i += 4
- output.append(sym_offset)
- return output
- def get_instruction_from_vmlinux(elffile, section, virtual_address, target_address):
- from capstone import Cs, CS_ARCH_X86, CS_MODE_64
- section_start = section['sh_addr']
- section_end = section_start + section['sh_size']
- if not (section_start <= target_address < section_end):
- return None
- offset = target_address - section_start
- code = section.data()[offset:offset + 16]
- cap = init_capstone()
- for instruction in cap.disasm(code, target_address):
- if instruction.address == target_address:
- return instruction
- return None
- def init_capstone():
- from capstone import Cs, CS_ARCH_X86, CS_MODE_64, CS_OPT_SYNTAX_ATT
- cap = Cs(CS_ARCH_X86, CS_MODE_64)
- cap.syntax = CS_OPT_SYNTAX_ATT
- return cap
- def get_runtime_kernel():
- import drgn
- return drgn.program_from_kernel()
- def check_dependencies_or_skip(modules, script_name="unknown test"):
- for mod in modules:
- try:
- __import__(mod)
- except ImportError:
- ksft.test_result_skip(f"Skipping {script_name}: missing module '{mod}'")
- ksft.finished()
|