diff --git a/servicereportpkg/repair/plugins/spyre_repair.py b/servicereportpkg/repair/plugins/spyre_repair.py index cbc4746..635487d 100644 --- a/servicereportpkg/repair/plugins/spyre_repair.py +++ b/servicereportpkg/repair/plugins/spyre_repair.py @@ -46,10 +46,25 @@ def fix_vfio_drive_config(self, plugin_obj, vfio_drive_config_check): def fix_user_mem_conf(self, plugin_obj, user_mem_conf_check): """Fix memory configuration usergroup""" + updated_lines = [] for config, val in user_mem_conf_check.get_config_attributes().items(): if not val["status"]: - append_to_file(user_mem_conf_check.get_file_path(), - "\n"+config) + try: + with open(user_mem_conf_check.get_file_path(), "r", encoding="utf-8") as file: + lines = file.readlines() + for line in lines: + # if a user mem config rule is redundant incorrect or old rule will be + # removed + if not re.match(r'^@sentient', line.strip()): + updated_lines.append(line) + + except FileNotFoundError: + self.log.error("File not found : %s", user_mem_conf_check.get_file_path()) + + updated_lines.append("\n"+config) + updated_string = "".join(updated_lines) + add_to_file(user_mem_conf_check.get_file_path(), + updated_string) re_check = plugin_obj.check_memlock_conf() if re_check.get_status(): diff --git a/servicereportpkg/validate/plugins/spyre.py b/servicereportpkg/validate/plugins/spyre.py index b4bc16c..c02492a 100644 --- a/servicereportpkg/validate/plugins/spyre.py +++ b/servicereportpkg/validate/plugins/spyre.py @@ -30,10 +30,21 @@ def __init__(self): self.name = Spyre.__name__ self.description = Spyre.__doc__ + """ + get_number_of_spyre_cards(): Get the number of spyre cards available in + the system. + + Args: + None + + Returns: + int: Number of spyre cards in the system. + """ @classmethod - def is_spyre_card_exists(cls): - """Return True if spyre exists in the system otherwise False""" + def get_number_of_spyre_cards(cls): + """Returns number of spyre cards in the device""" + number_of_cards = 0 context = pyudev.Context() # IBM vendor ID spyre_vendor_ids = ["0x1014"] @@ -49,15 +60,15 @@ def is_spyre_card_exists(cls): if device_id not in spyre_device_ids: continue - return True + number_of_cards += 1 - return False + return number_of_cards @classmethod def is_applicable(cls): """Returns True if plugin is applicable otherwise False""" - return Spyre.is_spyre_card_exists() + return Spyre.get_number_of_spyre_cards() > 0 def check_driver_config(self): """VFIO Driver configuration""" @@ -136,28 +147,73 @@ def check_udev_rule(self): conf_check.set_status(status) return conf_check - def check_memlock_conf(self): - """User memlock configuration""" + """ + is_mem_limit_config_valid(): Verify whether the current memlock + configuration satisfies or exceeds the expected VFIO memory configuration. - vfio_mem_conf = ["@sentient - memlock 134217728"] - config_file = "/etc/security/limits.d/memlock.conf" + Args: + config_file (str): File path to existing configuration + conf (str): Expected memlimit configuration - conf_check = ConfigurationFileCheck(self.check_memlock_conf.__doc__, - config_file) + Returns: + bool: True if current memlimit config is valid, False otherwise. + """ + def is_mem_limit_config_valid(self, config_file, conf): - status = True + # Example strings matching the pattern: + # "@sentient 1234", "@sentient unlimited", "@sentient 7890", + # "@sentient -memlock unlimited" + pattern = r'^(@sentient.+)\s+(unlimited|\d+)$' + status = False try: with open(config_file, "r", encoding="utf-8") as file: for line in file: line = line.strip() - if line in vfio_mem_conf: - conf_check.add_attribute(line, True, None, None) - vfio_mem_conf.remove(line) + if not line: + continue + + if line == conf: + status = True + + line_match = re.match(pattern, line) + conf_match = re.match(pattern, conf) + if line_match and conf_match: + line_str = line_match.group(1) + line_value = line_match.group(2) + conf_str = conf_match.group(1) + conf_value = conf_match.group(2) + if line_str == conf_str: + if (line_value == "unlimited" + or (int(line_value) >= int(conf_value))): + status = True except FileNotFoundError: self.log.error("File not found : %s", config_file) status = False + except ValueError as e: + self.log.error("Type casting error: %s", e) + status = False + + return status + + def check_memlock_conf(self): + """User memlock configuration""" + + num_cards = Spyre.get_number_of_spyre_cards() + memlimit = num_cards * 134234112 + vfio_mem_conf = [f"@sentient - memlock {memlimit}"] + config_file = "/etc/security/limits.d/memlock.conf" + + conf_check = ConfigurationFileCheck(self.check_memlock_conf.__doc__, + config_file) + + status = True + for conf in vfio_mem_conf[:]: + if self.is_mem_limit_config_valid(config_file, conf): + conf_check.add_attribute(conf, True, None, None) + vfio_mem_conf.remove(conf) + if vfio_mem_conf: status = False for conf in vfio_mem_conf: