File Index
Files and directories
Sign in
FILE

common.py

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/x86/bugs/common.py PYTHON
  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()
~/ Read-only file preview.