1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0 3 4from struct import pack 5from time import sleep 6 7import errno 8import glob 9import os 10import subprocess 11 12try: 13 import pytest 14except ImportError: 15 print("Unable to import pytest python module.") 16 print("\nIf not already installed, you may do so with:") 17 print("\t\tpip3 install pytest") 18 exit(1) 19 20SOCKETS = glob.glob('/sys/bus/auxiliary/devices/intel_vsec.sdsi.*') 21NUM_SOCKETS = len(SOCKETS) 22 23MODULE_NAME = 'intel_sdsi' 24DEV_PREFIX = 'intel_vsec.sdsi' 25CLASS_DIR = '/sys/bus/auxiliary/devices' 26GUID = "0x6dd191" 27 28def read_bin_file(file): 29 with open(file, mode='rb') as f: 30 content = f.read() 31 return content 32 33def get_dev_file_path(socket, file): 34 return CLASS_DIR + '/' + DEV_PREFIX + '.' + str(socket) + '/' + file 35 36def kmemleak_enabled(): 37 kmemleak = "/sys/kernel/debug/kmemleak" 38 return os.path.isfile(kmemleak) 39 40class TestSDSiDriver: 41 def test_driver_loaded(self): 42 lsmod_p = subprocess.Popen(('lsmod'), stdout=subprocess.PIPE) 43 result = subprocess.check_output(('grep', '-q', MODULE_NAME), stdin=lsmod_p.stdout) 44 45@pytest.mark.parametrize('socket', range(0, NUM_SOCKETS)) 46class TestSDSiFilesClass: 47 48 def read_value(self, file): 49 f = open(file, "r") 50 value = f.read().strip("\n") 51 return value 52 53 def get_dev_folder(self, socket): 54 return CLASS_DIR + '/' + DEV_PREFIX + '.' + str(socket) + '/' 55 56 def test_sysfs_files_exist(self, socket): 57 folder = self.get_dev_folder(socket) 58 print (folder) 59 assert os.path.isfile(folder + "guid") == True 60 assert os.path.isfile(folder + "provision_akc") == True 61 assert os.path.isfile(folder + "provision_cap") == True 62 assert os.path.isfile(folder + "state_certificate") == True 63 assert os.path.isfile(folder + "registers") == True 64 65 def test_sysfs_file_permissions(self, socket): 66 folder = self.get_dev_folder(socket) 67 mode = os.stat(folder + "guid").st_mode & 0o777 68 assert mode == 0o444 # Read all 69 mode = os.stat(folder + "registers").st_mode & 0o777 70 assert mode == 0o400 # Read owner 71 mode = os.stat(folder + "provision_akc").st_mode & 0o777 72 assert mode == 0o200 # Read owner 73 mode = os.stat(folder + "provision_cap").st_mode & 0o777 74 assert mode == 0o200 # Read owner 75 mode = os.stat(folder + "state_certificate").st_mode & 0o777 76 assert mode == 0o400 # Read owner 77 78 def test_sysfs_file_ownership(self, socket): 79 folder = self.get_dev_folder(socket) 80 81 st = os.stat(folder + "guid") 82 assert st.st_uid == 0 83 assert st.st_gid == 0 84 85 st = os.stat(folder + "registers") 86 assert st.st_uid == 0 87 assert st.st_gid == 0 88 89 st = os.stat(folder + "provision_akc") 90 assert st.st_uid == 0 91 assert st.st_gid == 0 92 93 st = os.stat(folder + "provision_cap") 94 assert st.st_uid == 0 95 assert st.st_gid == 0 96 97 st = os.stat(folder + "state_certificate") 98 assert st.st_uid == 0 99 assert st.st_gid == 0 100 101 def test_sysfs_file_sizes(self, socket): 102 folder = self.get_dev_folder(socket) 103 104 if self.read_value(folder + "guid") == GUID: 105 st = os.stat(folder + "registers") 106 assert st.st_size == 72 107 108 st = os.stat(folder + "provision_akc") 109 assert st.st_size == 1024 110 111 st = os.stat(folder + "provision_cap") 112 assert st.st_size == 1024 113 114 st = os.stat(folder + "state_certificate") 115 assert st.st_size == 4096 116 117 def test_no_seek_allowed(self, socket): 118 folder = self.get_dev_folder(socket) 119 rand_file = bytes(os.urandom(8)) 120 121 f = open(folder + "provision_cap", "wb", 0) 122 f.seek(1) 123 with pytest.raises(OSError) as error: 124 f.write(rand_file) 125 assert error.value.errno == errno.ESPIPE 126 f.close() 127 128 f = open(folder + "provision_akc", "wb", 0) 129 f.seek(1) 130 with pytest.raises(OSError) as error: 131 f.write(rand_file) 132 assert error.value.errno == errno.ESPIPE 133 f.close() 134 135 def test_registers_seek(self, socket): 136 folder = self.get_dev_folder(socket) 137 138 # Check that the value read from an offset of the entire 139 # file is none-zero and the same as the value read 140 # from seeking to the same location 141 f = open(folder + "registers", "rb") 142 data = f.read() 143 f.seek(64) 144 id = f.read() 145 assert id != bytes(0) 146 assert data[64:] == id 147 f.close() 148 149@pytest.mark.parametrize('socket', range(0, NUM_SOCKETS)) 150class TestSDSiMailboxCmdsClass: 151 def test_provision_akc_eoverflow_1017_bytes(self, socket): 152 153 # The buffer for writes is 1k, of with 8 bytes must be 154 # reserved for the command, leaving 1016 bytes max. 155 # Check that we get an overflow error for 1017 bytes. 156 node = get_dev_file_path(socket, "provision_akc") 157 rand_file = bytes(os.urandom(1017)) 158 159 f = open(node, 'wb', 0) 160 with pytest.raises(OSError) as error: 161 f.write(rand_file) 162 assert error.value.errno == errno.EOVERFLOW 163 f.close() 164 165@pytest.mark.parametrize('socket', range(0, NUM_SOCKETS)) 166class TestSdsiDriverLocksClass: 167 def test_enodev_when_pci_device_removed(self, socket): 168 node = get_dev_file_path(socket, "provision_akc") 169 dev_name = DEV_PREFIX + '.' + str(socket) 170 driver_dir = CLASS_DIR + '/' + dev_name + "/driver/" 171 rand_file = bytes(os.urandom(8)) 172 173 f = open(node, 'wb', 0) 174 g = open(node, 'wb', 0) 175 176 with open(driver_dir + 'unbind', 'w') as k: 177 print(dev_name, file = k) 178 179 with pytest.raises(OSError) as error: 180 f.write(rand_file) 181 assert error.value.errno == errno.ENODEV 182 183 with pytest.raises(OSError) as error: 184 g.write(rand_file) 185 assert error.value.errno == errno.ENODEV 186 187 f.close() 188 g.close() 189 190 # Short wait needed to allow file to close before pulling driver 191 sleep(1) 192 193 p = subprocess.Popen(('modprobe', '-r', 'intel_sdsi')) 194 p.wait() 195 p = subprocess.Popen(('modprobe', '-r', 'intel_vsec')) 196 p.wait() 197 p = subprocess.Popen(('modprobe', 'intel_vsec')) 198 p.wait() 199 200 # Short wait needed to allow driver time to get inserted 201 # before continuing tests 202 sleep(1) 203 204 def test_memory_leak(self, socket): 205 if not kmemleak_enabled(): 206 pytest.skip("kmemleak not enabled in kernel") 207 208 dev_name = DEV_PREFIX + '.' + str(socket) 209 driver_dir = CLASS_DIR + '/' + dev_name + "/driver/" 210 211 with open(driver_dir + 'unbind', 'w') as k: 212 print(dev_name, file = k) 213 214 sleep(1) 215 216 subprocess.check_output(('modprobe', '-r', 'intel_sdsi')) 217 subprocess.check_output(('modprobe', '-r', 'intel_vsec')) 218 219 with open('/sys/kernel/debug/kmemleak', 'w') as f: 220 print('scan', file = f) 221 sleep(5) 222 223 assert os.stat('/sys/kernel/debug/kmemleak').st_size == 0 224 225 subprocess.check_output(('modprobe', 'intel_vsec')) 226 sleep(1) 227