1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
#!/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()
|