Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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()