Compare commits

..

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
7448cf03b6
!168 [sync] PR-165: [bug fix]update register template file
From: @openeuler-sync-bot 
Reviewed-by: @Lostwayzxc 
Signed-off-by: @Lostwayzxc
2024-07-02 02:26:45 +00:00
rabbitali
305a52e069 update register template file
(cherry picked from commit 5611fc4c59a449c6c27a8ee8e4834cdbe67f8a44)
2024-06-17 15:31:10 +08:00
openeuler-ci-bot
5ee664a67e
!163 [sync] PR-162: [bugfix]override list file method
From: @openeuler-sync-bot 
Reviewed-by: @zhu-yuncheng 
Signed-off-by: @zhu-yuncheng
2024-02-07 07:59:38 +00:00
rabbitali
1c4a235e67 override list file method
(cherry picked from commit 05c5c2804f86d83d47c2e08cef926ff3c7f17996)
2024-02-07 15:15:33 +08:00
openeuler-ci-bot
ae5f805fb3
!160 [sync] PR-158: [bug fix]fix cve-2021-33633
From: @openeuler-sync-bot 
Reviewed-by: @zhu-yuncheng 
Signed-off-by: @zhu-yuncheng
2024-02-06 12:52:29 +00:00
rabbitali
9deaa24417 fix cve-2021-33633
(cherry picked from commit 6aa4bd6c9e8cda79856343d9573170e85081a44d)
2024-02-06 20:07:18 +08:00
openeuler-ci-bot
6cedf8743b
!157 [sync] PR-153: remove installed rpm if unreboot and improve log info for rollback operation
From: @openeuler-sync-bot 
Reviewed-by: @zhu-yuncheng 
Signed-off-by: @zhu-yuncheng
2023-12-25 02:32:21 +00:00
wang-guangge
08d29dedeb remove installed rpm if unreboot and improve log info for rollback operation
(cherry picked from commit ab3d4ddde6ebe09f33e8bce657bdb1d3374736ce)
2023-12-25 09:37:51 +08:00
openeuler-ci-bot
782e4bfb94
!149 由于master分支与其它代码差异较大, 手动同步master分支为最新代码
From: @rabbitali 
Reviewed-by: @zhu-yuncheng 
Signed-off-by: @zhu-yuncheng
2023-12-22 03:59:53 +00:00
rabbitali
31809edede update version to v1.4.1 2023-12-21 09:30:16 +08:00
15 changed files with 1150 additions and 2488 deletions

View File

@ -0,0 +1,202 @@
From 2229dade5b178fa2f6a3b572f110eb4fe6677935 Mon Sep 17 00:00:00 2001
From: wang-guangge <wangguangge@huawei.com>
Date: Mon, 18 Dec 2023 21:59:46 +0800
Subject: [PATCH] improve task execution status code and hotupgrade logic of
reinstalling active/accept hotpatch
---
hotpatch/hotupgrade.py | 69 +++++++++++++++++++++++++++++++-----------
hotpatch/upgrade_en.py | 6 ++--
2 files changed, 54 insertions(+), 21 deletions(-)
diff --git a/hotpatch/hotupgrade.py b/hotpatch/hotupgrade.py
index 5dfee0d..37497cf 100644
--- a/hotpatch/hotupgrade.py
+++ b/hotpatch/hotupgrade.py
@@ -13,6 +13,7 @@
from __future__ import print_function
from time import sleep
+from typing import Tuple
import dnf.base
import dnf.exceptions
@@ -28,6 +29,8 @@ from .upgrade_en import UpgradeEnhanceCommand
from .version import Versions
EMPTY_TAG = "-"
+SUCCEED = 0
+FAIL = 255
@dnf.plugin.register_command
@@ -94,9 +97,14 @@ class HotupgradeCommand(dnf.cli.Command):
logger.info(_('No hot patches marked for install.'))
return
- applied_old_patches = self._get_applied_old_patch(list(available_hp_dict.values()))
- if applied_old_patches:
- self._remove_hot_patches(applied_old_patches)
+ uneffectived_old_patches, effectived_old_patches = self._get_applied_old_patch(list(available_hp_dict.values()))
+ # remove effectived hp from self.hp_list and available_hp_dict
+ effectived_hp_list = [key for key, value in available_hp_dict.items() if value in effectived_old_patches]
+ self.hp_list = [hp for hp in self.hp_list if hp not in effectived_hp_list]
+ available_hp_dict = {key: value for key, value in available_hp_dict.items() if value not in effectived_hp_list}
+
+ if uneffectived_old_patches:
+ self._remove_hot_patches(uneffectived_old_patches)
else:
self.syscare.save()
success = self._install_rpm_pkg(list(available_hp_dict.keys()))
@@ -143,14 +151,24 @@ class HotupgradeCommand(dnf.cli.Command):
if str(ts_item.pkg) == self.kernel_coldpatch:
self.is_kernel_coldpatch_installed = True
- self.keep_hp_operation_atomic(is_all_kernel_hp_actived, target_remove_hp)
+ is_task_success = True
+ is_task_success &= self.keep_hp_operation_atomic(is_all_kernel_hp_actived, target_remove_hp)
if self.is_need_accept_kernel_hp and acceptable_hp:
+ is_accept_success = True
logger.info(_('No available kernel cold patch for takeover, gonna accept available kernel hot patch.'))
for hp in acceptable_hp:
- self._accept_kernel_hp(hp)
+ pkg_info = self._parse_hp_name(hp)
+ if pkg_info['target_name'] != "kernel":
+ continue
+ is_accept_success &= False if self._accept_hp(hp) != SUCCEED else True
+ # if need accept operation but failed, it indicates hotupgrade task failed
+ is_task_success &= is_accept_success
+
+ if not is_task_success:
+ exit(1)
- def keep_hp_operation_atomic(self, is_all_kernel_hp_actived, target_remove_hp):
+ def keep_hp_operation_atomic(self, is_all_kernel_hp_actived, target_remove_hp) -> bool:
"""
Keep hotpatch related operation atomic. Once one kernel hotpatch is not successfully activated or
kabi check fails, uninstall the kernel coldpatch. And unsuccessfully activated hotpatch package
@@ -159,9 +177,13 @@ class HotupgradeCommand(dnf.cli.Command):
Args:
is_all_kernel_hp_actived(bool): are all kernel related hotpatches activated
target_remove_hp(list): target remove hotpatch list
+
+ Returns:
+ bool: if hotupgrade task success
"""
upgrade_en = UpgradeEnhanceCommand(self.cli)
+ is_task_success = True
if self.is_kernel_coldpatch_installed:
if not is_all_kernel_hp_actived:
logger.info(_('Gonna remove %s due to some kernel hotpatch activation failed.'), self.kernel_coldpatch)
@@ -177,8 +199,12 @@ class HotupgradeCommand(dnf.cli.Command):
if target_remove_hp:
logger.info(_('Gonna remove unsuccessfully activated hotpatch rpm.'))
+ # when processing remove operation, do not achieve the expected result of activating hotpatch rpm,
+ # it indicates that the hotupgrade task failed
+ is_task_success &= False
for hotpatch in target_remove_hp:
upgrade_en.remove_rpm(hotpatch)
+ return is_task_success
def _apply_hp(self, hp_full_name):
pkg_info = self._parse_hp_name(hp_full_name)
@@ -264,7 +290,7 @@ class HotupgradeCommand(dnf.cli.Command):
return hp_map
@staticmethod
- def _get_applied_old_patch(available_hp_list: list) -> list:
+ def _get_applied_old_patch(available_hp_list: list) -> Tuple[list, list]:
"""
get targets' applied accumulative hot patches.
User can install and apply multiple sgl (single) hot patches because the rpm name is different,
@@ -273,9 +299,11 @@ class HotupgradeCommand(dnf.cli.Command):
available_hp_list: e.g. ['redis-1.0-1/ACC-1-1', 'redis-1.0-1/SGL_CVE_2022_1-1-1']
Returns:
- list: applied hot patches. e.g. ['redis-1.0-1/ACC-1-1']
+ Tuple[str, str]: a tuple containing two elements (uneffectived hot patches, effectived hot patches).
+ e.g. (['redis-1.0-1/ACC-1-1'], ['redis-1.0-1/SGL_CVE_2022_3047-1-1'])
"""
- hotpatch_set = set()
+ uneffectived_hotpatch_set = set()
+ effectived_hotpatch_set = set()
hps_info = Syscare.list()
for hp_info in hps_info:
# hp_info[Name] is the middle column of syscare list. format: {target_rpm_name}/{hp_name}/{binary_file}
@@ -297,9 +325,12 @@ class HotupgradeCommand(dnf.cli.Command):
hp_info["Status"],
binary_file,
)
- if hotpatch not in hotpatch_set:
- hotpatch_set.add(hotpatch)
- return list(hotpatch_set)
+ if hp_info["Status"] in ["ACTIVED", "ACCEPTED"]:
+ effectived_hotpatch_set.add(hotpatch)
+ continue
+ if hotpatch not in uneffectived_hotpatch_set:
+ uneffectived_hotpatch_set.add(hotpatch)
+ return list(uneffectived_hotpatch_set), list(effectived_hotpatch_set)
def _remove_hot_patches(self, applied_old_patches: list) -> None:
# output = Output(self.base, dnf.conf.Conf())
@@ -548,19 +579,21 @@ class HotupgradeCommand(dnf.cli.Command):
parsed_nevra = parsed_nevras[0]
return parsed_nevra.name, "%s-%s" % (parsed_nevra.version, parsed_nevra.release)
- def _accept_kernel_hp(self, hp_full_name: str):
+ def _accept_hp(self, hp_full_name: str) -> int:
"""
- accept kernel hot patch
+ accept hot patch
Args:
str: hp_full_name: full name of hot patch. e.g. patch-kernel-5.10.0-1-ACC-1-1.x86_64
+
+ Returns:
+ int: status
"""
pkg_info = self._parse_hp_name(hp_full_name)
- if pkg_info['target_name'] != "kernel":
- return
hp_subname = self._get_hp_subname_for_syscare(pkg_info)
output, status = self.syscare.accept(hp_subname)
if status:
- logger.info(_('Accept kernel hot patch failed: %s.'), hp_subname)
+ logger.info(_('Accept hot patch failed: %s.'), hp_subname)
else:
- logger.info(_('Accept kernel hot patch succeed: %s.'), hp_subname)
+ logger.info(_('Accept hot patch succeed: %s.'), hp_subname)
+ return status
diff --git a/hotpatch/upgrade_en.py b/hotpatch/upgrade_en.py
index 3053179..94ba4da 100644
--- a/hotpatch/upgrade_en.py
+++ b/hotpatch/upgrade_en.py
@@ -97,7 +97,10 @@ class UpgradeEnhanceCommand(dnf.cli.Command):
print('Gonna remove %s due to kabi check failed.' % kernel_pkg)
# rebuild rpm database for processing kernel rpm remove operation
self.rebuild_rpm_db()
+ # when processing remove operation, do not achieve the expected result of installing related rpm,
+ # it indicates that the upgrade task failed
self.remove_rpm(kernel_pkg)
+ exit(1)
def remove_rpm(self, pkg: str):
"""
@@ -113,11 +116,8 @@ class UpgradeEnhanceCommand(dnf.cli.Command):
if return_code != SUCCEED:
print('Remove package failed: %s.' % pkg)
print(output)
- exit(1)
else:
print('Remove package succeed: %s.' % pkg)
- # do not achieve the expected result of installing related rpm
- exit(1)
def rebuild_rpm_db(self):
"""
--
2.27.0

View File

@ -1,628 +0,0 @@
From 0f0cbce6c93b97e312cafead937b46e6b2ceaf51 Mon Sep 17 00:00:00 2001
From: wang-guangge <wangguangge@huawei.com>
Date: Thu, 9 Nov 2023 10:46:33 +0800
Subject: [PATCH] support kabi check
---
ceres/manages/vulnerability_manage.py | 2 +-
hotpatch/hotupgrade.py | 97 +++++-
hotpatch/updateinfo_parse.py | 3 +
hotpatch/upgrade_en.py | 413 ++++++++++++++++++++++++++
4 files changed, 506 insertions(+), 9 deletions(-)
create mode 100644 hotpatch/upgrade_en.py
diff --git a/ceres/manages/vulnerability_manage.py b/ceres/manages/vulnerability_manage.py
index c41a7fa..bad2dee 100644
--- a/ceres/manages/vulnerability_manage.py
+++ b/ceres/manages/vulnerability_manage.py
@@ -620,7 +620,7 @@ class VulnerabilityManage:
Tuple[str, str]
a tuple containing two elements (update result, log).
"""
- code, stdout, stderr = execute_shell_command(f"dnf update {rpm_name} -y")
+ code, stdout, stderr = execute_shell_command(f"dnf upgrade-en {rpm_name} -y")
if code != CommandExitCode.SUCCEED:
return TaskExecuteRes.FAIL, stderr
if "Complete" not in stdout:
diff --git a/hotpatch/hotupgrade.py b/hotpatch/hotupgrade.py
index f61e37f..c508e07 100644
--- a/hotpatch/hotupgrade.py
+++ b/hotpatch/hotupgrade.py
@@ -12,16 +12,14 @@
# ******************************************************************************/
from __future__ import print_function
-from time import sleep
import dnf.base
import dnf.exceptions
import hawkey
+from time import sleep
from dnf.cli import commands
from dnf.cli.option_parser import OptionParser
-
-# from dnf.cli.output import Output
from dnfpluginscore import _, logger
-
+from .upgrade_en import UpgradeEnhanceCommand
from .hot_updateinfo import HotUpdateinfoCommand
from .updateinfo_parse import HotpatchUpdateInfo
from .syscare import Syscare
@@ -37,6 +35,9 @@ class HotupgradeCommand(dnf.cli.Command):
usage = ""
syscare = Syscare()
hp_list = []
+ is_need_accept_kernel_hp = False
+ is_kernel_coldpatch_installed = False
+ kernel_coldpatch = ''
@staticmethod
def set_argparser(parser):
@@ -50,6 +51,13 @@ class HotupgradeCommand(dnf.cli.Command):
parser.add_argument(
"--takeover", default=False, action='store_true', help=_('kernel cold patch takeover operation')
)
+ parser.add_argument(
+ "-f",
+ dest='force',
+ default=False,
+ action='store_true',
+ help=_('force retain kernel rpm package if kernel kabi check fails'),
+ )
def configure(self):
"""Verify that conditions are met so that this command can run.
@@ -104,17 +112,72 @@ class HotupgradeCommand(dnf.cli.Command):
def run_transaction(self) -> None:
"""
- apply hot patches
+ apply hot patches, and process kabi check for kernel package rpm.
Returns:
None
"""
# syscare need a little bit time to process the installed hot patch
sleep(0.5)
+
+ is_all_kernel_hp_actived = True
+ # hotpatch that fail to be activated will be automatically uninstalled
+ target_remove_hp = []
+ acceptable_hp = []
for hp in self.hp_list:
- self._apply_hp(hp)
- if self.opts.takeover and self.is_need_accept_kernel_hp:
+ status = self._apply_hp(hp)
+ if status:
+ target_remove_hp.append(hp)
+ if not hp.startswith('patch-kernel-'):
+ continue
+ if status:
+ is_all_kernel_hp_actived &= False
+ else:
+ is_all_kernel_hp_actived &= True
+ acceptable_hp.append(hp)
+
+ for ts_item in self.base.transaction:
+ if ts_item.action not in dnf.transaction.FORWARD_ACTIONS:
+ continue
+ if str(ts_item.pkg) == self.kernel_coldpatch:
+ self.is_kernel_coldpatch_installed = True
+
+ self.keep_hp_operation_atomic(is_all_kernel_hp_actived, target_remove_hp)
+
+ if self.is_need_accept_kernel_hp and acceptable_hp:
+ logger.info(_('No available kernel cold patch for takeover, gonna accept available kernel hot patch.'))
+ for hp in acceptable_hp:
self._accept_kernel_hp(hp)
+ def keep_hp_operation_atomic(self, is_all_kernel_hp_actived, target_remove_hp):
+ """
+ Keep hotpatch related operation atomic. Once one kernel hotpatch is not successfully activated or
+ kabi check fails, uninstall the kernel coldpatch. And unsuccessfully activated hotpatch package
+ will be removed.
+
+ Args:
+ is_all_kernel_hp_actived(bool): are all kernel related hotpatches activated
+ target_remove_hp(list): target remove hotpatch list
+ """
+ upgrade_en = UpgradeEnhanceCommand(self.cli)
+
+ if self.is_kernel_coldpatch_installed:
+ if not is_all_kernel_hp_actived:
+ logger.info(_('Gonna remove %s due to some kernel hotpatch activation failed.'), self.kernel_coldpatch)
+ upgrade_en.remove_rpm(str(self.kernel_coldpatch))
+ self.is_need_accept_kernel_hp = False
+ # process kabi check
+ elif not upgrade_en.kabi_check(str(self.kernel_coldpatch)) and not self.opts.force:
+ logger.info(_('Gonna remove %s due to Kabi check failed.'), self.kernel_coldpatch)
+ # rebuild rpm database for processing kernel rpm remove operation
+ upgrade_en.rebuild_rpm_db()
+ upgrade_en.remove_rpm(str(self.kernel_coldpatch))
+ self.is_need_accept_kernel_hp = True
+
+ if target_remove_hp:
+ logger.info(_('Gonna remove unsuccessfully activated hotpatch rpm.'))
+ for hotpatch in target_remove_hp:
+ upgrade_en.remove_rpm(hotpatch)
+
def _apply_hp(self, hp_full_name):
pkg_info = self._parse_hp_name(hp_full_name)
hp_subname = self._get_hp_subname_for_syscare(pkg_info)
@@ -123,6 +186,7 @@ class HotupgradeCommand(dnf.cli.Command):
logger.info(_('Apply hot patch failed: %s.'), hp_subname)
else:
logger.info(_('Apply hot patch succeed: %s.'), hp_subname)
+ return status
@staticmethod
def _get_hp_subname_for_syscare(pkg_info: dict) -> str:
@@ -394,9 +458,11 @@ class HotupgradeCommand(dnf.cli.Command):
"""
process takeover operation.
"""
+ if not self.get_kernel_hp_list():
+ return
kernel_coldpatch = self.get_target_installed_kernel_coldpatch_of_hotpatch()
- self.is_need_accept_kernel_hp = False
if kernel_coldpatch:
+ self.kernel_coldpatch = kernel_coldpatch
logger.info(_("Gonna takeover kernel cold patch: ['%s']" % kernel_coldpatch))
success = self._install_rpm_pkg([kernel_coldpatch])
if success:
@@ -412,6 +478,21 @@ class HotupgradeCommand(dnf.cli.Command):
)
return
+ def get_kernel_hp_list(self) -> list:
+ """
+ Get kernel hp list from self.hp_list.
+
+ Returns:
+ list: kernel hp list
+ e.g.
+ ['patch-kernel-5.10.0-153.12.0.92.oe2203sp2-ACC-1-1.x86_64']
+ """
+ kernel_hp_list = []
+ for hp in self.hp_list:
+ if hp.startswith('patch-kernel-'):
+ kernel_hp_list.append(hp)
+ return kernel_hp_list
+
def get_target_installed_kernel_coldpatch_of_hotpatch(self) -> str:
"""
get the highest kernel cold patch of hot patch in "dnf hot-updateinfo list cves", if the corresponding
diff --git a/hotpatch/updateinfo_parse.py b/hotpatch/updateinfo_parse.py
index 4760378..fc39d48 100644
--- a/hotpatch/updateinfo_parse.py
+++ b/hotpatch/updateinfo_parse.py
@@ -322,6 +322,9 @@ class HotpatchUpdateInfo(object):
cmd = ["uname", "-r"]
kernel_version = ''
kernel_version, return_code = cmd_output(cmd)
+ # 'uname -r' show the kernel version-release.arch of the current system
+ # [root@openEuler hotpatch]# uname -r
+ # 5.10.0-136.12.0.86.oe2203sp1.x86_64
if return_code != SUCCEED:
return kernel_version
kernel_version = kernel_version.split('\n')[0]
diff --git a/hotpatch/upgrade_en.py b/hotpatch/upgrade_en.py
new file mode 100644
index 0000000..266bcae
--- /dev/null
+++ b/hotpatch/upgrade_en.py
@@ -0,0 +1,413 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+import dnf
+import gzip
+import subprocess
+from dnfpluginscore import _
+from dnf.cli import commands
+from dnf.cli.commands.upgrade import UpgradeCommand
+from dnf.cli.option_parser import OptionParser
+
+SUCCEED = 0
+FAIL = 255
+
+
+def cmd_output(cmd):
+ try:
+ result = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ result.wait()
+ return result.stdout.read().decode('utf-8'), result.returncode
+ except Exception as e:
+ print("error: ", e)
+ return str(e), FAIL
+
+
+@dnf.plugin.register_command
+class UpgradeEnhanceCommand(dnf.cli.Command):
+ SYMVERS_FILE = "/boot/symvers-%s.gz"
+
+ aliases = ['upgrade-en']
+ summary = _(
+ 'upgrade with KABI(Kernel Application Binary Interface) check. If the loaded kernel modules \
+ have KABI compatibility with the new version kernel rpm, the kernel modules can be installed \
+ and used in the new version kernel without recompling.'
+ )
+
+ @staticmethod
+ def set_argparser(parser):
+ parser.add_argument(
+ 'packages',
+ nargs='*',
+ help=_('Package to upgrade'),
+ action=OptionParser.ParseSpecGroupFileCallback,
+ metavar=_('PACKAGE'),
+ )
+ parser.add_argument(
+ "-f",
+ dest='force',
+ default=False,
+ action='store_true',
+ help=_('force retain kernel rpm package if kernel kabi check fails'),
+ )
+
+ def configure(self):
+ """Verify that conditions are met so that this command can run.
+
+ These include that there are enabled repositories with gpg
+ keys, and that this command is being run by the root user.
+ """
+ demands = self.cli.demands
+ demands.sack_activation = True
+ demands.available_repos = True
+ demands.resolving = True
+ demands.root_user = True
+ commands._checkGPGKey(self.base, self.cli)
+ if not self.opts.filenames:
+ commands._checkEnabledRepo(self.base)
+ self.upgrade_minimal = None
+ self.all_security = None
+ self.skipped_grp_specs = None
+
+ def run(self):
+ self.upgrade()
+
+ def run_transaction(self):
+ """
+ Process kabi check for kernel rpm package installed this time. If the kernel rpm pakcgae fails kabi check,
+ uninstall it.
+ """
+ for ts_item in self.base.transaction:
+ if ts_item.action not in dnf.transaction.FORWARD_ACTIONS:
+ continue
+ if ts_item.pkg.name == 'kernel':
+ kernel_pkg = str(ts_item.pkg)
+ success = self.kabi_check(kernel_pkg)
+ if not success and not self.opts.force:
+ print('Gonna remove %s due to kabi check failed.' % kernel_pkg)
+ # rebuild rpm database for processing kernel rpm remove operation
+ self.rebuild_rpm_db()
+ self.remove_rpm(kernel_pkg)
+
+ def remove_rpm(self, pkg: str):
+ """
+ Remove rpm package via command line.
+
+ Args:
+ pkg(str): package name
+ e.g.
+ kernel-5.10.0-153.18.0.94.oe2203sp2.x86_64
+ """
+ remove_cmd = ["dnf", "remove", pkg, "-y"]
+ output, return_code = cmd_output(remove_cmd)
+ if return_code != SUCCEED:
+ print('Remove package failed: %s.' % pkg)
+ exit(1)
+ else:
+ print('Remove package succeed: %s.' % pkg)
+ # do not achieve the expected result of installing related kernel rpm
+ exit(1)
+
+ def rebuild_rpm_db(self):
+ """
+ Rebuild rpm database for processing kernel rpm remove operation.
+ """
+ rebuilddb_cmd = ["rpm", "--rebuilddb"]
+ output, return_code = cmd_output(rebuilddb_cmd)
+ if return_code != SUCCEED:
+ print('Rebuild rpm database failed.')
+ else:
+ print('Rebuild rpm database succeed.')
+
+ def kabi_check(self, pkg: str) -> bool:
+ """
+ Process kabi check after upgrading kernel rpm.
+
+ Args:
+ pkg(str): package name
+ e.g.
+ kernel-5.10.0-153.18.0.94.oe2203sp2.x86_64
+
+ Returns:
+ bool: kabi check result
+ """
+ print("Kabi check for %s:" % pkg)
+ # version-release.arch
+ evra = pkg.split("-", 1)[1]
+ symvers_file = self.SYMVERS_FILE % (evra)
+
+ target_symvers_symbol_crc_mapping, return_code = self.get_target_symvers_symbol_crc_mapping(symvers_file)
+ if return_code != SUCCEED:
+ print('[Fail] Cannot find the symvers file of %s.', pkg)
+ return False
+ module_actual_symbol_crc_mapping = self.get_module_actual_symbol_crc_mapping()
+
+ module_different_symbol_crc_mapping = self.compare_actual_and_target_symvers_symbol_crc_mapping(
+ module_actual_symbol_crc_mapping, target_symvers_symbol_crc_mapping
+ )
+
+ sum_module_num = len(module_actual_symbol_crc_mapping)
+ fail_module_num = len(module_different_symbol_crc_mapping)
+ pass_module_num = sum_module_num - fail_module_num
+
+ reminder_statement = "Here are %s loaded kernel modules in this system, %s pass, %s fail." % (
+ sum_module_num,
+ pass_module_num,
+ fail_module_num,
+ )
+
+ if fail_module_num > 0:
+ print('[Fail] %s' % reminder_statement)
+ self.output_symbol_crc_difference_report(module_different_symbol_crc_mapping)
+ return False
+
+ print('[Success] %s' % reminder_statement)
+ return True
+
+ def output_symbol_crc_difference_report(self, module_different_symbol_crc_mapping: dict):
+ """
+ Format the output for symbol crc difference report.
+ The output is as follows:
+
+ Failed modules are as follows:
+ No. Module Difference
+ 1 upatch ipv6_chk_custom_prefix : 0x0c994af2 != 0x0c994af3
+ pcmcia_reset_card : 0xe9bed965 != null
+ 2 crct10dif_pclmul crypto_unregister_shash: 0x60f5b0b7 != 0x0c994af3
+ __fentry__ : 0xbdfb6dbb != null
+ """
+ print('Failed modules are as follows:')
+
+ title = ['No.', 'Module', 'Difference']
+ # column width
+ sequence_width = len(title[0])
+ module_width = len(title[1])
+ symbol_width = crc_info_width = 0
+
+ for seq, module_name in enumerate(module_different_symbol_crc_mapping):
+ # the sequence starts from 1
+ seq = seq + 1
+ sequence_width = max(sequence_width, len(str(seq)))
+ different_symbol_crc_mapping = module_different_symbol_crc_mapping[module_name]
+ module_width = max(module_width, len(module_name))
+ for symbol, crc_list in different_symbol_crc_mapping.items():
+ symbol_width = max(symbol_width, len(symbol))
+ crc_info = "%s != %s" % (crc_list[0], crc_list[1])
+ crc_info_width = max(crc_info_width, len(crc_info))
+
+ # print title
+ print('%-*s %-*s %s' % (sequence_width, title[0], module_width, title[1], title[2]))
+
+ for seq, module_name in enumerate(module_different_symbol_crc_mapping):
+ seq = seq + 1
+ print('%-*s %-*s' % (sequence_width, seq, module_width, module_name), end='')
+ different_symbol_crc_mapping = module_different_symbol_crc_mapping[module_name]
+ is_first_symbol = True
+ for symbol, crc_list in different_symbol_crc_mapping.items():
+ crc_info = "%s != %s" % (crc_list[0], crc_list[1])
+ if is_first_symbol:
+ print(' %-*s: %s' % (symbol_width, symbol, crc_info), end='')
+ is_first_symbol = False
+ else:
+ print(
+ ' %-*s %-*s: %s' % (sequence_width + module_width, "", symbol_width, symbol, crc_info), end=''
+ )
+ print('')
+
+ def compare_actual_and_target_symvers_symbol_crc_mapping(
+ self, module_actual_symbol_crc_mapping: dict, target_symvers_symbol_crc_mapping: dict
+ ) -> dict:
+ """
+ Compare the actual symbol crc mapping with the target symvers symbol crc mapping.
+
+ Args:
+ module_actual_symbol_crc_mapping(dict): module actual symbol crc mapping
+ e.g.
+ {
+ 'upatch': {
+ 'ipv6_chk_custom_prefix': '0x0c994af3',
+ 'pcmcia_reset_card': '0xe9bed965',
+ }
+ }
+
+ target_symvers_symbol_crc_mapping(dict): target symvers symbol crc mapping
+ e.g.
+ {
+ 'ipv6_chk_custom_prefix': '0x0c994af2',
+ 'pcmcia_reset_card': '0xe9bed965',
+ }
+
+ Returns:
+ dict: module different symbol crc mapping
+ e.g.
+ {
+ 'upatch': {
+ 'ipv6_chk_custom_prefix': ['0x0c994af3', '0x0c994af2'].
+ }
+ }
+ """
+ module_different_symbol_crc_mapping = dict()
+ for module_name, actual_symbol_crc_mapping in module_actual_symbol_crc_mapping.items():
+ different_symbol_crc_mapping = dict()
+ for actual_symbol, actual_crc in actual_symbol_crc_mapping.items():
+ if actual_symbol not in target_symvers_symbol_crc_mapping:
+ continue
+ elif target_symvers_symbol_crc_mapping[actual_symbol] != actual_symbol_crc_mapping[actual_symbol]:
+ different_symbol_crc_mapping[actual_symbol] = [
+ actual_crc,
+ target_symvers_symbol_crc_mapping[actual_symbol],
+ ]
+ if not different_symbol_crc_mapping:
+ continue
+ module_different_symbol_crc_mapping[module_name] = different_symbol_crc_mapping
+ return module_different_symbol_crc_mapping
+
+ def get_module_actual_symbol_crc_mapping(self) -> dict:
+ """
+ Get the module actual symbol crc mapping of the driver modules currently being loaded in the system.
+
+ Returns:
+ dict: module actual symbol crc mapping
+ e.g.
+ {
+ 'upatch': {
+ 'ipv6_chk_custom_prefix': '0x0c994af3',
+ 'pcmcia_reset_card': '0xe9bed965',
+ }
+ }
+ """
+ module_actual_symbol_crc_mapping = dict()
+ lsmod_cmd = ["lsmod"]
+ # 'lsmod' shows all modules loaded in the system
+ # e.g.
+ # [root@openEuler ~]# lsmod
+ # Module Size Used by
+ # upatch 53248 0
+ # nft_fib_inet 16384 1
+ # nft_fib_ipv4 16384 1 nft_fib_inet
+ list_output, return_code = cmd_output(lsmod_cmd)
+ if return_code != SUCCEED:
+ return module_actual_symbol_crc_mapping
+
+ content = list_output.split('\n')
+ for line in content[1:]:
+ if not line:
+ continue
+ module_name = line.split()[0]
+ modinfo_cmd = ['modinfo', module_name, '-n']
+ # 'modinfo module_name -n' shows module path information
+ # e.g.
+ # [root@openEuler ~]# modinfo upatch -n
+ # /lib/modules/5.10.0-153.12.0.92.oe2203sp2.x86_64/weak-updates/syscare/upatch.ko
+ module_path_output, return_code = cmd_output(modinfo_cmd)
+ if return_code != SUCCEED:
+ continue
+
+ module_path = module_path_output.split('\n')[0]
+ actual_symbol_crc_mapping, return_code = self.get_actual_symbol_crc_mapping(module_path)
+ if return_code != SUCCEED:
+ continue
+
+ module_actual_symbol_crc_mapping[module_name] = actual_symbol_crc_mapping
+ return module_actual_symbol_crc_mapping
+
+ def get_actual_symbol_crc_mapping(self, module_path: str) -> (dict, int):
+ """
+ Get actual symbol crc mapping for specific module.
+
+ Args:
+ module_path(str): loaded module path
+
+ Returns:
+ dict, bool: actual symbol crc mapping, return code
+ """
+ actual_symbol_crc_mapping = dict()
+ modprobe_cmd = ['modprobe', '--dump', module_path]
+ # 'modprobe --dump module_path' shows module related kabi information
+ # e.g.
+ # [root@openEuler ~]# modprobe --dump \
+ # /lib/modules/5.10.0-153.12.0.92.oe2203sp2.x86_64/weak-updates/syscare/upatch.ko
+ # 0xe32130cf module_layout
+ # 0x9c4befaf kmalloc_caches
+ # 0xeb233a45 __kmalloc
+ # 0xd6ee688f vmalloc
+ # 0x349cba85 strchr
+ # 0x754d539c strlen
+ crc_symbol_output_lines, return_code = cmd_output(modprobe_cmd)
+ if return_code != SUCCEED:
+ return actual_symbol_crc_mapping, return_code
+
+ crc_symbol_output = crc_symbol_output_lines.split('\n')
+ for crc_symbol_line in crc_symbol_output:
+ if not crc_symbol_line:
+ continue
+ crc_symbol_line = crc_symbol_line.split()
+ crc, symbol = crc_symbol_line[0], crc_symbol_line[1]
+ actual_symbol_crc_mapping[symbol] = crc
+ return actual_symbol_crc_mapping, return_code
+
+ def get_target_symvers_symbol_crc_mapping(self, symvers_file: str) -> (dict, int):
+ """
+ Get target symbol crc mapping from symvers file of kernel rpm package. The symvers file content is
+ as follows(e.g.):
+
+ 0x0c994af3 ipv6_chk_custom_prefix vmlinux EXPORT_SYMBOL
+ 0xe9bed965 pcmcia_reset_card vmlinux EXPORT_SYMBOL
+ 0x55417264 unregister_vt_notifier vmlinux EXPORT_SYMBOL_GPL
+ 0x8c8905c0 set_anon_super vmlinux EXPORT_SYMBOL
+ 0x3ba051a9 __cleancache_invalidate_page vmlinux EXPORT_SYMBOL
+
+ the first column is crc(Cyclic Redundancy Check), and the second column is symbol.
+
+ Args:
+ symvers_file(str): symvers file path
+
+ Returns:
+ dict, int: target symvers symbol crc mapping, return_code
+ e.g.
+ {
+ 'ipv6_chk_custom_prefix': '0x0c994af3',
+ 'pcmcia_reset_card': '0xe9bed965',
+ },
+ SUCCEED
+ """
+ symvers_symbol_crc_mapping = dict()
+ try:
+ content = gzip.open(symvers_file, 'rb')
+ except FileNotFoundError as e:
+ print("error: ", e)
+ return symvers_symbol_crc_mapping, FAIL
+
+ for line in content.readlines():
+ line = line.decode()
+ line = line.split()
+ crc, symbol = line[0], line[1]
+ symvers_symbol_crc_mapping[symbol] = crc
+ content.close()
+ return symvers_symbol_crc_mapping, SUCCEED
+
+ def upgrade(self):
+ """
+ Use UpgradeCommand to process the upgrade operation.
+ """
+ upgrade = UpgradeCommand(self.cli)
+ upgrade.upgrade_minimal = self.upgrade_minimal
+ upgrade.opts = self.opts
+ upgrade.opts.filenames = self.opts.filenames
+ upgrade.opts.pkg_specs = self.opts.pkg_specs
+ upgrade.opts.grp_specs = self.opts.grp_specs
+
+ upgrade.upgrade_minimal = None
+ upgrade.all_security = None
+ upgrade.skipped_grp_specs = None
+
+ upgrade.run()
--
2.27.0

View File

@ -1,81 +0,0 @@
From 831aca01a20fcd67b1d6ff604a0334aaa419efd5 Mon Sep 17 00:00:00 2001
From: gongzt <gong_zhengtang@163.com>
Date: Sat, 11 Nov 2023 17:47:25 +0800
Subject: Modify the regular expression of kernel filter
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ceres/manages/vulnerability_manage.py | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/ceres/manages/vulnerability_manage.py b/ceres/manages/vulnerability_manage.py
index c41a7fa..39f475d 100644
--- a/ceres/manages/vulnerability_manage.py
+++ b/ceres/manages/vulnerability_manage.py
@@ -166,7 +166,7 @@ class VulnerabilityManage:
return rpm_info
for line in stdout.splitlines():
- rpm_name, new_rpm_info = line.split(":",1)
+ rpm_name, new_rpm_info = line.split(":", 1)
old_rpm_info = rpm_info.get(rpm_name, "")
rpm_info[rpm_name] = new_rpm_info if new_rpm_info > old_rpm_info else old_rpm_info
LOGGER.debug("query installed rpm package info succeed!")
@@ -200,7 +200,7 @@ class VulnerabilityManage:
# ("kernel", "x86_64.", "5.10.0-60.105.0.132.oe2203"),
# ("kernel-debuginfo", "x86_64", "5.10.0-60.105.0.132.oe2203")
# ]
- rpm_info = re.findall("^(kernel\S*)\.([a-z468_]+)\s+(\S+)", stdout, re.MULTILINE)
+ rpm_info = re.findall("^(kernel)\.([a-z468_]+)\s+(\S+)", stdout, re.MULTILINE)
if not rpm_info:
return result
@@ -243,7 +243,7 @@ class VulnerabilityManage:
# ("CVE-2021-43976", "Important/Sec.", "kernel-4.19.90-2201.1.0.0132.oe1.x86_64"),
# ("CVE-2021-0941", "Important/Sec.", "kernel-4.19.90-2201.1.0.0132.oe1.x86_64")
# ]
- all_cve_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(kernel\S+)", stdout)
+ all_cve_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(kernel-\d\S+)", stdout)
if not all_cve_info:
return unfixed_cves
@@ -306,7 +306,7 @@ class VulnerabilityManage:
# ("CVE-2023-1513", "Important/Sec.", "kernel-4.19.90-2304.1.0.0196.oe1.x86_64", "patch-kernel-4.19.90-2112.."),
# ("CVE-2021-xxxx", "Important/Sec.", "-", "patch-redis-6.2.5-1-SGL_CVE_2023_1111_CVE_2023_1112-1-1.x86_64")
# ]
- all_cve_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(kernel\S+|-)\s+(patch-kernel\S+|-)", stdout)
+ all_cve_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(kernel-\d\S+|-)\s+(patch-kernel-\d\S+|-)", stdout)
if not all_cve_info:
return cve_info_list
@@ -368,7 +368,7 @@ class VulnerabilityManage:
# ("CVE-2021-43976","Important/Sec.", "kernel-4.19.90-2201.1.0.0132.oe1.x86_64"),
# ("CVE-2021-0941","Important/Sec.", "kernel-4.19.90-2201.1.0.0132.oe1.x86_64")
# ]
- fixed_cves_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(kernel\S+)", stdout)
+ fixed_cves_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(kernel-\d\S+)", stdout)
if not fixed_cves_info:
return fixed_cves
@@ -407,7 +407,7 @@ class VulnerabilityManage:
# ("CVE-2021-xxxx", "Important/Sec.", "-", "patch-redis-6.2.5-1-SGL_CVE_2023_1111_CVE_2023_1112-1-1.x86_64")
# ]
hotpatch_status = self._query_applied_hotpatch_status()
- all_cve_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(kernel\S+|-)\s+(patch-kernel\S+|-)", stdout)
+ all_cve_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(kernel-\d\S+|-)\s+(patch-kernel-\d\S+|-)", stdout)
cve_info_fixed_by_coldpatch, cve_info_fixed_by_hotpatch, hotpatch_dic = [], [], defaultdict(str)
for cve_id, _, coldpatch, hotpatch in all_cve_info:
@@ -472,7 +472,7 @@ class VulnerabilityManage:
# ("CVE-2023-1112", "redis-6.2.5-1/SGL_CVE_2023_1111_CVE_2023_1112-1-1/redis-server", "NOT-APPLIED"),
# ("CVE-2023-1111", "redis-6.2.5-1/ACC-1-1/redis-benchmark", "ACTIVED")
# ]
- applied_hotpatch_info_list = re.findall(r"(CVE-\d{4}-\d+)\s+(kernel[\w\-/.]+)\s+([A-W]+)", stdout)
+ applied_hotpatch_info_list = re.findall(r"(CVE-\d{4}-\d+)\s+(kernel-\d[\w\-/.]+)\s+([A-W]+)", stdout)
if not applied_hotpatch_info_list:
return result
--
Gitee

View File

@ -0,0 +1,167 @@
From 2c3dcc5bb5de4d3f83902bb8cb7f0fe1fa9a55b9 Mon Sep 17 00:00:00 2001
From: wang-guangge <wangguangge@huawei.com>
Date: Tue, 19 Dec 2023 21:03:48 +0800
Subject: [PATCH] support restore default boot kernel if kabi check failed
---
hotpatch/hotupgrade.py | 19 ++++++++-----
hotpatch/upgrade_en.py | 61 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 7 deletions(-)
diff --git a/hotpatch/hotupgrade.py b/hotpatch/hotupgrade.py
index 37497cf..4e1ea96 100644
--- a/hotpatch/hotupgrade.py
+++ b/hotpatch/hotupgrade.py
@@ -43,6 +43,7 @@ class HotupgradeCommand(dnf.cli.Command):
is_need_accept_kernel_hp = False
is_kernel_coldpatch_installed = False
kernel_coldpatch = ''
+ previous_boot_kernel = None
@staticmethod
def set_argparser(parser):
@@ -80,6 +81,9 @@ class HotupgradeCommand(dnf.cli.Command):
commands._checkEnabledRepo(self.base)
def run(self):
+ self.upgrade_en = UpgradeEnhanceCommand(self.cli)
+ self.previous_boot_kernel = self.upgrade_en.get_default_boot_kernel()
+
if self.opts.pkg_specs:
self.hp_list = self.opts.pkg_specs
elif self.opts.cves or self.opts.advisory:
@@ -181,20 +185,21 @@ class HotupgradeCommand(dnf.cli.Command):
Returns:
bool: if hotupgrade task success
"""
- upgrade_en = UpgradeEnhanceCommand(self.cli)
-
is_task_success = True
if self.is_kernel_coldpatch_installed:
if not is_all_kernel_hp_actived:
logger.info(_('Gonna remove %s due to some kernel hotpatch activation failed.'), self.kernel_coldpatch)
- upgrade_en.remove_rpm(str(self.kernel_coldpatch))
+ self.upgrade_en.rebuild_rpm_db()
+ self.upgrade_en.remove_rpm(str(self.kernel_coldpatch))
+ self.upgrade_en.restore_default_boot_kernel(self.previous_boot_kernel)
self.is_need_accept_kernel_hp = False
# process kabi check
- elif not upgrade_en.kabi_check(str(self.kernel_coldpatch)) and not self.opts.force:
+ elif not self.upgrade_en.kabi_check(str(self.kernel_coldpatch)) and not self.opts.force:
logger.info(_('Gonna remove %s due to Kabi check failed.'), self.kernel_coldpatch)
# rebuild rpm database for processing kernel rpm remove operation
- upgrade_en.rebuild_rpm_db()
- upgrade_en.remove_rpm(str(self.kernel_coldpatch))
+ self.upgrade_en.rebuild_rpm_db()
+ self.upgrade_en.remove_rpm(str(self.kernel_coldpatch))
+ self.upgrade_en.restore_default_boot_kernel(self.previous_boot_kernel)
self.is_need_accept_kernel_hp = True
if target_remove_hp:
@@ -203,7 +208,7 @@ class HotupgradeCommand(dnf.cli.Command):
# it indicates that the hotupgrade task failed
is_task_success &= False
for hotpatch in target_remove_hp:
- upgrade_en.remove_rpm(hotpatch)
+ self.upgrade_en.remove_rpm(hotpatch)
return is_task_success
def _apply_hp(self, hp_full_name):
diff --git a/hotpatch/upgrade_en.py b/hotpatch/upgrade_en.py
index 94ba4da..0bd78cc 100644
--- a/hotpatch/upgrade_en.py
+++ b/hotpatch/upgrade_en.py
@@ -12,6 +12,7 @@
# ******************************************************************************/
import gzip
import subprocess
+from typing import Optional
import dnf
from dnf.cli import commands
@@ -36,6 +37,7 @@ def cmd_output(cmd):
@dnf.plugin.register_command
class UpgradeEnhanceCommand(dnf.cli.Command):
SYMVERS_FILE = "/boot/symvers-%s.gz"
+ previous_boot_kernel = None
aliases = ['upgrade-en']
summary = _(
@@ -80,8 +82,65 @@ class UpgradeEnhanceCommand(dnf.cli.Command):
self.skipped_grp_specs = None
def run(self):
+ # if kernel kabi check failed, need change back to the default boot kernel version
+ self.previous_boot_kernel = self.get_default_boot_kernel()
self.upgrade()
+ @staticmethod
+ def get_default_boot_kernel() -> Optional[str]:
+ """
+ Get default boot kernel version.
+
+ Returns:
+ str: default boot kernel
+ """
+ cmd = ["grubby", "--default-kernel"]
+ # 'grubby --default-kernel' shows boot default kernel version in the system
+ # e.g.
+ # [root@openEuler ~]# grubby --default-kernel
+ # /boot/vmlinuz-4.19.90-2112.8.0.0131.oe1.x86_64
+ output, return_code = cmd_output(cmd)
+ default_boot_kernel = output.split('\n')[0]
+ if return_code != SUCCEED:
+ return None
+ return default_boot_kernel
+
+ @staticmethod
+ def restore_default_boot_kernel(target_boot_kernel: str):
+ """
+ Restore default boot kernel version.
+
+ Args:
+ target_boot_kernel(str): target boot kernel
+ """
+ # 'grubby --set-default=/boot/vmlinuz-4.19.90-2112.8.0.0131.oe1.x86_64' can set default boot kernel version
+ # to kernel-4.19.90-2112.8.0.0131.oe1.x86_64
+ if not target_boot_kernel:
+ print("Get default boot kernel before upgrade failed.")
+ return
+
+ cmd = ["grubby", "--set-default=%s" % target_boot_kernel]
+ try:
+ # e.g. 4.19.90-2112.8.0.0131.oe1.x86_64
+ target_boot_kernel_vere = target_boot_kernel.split('-', 1)[1]
+ target_boot_kernel_nevra = "kernel-%s" % target_boot_kernel_vere
+ except IndexError as e:
+ print(
+ "Parse target boot kernel failed. Please check if target boot kernel path is correct: %s."
+ % target_boot_kernel,
+ "\nRestore the default boot kernel failed. Please manually check the default boot kernel to prevent unexpected kernel switching after reboot.",
+ )
+ return
+
+ output, return_code = cmd_output(cmd)
+ if return_code != SUCCEED:
+ print(
+ "Restore the default boot kernel failed: %s. Please manually check the default boot kernel to prevent unexpected kernel switching after reboot."
+ % target_boot_kernel_nevra
+ )
+ return
+ print("Restore the default boot kernel succeed: %s." % target_boot_kernel_nevra)
+
def run_transaction(self):
"""
Process kabi check for kernel rpm package installed this time. If the kernel rpm pakcgae fails kabi check,
@@ -100,6 +159,8 @@ class UpgradeEnhanceCommand(dnf.cli.Command):
# when processing remove operation, do not achieve the expected result of installing related rpm,
# it indicates that the upgrade task failed
self.remove_rpm(kernel_pkg)
+ # change back to the default boot kernel version before upgrade
+ self.restore_default_boot_kernel(self.previous_boot_kernel)
exit(1)
def remove_rpm(self, pkg: str):
--
2.27.0

View File

@ -1,27 +0,0 @@
From ccbd7a6dea68303fb7ec6f777f0e6b8d9e6c7773 Mon Sep 17 00:00:00 2001
From: wang-guangge <wangguangge@huawei.com>
Date: Wed, 15 Nov 2023 10:35:42 +0800
Subject: [PATCH] fix bug in test_hotpatch.py
---
hotpatch/test_hotpatch.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hotpatch/test_hotpatch.py b/hotpatch/test_hotpatch.py
index f46faed..e903d55 100644
--- a/hotpatch/test_hotpatch.py
+++ b/hotpatch/test_hotpatch.py
@@ -13,8 +13,8 @@
import unittest
from unittest import mock
-from .hotpatch import HotpatchCommand
-from .syscare import SUCCEED, FAIL
+from .hotpatch_ops import HotpatchCommand
+from .syscare import FAIL, SUCCEED
class HotpatchTestCase(unittest.TestCase):
--
2.27.0

View File

@ -0,0 +1,152 @@
From 88f2784a4673edb9ff0a185ea43beccb5108ece0 Mon Sep 17 00:00:00 2001
From: wang-guangge <wangguangge@huawei.com>
Date: Fri, 22 Dec 2023 18:44:27 +0800
Subject: [PATCH] improve rollback_manage.py
---
ceres/manages/rollback_manage.py | 73 ++++++++++++++++++++++++++------
1 file changed, 61 insertions(+), 12 deletions(-)
diff --git a/ceres/manages/rollback_manage.py b/ceres/manages/rollback_manage.py
index 0f30d29..160a74c 100644
--- a/ceres/manages/rollback_manage.py
+++ b/ceres/manages/rollback_manage.py
@@ -237,19 +237,67 @@ class RollbackManage:
log.append(result_log)
if result_code != TaskExecuteRes.SUCCEED:
return TaskExecuteRes.FAIL, os.linesep.join(log)
+
+ result_code, result_log = self._remove_kernel_rpm(installed_rpm)
+ if result_log:
+ log.append(result_log)
+ if result_code != TaskExecuteRes.SUCCEED:
+ return TaskExecuteRes.FAIL, os.linesep.join(log)
result_code, result_log = self._change_boot_kernel_version(target_rpm)
if result_log:
log.append(result_log)
if result_code != TaskExecuteRes.SUCCEED:
return TaskExecuteRes.FAIL, os.linesep.join(log)
-
+
return TaskExecuteRes.SUCCEED, os.linesep.join(log)
-
+
+ def _remove_kernel_rpm(self, installed_rpm: str) -> Tuple[str, str]:
+ """
+ Remove the kernel rpm if the installed kernel rpm is not in use.
+
+ Args:
+ installed_rpm(str): the installed kernel in executed fix task
+
+ Returns:
+ Tuple[str, str]: a tuple containing two elements (remove result, log)
+ """
+ code, stdout, stderr = execute_shell_command(f"rpm -qa | grep {installed_rpm}")
+ # 'rpm -qa' shows installed rpm
+ # e.g.
+ # [root@openEuler ~]# rpm -qa | grep kernel-4.19.90-2112.8.0.0131.oe1.x86_64
+ # kernel-4.19.90-2112.8.0.0131.oe1.x86_64
+ if code != CommandExitCode.SUCCEED or installed_rpm not in stdout:
+ tmp_log = f"The {installed_rpm} is not installed. Please check the input parameter."
+ LOGGER.error(tmp_log)
+ return TaskExecuteRes.FAIL, tmp_log
+
+ code, current_evra, stderr = execute_shell_command(f"uname -r")
+ # 'uname -r' show the kernel version-release.arch of the current system
+ # e.g.
+ # [root@openEuler ~]# uname -r
+ # 5.10.0-136.12.0.86.oe2203sp1.x86_64
+ if code != CommandExitCode.SUCCEED:
+ LOGGER.error(stderr)
+ return TaskExecuteRes.FAIL, current_evra + stderr
+
+ # version-release.arch
+ installed_evra = installed_rpm.split("-", 1)[1]
+
+ if installed_evra == current_evra:
+ return TaskExecuteRes.SUCCEED, f"Preserve the {installed_rpm} due to it is in use."
+
+ code, stdout, stderr = execute_shell_command(f"dnf remove {installed_rpm} -y")
+ if code != CommandExitCode.SUCCEED:
+ LOGGER.error(stderr)
+ return TaskExecuteRes.FAIL, stdout + stderr
+
+ return TaskExecuteRes.SUCCEED, stdout
+
def _check_boot_kernel_version(self, installed_rpm: str) -> Tuple[str, str]:
"""
Check if the boot kernel version is consistent with the installed kernel version. If not, it indicates
- that the executed fix task has been tampered.
+ that the environment after executed fix task has been tampered.
Args:
installed_rpm(str): the installed rpm in executed fix task
@@ -270,8 +318,8 @@ class RollbackManage:
evra = installed_rpm.split("-", 1)[1]
if evra not in stdout:
tmp_log = (
- "The grubby default kernel version is not consistent with installed kernel version. "
- "The executed fix task has been tampered."
+ f"The default boot kernel version is not consistent with {installed_rpm}. "
+ "The environment after executed fix task has been tampered."
)
LOGGER.error(tmp_log)
return TaskExecuteRes.FAIL, tmp_log
@@ -281,7 +329,7 @@ class RollbackManage:
def _check_current_kernel_version(self, installed_rpm: str, target_rpm: str) -> Tuple[str, str]:
"""
Check if the current kernel version is consistent with the installed kernel version or target kernel
- version. If not, it indicates that the executed fix task has been tampered.
+ version. If not, it indicates that the environment after executed fix task has been tampered.
Args:
installed_rpm(str): the installed rpm in executed fix task
@@ -304,8 +352,8 @@ class RollbackManage:
if installed_evra != current_evra and target_evra != current_evra:
tmp_log = (
- "The current kernel version is not consistent with installed kernel version or target kernel version. "
- "The executed fix task has been tampered."
+ f"The current kernel version is neither {installed_rpm} nor {target_rpm}. "
+ "The environment after executed fix task has been tampered."
)
LOGGER.error(tmp_log)
return TaskExecuteRes.FAIL, tmp_log
@@ -314,7 +362,8 @@ class RollbackManage:
def _check_if_target_rpm_installed(self, target_rpm: str) -> Tuple[str, str]:
"""
- Check if the target kernel is installed. If not, it indicates that the executed fix task has been tampered.
+ Check if the target kernel is installed. If not, it indicates that the environment after executed fix
+ task has been tampered.
Args:
target_rpm(str): the target rpm for rollback task
@@ -328,7 +377,7 @@ class RollbackManage:
# [root@openEuler ~]# rpm -qa | grep kernel-4.19.90-2112.8.0.0131.oe1.x86_64
# kernel-4.19.90-2112.8.0.0131.oe1.x86_64
if code != CommandExitCode.SUCCEED or target_rpm not in stdout:
- tmp_log = "The target kernel of rollback task is not installed. The executed fix task has been tampered."
+ tmp_log = "The target kernel of rollback task is not installed. The environment after executed fix task has been tampered."
LOGGER.error(tmp_log)
return TaskExecuteRes.FAIL, tmp_log
@@ -336,7 +385,7 @@ class RollbackManage:
def _change_boot_kernel_version(self, target_rpm: str) -> Tuple[str, str]:
"""
- Change the grubby default kernel version to target kernel version.
+ Change the default boot kernel version to target kernel version.
Args:
target_rpm(str): the target rpm for rollback task
@@ -358,4 +407,4 @@ class RollbackManage:
LOGGER.error(stderr)
return TaskExecuteRes.FAIL, stdout + stderr
- return TaskExecuteRes.SUCCEED, f"Change boot kernel version to {target_rpm} successfully."
+ return TaskExecuteRes.SUCCEED, f"Change default boot kernel version to {target_rpm} successfully."
--
2.27.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,486 @@
From d5c2db0af6d62a85c35c6cfe3e7af55edddf3b91 Mon Sep 17 00:00:00 2001
From: rabbitali <wenxin32@foxmail.com>
Date: Sun, 4 Feb 2024 00:39:26 +0800
Subject: [PATCH 1/1] fix cve-2021-33633
---
ceres/function/check.py | 4 +--
ceres/function/util.py | 11 ++++----
ceres/manages/collect_manage.py | 18 ++++++-------
ceres/manages/list_file_manage.py | 2 +-
ceres/manages/plugin_manage.py | 8 +++---
ceres/manages/resource_manage.py | 4 +--
ceres/manages/rollback_manage.py | 16 +++++------
ceres/manages/vulnerability_manage.py | 38 +++++++++++++--------------
8 files changed, 50 insertions(+), 51 deletions(-)
diff --git a/ceres/function/check.py b/ceres/function/check.py
index 20978f5..18b9561 100644
--- a/ceres/function/check.py
+++ b/ceres/function/check.py
@@ -61,14 +61,14 @@ class PreCheck(object):
"""
# Example of command execution result::
# /boot/vmlinuz-5.10.0-60.18.0.50.oe2203.x86_64
- code, boot_kernel_version, stderr = execute_shell_command("grubby --default-kernel")
+ code, boot_kernel_version, stderr = execute_shell_command(["grubby --default-kernel"])
if code != CommandExitCode.SUCCEED:
LOGGER.error(stderr)
return False, "Query boot kernel info failed!"
# Example of command execution result::
# 5.10.0-60.18.0.50.oe2203.x86_64
- code, current_kernel_version, stderr = execute_shell_command("uname -r")
+ code, current_kernel_version, stderr = execute_shell_command(["uname -r"])
if code != CommandExitCode.SUCCEED:
LOGGER.error(stderr)
return False, "Query current kernel info failed!"
diff --git a/ceres/function/util.py b/ceres/function/util.py
index 433db09..1d3d9e3 100644
--- a/ceres/function/util.py
+++ b/ceres/function/util.py
@@ -15,7 +15,7 @@ import json
import os
import shlex
import subprocess
-from typing import Any, Tuple, NoReturn
+from typing import Any, Tuple, NoReturn, Sequence
from libconf import load, ConfigParseError, AttrDict
from jsonschema import validate, ValidationError
@@ -63,12 +63,12 @@ def validate_data(data: Any, schema: dict) -> bool:
return False
-def execute_shell_command(command: str, **kwargs) -> Tuple[int, str, str]:
+def execute_shell_command(commands: Sequence[str], **kwargs) -> Tuple[int, str, str]:
"""
execute shell commands
Args:
- command(str): shell command which needs to execute
+ command(Sequence[str]): Multiple shell commands that need to be executed continuously
**kwargs: keyword arguments, it is used to create Popen object.supported options: env, cwd, bufsize, group and
so on. you can see more options information in annotation of Popen obejct.
@@ -77,11 +77,10 @@ def execute_shell_command(command: str, **kwargs) -> Tuple[int, str, str]:
a tuple containing three elements (return code, standard output, standard error).
Example usage:
- >>> return_code, stdout, stderr = execute_shell_command("ls -al|wc -l", **{"env": {"LANG": "en_US.utf-8"}})
+ >>> return_code, stdout, stderr = execute_shell_command(["ls -al", "wc -l"], **{"env": {"LANG": "en_US.utf-8"}})
>>> print(return_code, stdout, stderr)
0, 42, ""
"""
- commands = command.split('|')
process = None
stdout_data = ""
stderr_data = ""
@@ -153,7 +152,7 @@ def plugin_status_judge(plugin_name: str) -> str:
if service_name is None:
LOGGER.warning(f"Fail to get service name about {plugin_name}")
return ""
- return_code, stdout, _ = execute_shell_command(f"systemctl status {service_name}|grep Active")
+ return_code, stdout, _ = execute_shell_command([f"systemctl status {service_name}", "grep Active"])
if return_code == CommandExitCode.SUCCEED:
return stdout
diff --git a/ceres/manages/collect_manage.py b/ceres/manages/collect_manage.py
index e702120..b2ba350 100644
--- a/ceres/manages/collect_manage.py
+++ b/ceres/manages/collect_manage.py
@@ -104,7 +104,7 @@ class Collect:
Returns:
str: e.g openEuler 21.09
"""
- _, stdout, _ = execute_shell_command("cat /etc/os-release")
+ _, stdout, _ = execute_shell_command(["cat /etc/os-release"])
res = re.search('(?=PRETTY_NAME=).+', stdout)
if res:
@@ -140,7 +140,7 @@ class Collect:
Returns:
str
"""
- _, stdout, _ = execute_shell_command("dmidecode -t bios")
+ _, stdout, _ = execute_shell_command(["dmidecode -t bios"])
res = re.search('(?=Version:).+', stdout)
if res:
@@ -156,7 +156,7 @@ class Collect:
Returns:
str
"""
- code, stdout, stderr = execute_shell_command("uname -r")
+ code, stdout, stderr = execute_shell_command(["uname -r"])
if code != CommandExitCode.SUCCEED:
LOGGER.warning('Failed to get current kernel version, please check uname command and try again')
@@ -181,7 +181,7 @@ class Collect:
"l3_cache": string
}
"""
- _, stdout, _ = execute_shell_command("lscpu", **{"env": {"LANG": "en_US.utf-8"}})
+ _, stdout, _ = execute_shell_command(["lscpu"], **{"env": {"LANG": "en_US.utf-8"}})
info_list = re.findall('.+:.+', stdout)
@@ -214,7 +214,7 @@ class Collect:
Returns:
str: memory size
"""
- _, stdout, _ = execute_shell_command("lsmem")
+ _, stdout, _ = execute_shell_command(["lsmem"])
res = re.search("(?=Total online memory:).+", stdout)
if res:
@@ -245,7 +245,7 @@ class Collect:
"""
res = {'size': self.__get_total_online_memory() or None, "total": None, "info": []}
- code, memory_data, _ = execute_shell_command("dmidecode -t memory")
+ code, memory_data, _ = execute_shell_command(["dmidecode -t memory"])
# dmidecode -t memory
# e.g
@@ -306,7 +306,7 @@ class Collect:
}
]
"""
- code, stdout, _ = execute_shell_command("lshw -xml -c disk")
+ code, stdout, _ = execute_shell_command(["lshw -xml -c disk"])
if code != CommandExitCode.SUCCEED:
LOGGER.error(stdout)
return []
@@ -384,7 +384,7 @@ class Collect:
Returns:
uuid(str)
"""
- code, stdout, _ = execute_shell_command("dmidecode|grep UUID")
+ code, stdout, _ = execute_shell_command(["dmidecode", "grep UUID"])
if code == CommandExitCode.SUCCEED:
return stdout.replace("-", "").split(':')[1].strip()
return ""
@@ -420,7 +420,7 @@ class Collect:
}]
"""
- code, source_name_info, _ = execute_shell_command("rpm -qi kernel|grep .src.rpm")
+ code, source_name_info, _ = execute_shell_command(["rpm -qi kernel", "grep .src.rpm"])
if code != CommandExitCode.SUCCEED:
LOGGER.error("Failed to query installed packages.")
return []
diff --git a/ceres/manages/list_file_manage.py b/ceres/manages/list_file_manage.py
index 3d7fd21..dab55e6 100644
--- a/ceres/manages/list_file_manage.py
+++ b/ceres/manages/list_file_manage.py
@@ -40,7 +40,7 @@ class ListFileManage:
"""
file_list_res = []
try:
- command = "ls -l " + directory_path + " | awk '{print $9}'"
+ command = [f"ls -l {directory_path}", "awk '{print $9}'"]
_, stdout, _ = execute_shell_command(command)
file_list = stdout.split("\n")
for file in file_list:
diff --git a/ceres/manages/plugin_manage.py b/ceres/manages/plugin_manage.py
index ed7b2ab..fb06220 100644
--- a/ceres/manages/plugin_manage.py
+++ b/ceres/manages/plugin_manage.py
@@ -52,7 +52,7 @@ class Plugin:
if "running" in plugin_status:
return SUCCESS
- code, _, _ = execute_shell_command(f"systemctl start {self.rpm_name}")
+ code, _, _ = execute_shell_command([f"systemctl start {self.rpm_name}"])
if code != CommandExitCode.SUCCEED:
return FAIL
return SUCCESS
@@ -68,7 +68,7 @@ class Plugin:
if "inactive" in plugin_status:
return SUCCESS
- code, _, _ = execute_shell_command(f"systemctl stop {self.rpm_name}")
+ code, _, _ = execute_shell_command([f"systemctl stop {self.rpm_name}"])
if code != CommandExitCode.SUCCEED:
return FAIL
return SUCCESS
@@ -100,7 +100,7 @@ class Plugin:
str: dead or running
"""
- code, stdout, _ = execute_shell_command(f"systemctl status {self.rpm_name}|grep Active")
+ code, stdout, _ = execute_shell_command([f"systemctl status {self.rpm_name}", "grep Active"])
if code == CommandExitCode.SUCCEED:
return re.search(r':.+\(', stdout).group()[1:-1].strip()
LOGGER.error(f'Failed to get service {self.rpm_name} status!')
@@ -114,7 +114,7 @@ class Plugin:
Returns:
The str type of main process id
"""
- code, main_pid_info, _ = execute_shell_command(f"systemctl status {rpm_name}|grep Main")
+ code, main_pid_info, _ = execute_shell_command([f"systemctl status {rpm_name}", "grep Main"])
if code == CommandExitCode.SUCCEED:
return re.search("[0-9]+[0-9]", main_pid_info).group()
LOGGER.error(f"Failed to get {rpm_name} pid")
diff --git a/ceres/manages/resource_manage.py b/ceres/manages/resource_manage.py
index 5766744..e9c6256 100644
--- a/ceres/manages/resource_manage.py
+++ b/ceres/manages/resource_manage.py
@@ -32,7 +32,7 @@ class Resource:
Returns:
str:The memory value which has used
"""
- code, stdout, _ = execute_shell_command(f"cat /proc/{pid}/status|grep VmRSS")
+ code, stdout, _ = execute_shell_command([f"cat /proc/{pid}/status", "grep VmRSS"])
if code == CommandExitCode.SUCCEED:
return stdout.split(":")[1].strip()
LOGGER.error(f'Failed to get memory info of process {pid}!')
@@ -80,7 +80,7 @@ class Resource:
Returns:
str: cpu usage
"""
- code, stdout, _ = execute_shell_command(f"ps -aux|grep -w {rpm_name}|grep {pid}|awk {{print$3}}")
+ code, stdout, _ = execute_shell_command(["ps -aux", f"grep -w {rpm_name}", f"grep {pid}", f"awk {{print$3}}"])
if code == CommandExitCode.SUCCEED:
return f'{stdout.strip()}%'
LOGGER.error(f'Failed to get plugin cpu info about {rpm_name}.')
diff --git a/ceres/manages/rollback_manage.py b/ceres/manages/rollback_manage.py
index 160a74c..51ef6d6 100644
--- a/ceres/manages/rollback_manage.py
+++ b/ceres/manages/rollback_manage.py
@@ -162,7 +162,7 @@ class RollbackManage:
Returns:
Tuple[str, str]: a tuple containing two elements (rollback result, log)
"""
- cmd = f"dnf history rollback {dnf_event_start} -y"
+ cmd = [f"dnf history rollback {dnf_event_start} -y"]
# 'dnf history rollback transaction-id' command can revert all dnf transactions performed after transaction-id
code, stdout, stderr = execute_shell_command(cmd)
if code != CommandExitCode.SUCCEED:
@@ -262,7 +262,7 @@ class RollbackManage:
Returns:
Tuple[str, str]: a tuple containing two elements (remove result, log)
"""
- code, stdout, stderr = execute_shell_command(f"rpm -qa | grep {installed_rpm}")
+ code, stdout, stderr = execute_shell_command(["rpm -qa", f"grep {installed_rpm}"])
# 'rpm -qa' shows installed rpm
# e.g.
# [root@openEuler ~]# rpm -qa | grep kernel-4.19.90-2112.8.0.0131.oe1.x86_64
@@ -272,7 +272,7 @@ class RollbackManage:
LOGGER.error(tmp_log)
return TaskExecuteRes.FAIL, tmp_log
- code, current_evra, stderr = execute_shell_command(f"uname -r")
+ code, current_evra, stderr = execute_shell_command([f"uname -r"])
# 'uname -r' show the kernel version-release.arch of the current system
# e.g.
# [root@openEuler ~]# uname -r
@@ -287,7 +287,7 @@ class RollbackManage:
if installed_evra == current_evra:
return TaskExecuteRes.SUCCEED, f"Preserve the {installed_rpm} due to it is in use."
- code, stdout, stderr = execute_shell_command(f"dnf remove {installed_rpm} -y")
+ code, stdout, stderr = execute_shell_command([f"dnf remove {installed_rpm} -y"])
if code != CommandExitCode.SUCCEED:
LOGGER.error(stderr)
return TaskExecuteRes.FAIL, stdout + stderr
@@ -305,7 +305,7 @@ class RollbackManage:
Returns:
Tuple[str, str]: a tuple containing two elements (check result, log)
"""
- code, stdout, stderr = execute_shell_command(f"grubby --default-kernel")
+ code, stdout, stderr = execute_shell_command([f"grubby --default-kernel"])
# 'grubby --default-kernel' shows boot default kernel version in the system
# e.g.
# [root@openEuler ~]# grubby --default-kernel
@@ -338,7 +338,7 @@ class RollbackManage:
Returns:
Tuple[str, str]: a tuple containing two elements (check result, log)
"""
- code, current_evra, stderr = execute_shell_command(f"uname -r")
+ code, current_evra, stderr = execute_shell_command(["uname -r"])
# 'uname -r' show the kernel version-release.arch of the current system
# e.g.
# [root@openEuler ~]# uname -r
@@ -371,7 +371,7 @@ class RollbackManage:
Returns:
Tuple[str, str]: a tuple containing two elements (check result, log)
"""
- code, stdout, stderr = execute_shell_command(f"rpm -qa | grep {target_rpm}")
+ code, stdout, stderr = execute_shell_command(["rpm -qa", f"grep {target_rpm}"])
# 'rpm -qa' shows installed rpm
# e.g.
# [root@openEuler ~]# rpm -qa | grep kernel-4.19.90-2112.8.0.0131.oe1.x86_64
@@ -402,7 +402,7 @@ class RollbackManage:
return TaskExecuteRes.FAIL, tmp_log
# 'grubby --set-default=/boot/vmlinuz-xxx' changes the default boot entry
- code, stdout, stderr = execute_shell_command(f"grubby --set-default={boot_file}")
+ code, stdout, stderr = execute_shell_command([f"grubby --set-default={boot_file}"])
if code != CommandExitCode.SUCCEED:
LOGGER.error(stderr)
return TaskExecuteRes.FAIL, stdout + stderr
diff --git a/ceres/manages/vulnerability_manage.py b/ceres/manages/vulnerability_manage.py
index 314e054..9017b17 100644
--- a/ceres/manages/vulnerability_manage.py
+++ b/ceres/manages/vulnerability_manage.py
@@ -87,7 +87,7 @@ class VulnerabilityManage:
Returns:
bool
"""
- code, _, stderr = execute_shell_command(f"dnf repoinfo --repo {repo_id}")
+ code, _, stderr = execute_shell_command([f"dnf repoinfo --repo {repo_id}"])
if code == CommandExitCode.SUCCEED:
return True
LOGGER.warning(f"Failed to query repo information with repo id {repo_id}.")
@@ -181,9 +181,7 @@ class VulnerabilityManage:
# powertop:powertop-2.9-12.oe1.x86_64
# libusbx:libusbx-1.0.23-1.oe1.x86_64
code, stdout, _ = execute_shell_command(
- """
- rpm -qa --queryformat '%{NAME}:%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | grep kernel
- """
+ ["rpm -qa --queryformat '%{NAME}:%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n'", "grep kernel"]
)
if code != CommandExitCode.SUCCEED or not stdout:
LOGGER.error("query installed packages info failed!")
@@ -222,7 +220,7 @@ class VulnerabilityManage:
# CVE-2021-45469 Important/Sec. kernel-4.19.90-2201.1.0.0132.oe1.x86_64
# CVE-2021-44733 Important/Sec. kernel-4.19.90-2201.1.0.0132.oe1.x86_64
unfixed_cves = []
- code, stdout, stderr = execute_shell_command("dnf updateinfo list cves | grep kernel")
+ code, stdout, stderr = execute_shell_command(["dnf updateinfo list cves", "grep kernel"])
if code != CommandExitCode.SUCCEED:
LOGGER.error("query unfixed cve info failed by dnf!")
LOGGER.error(stderr)
@@ -287,7 +285,7 @@ class VulnerabilityManage:
# CVE-2021-42574 Important/Sec. binutils-2.34-19.oe1.x86_64 -
# CVE-2023-1513 Important/Sec. kernel-4.19.90-2304.1.0.0196.oe1.x86_64 patch-kernel-4.19.90-2112...
cve_info_list = []
- code, stdout, stderr = execute_shell_command("dnf hot-updateinfo list cves | grep kernel")
+ code, stdout, stderr = execute_shell_command(["dnf hot-updateinfo list cves", "grep kernel"])
if code != CommandExitCode.SUCCEED:
LOGGER.error("query unfixed cve info failed by dnf!")
LOGGER.error(stderr)
@@ -354,7 +352,7 @@ class VulnerabilityManage:
return fixed_cves
current_kernel_rpm_name = f"kernel-{current_kernel_version}"
- code, stdout, stderr = execute_shell_command("dnf updateinfo list cves --installed |grep kernel")
+ code, stdout, stderr = execute_shell_command(["dnf updateinfo list cves --installed", "grep kernel"])
if code != CommandExitCode.SUCCEED:
LOGGER.error("query fixed cve info failed!")
LOGGER.error(stderr)
@@ -400,7 +398,7 @@ class VulnerabilityManage:
return []
current_kernel_rpm_name = f"kernel-{current_kernel_version}"
- code, stdout, stderr = execute_shell_command("dnf hot-updateinfo list cves --installed | grep kernel")
+ code, stdout, stderr = execute_shell_command(["dnf hot-updateinfo list cves --installed", "grep kernel"])
if code != CommandExitCode.SUCCEED:
LOGGER.error("query unfixed cve info failed by dnf!")
LOGGER.error(stderr)
@@ -468,7 +466,7 @@ class VulnerabilityManage:
# CVE-2023-1111 redis-6.2.5-1/SGL_CVE_2023_1111_CVE_2023_1112-1-1/redis-server NOT-APPLIED
# CVE-2023-1112 redis-6.2.5-1/SGL_CVE_2023_1111_CVE_2023_1112-1-1/redis-server NOT-APPLIED
result = {}
- code, stdout, stderr = execute_shell_command("dnf hotpatch --list cves")
+ code, stdout, stderr = execute_shell_command(["dnf hotpatch --list cves"])
if code != CommandExitCode.SUCCEED:
LOGGER.error("query applied hotpatch info failed!")
LOGGER.error(stderr)
@@ -634,7 +632,7 @@ class VulnerabilityManage:
Tuple[str, str]
a tuple containing two elements (upgrade result, package upgrade log).
"""
- code, stdout, stderr = execute_shell_command(f"dnf upgrade-en {rpm} -y")
+ code, stdout, stderr = execute_shell_command([f"dnf upgrade-en {rpm} -y"])
if code != CommandExitCode.SUCCEED:
LOGGER.error(stderr)
return TaskExecuteRes.FAIL, stdout + stderr
@@ -673,7 +671,7 @@ class VulnerabilityManage:
final_fix_result, package_update_info = TaskExecuteRes.SUCCEED, []
for rpm in rpms:
- code, stdout, stderr = execute_shell_command(f"dnf hotupgrade {rpm} -y")
+ code, stdout, stderr = execute_shell_command([f"dnf hotupgrade {rpm} -y"])
tmp = {
"available_rpm": rpm,
"result": TaskExecuteRes.SUCCEED,
@@ -711,7 +709,7 @@ class VulnerabilityManage:
"kernel-5.10.0-60.91.0.116.oe2203.x86_64": ["CVE-2023-2006"]
}}
"""
- code, stdout, stderr = execute_shell_command("dnf updateinfo list cves")
+ code, stdout, stderr = execute_shell_command(["dnf updateinfo list cves"])
if code != CommandExitCode.SUCCEED:
LOGGER.error("Failed to query update info by dnf!")
LOGGER.error(stderr)
@@ -737,7 +735,7 @@ class VulnerabilityManage:
Example:
"Succeed", {"kernel": {"CVE-2023-XXXX","CVE-2022-XXXX"}}
"""
- code, stdout, stderr = execute_shell_command("dnf hot-updateinfo list cves --installed")
+ code, stdout, stderr = execute_shell_command(["dnf hot-updateinfo list cves --installed"])
if code != CommandExitCode.SUCCEED:
LOGGER.error("Failed to query fixed cves by hotpatch!")
LOGGER.error(stderr)
@@ -808,7 +806,7 @@ class VulnerabilityManage:
return package_set
# The exit code of the command is 1 when input parameters contains assumeno
- _, stdout, _ = execute_shell_command(f"dnf upgrade-en {package} --assumeno")
+ _, stdout, _ = execute_shell_command([f"dnf upgrade-en {package} --assumeno"])
installed_rpm_info = re.findall(r"(Upgrading|Installing):(.*?)Transaction Summary", stdout, re.S)
if not installed_rpm_info:
@@ -841,7 +839,7 @@ class VulnerabilityManage:
return False
LOGGER.info("The Linux boot kernel is about to be changed")
- code, _, stderr = execute_shell_command(f"grubby --set-default={boot_kernel_path}")
+ code, _, stderr = execute_shell_command([f"grubby --set-default={boot_kernel_path}"])
if code != CommandExitCode.SUCCEED:
LOGGER.info("The Linux boot kernel change failed")
@@ -863,7 +861,9 @@ class VulnerabilityManage:
# ---------------------------------------------------------------------
# 3 | rm aops-ceres | 2023-11-30 09:57 | Removed | 1
# 2 | install gcc | 2023-11-30 09:57 | Install | 1
- code, stdout, stderr = execute_shell_command("dnf history | grep -E '^\s*[0-9]+'|head -1|awk '{print $1}'")
+ code, stdout, stderr = execute_shell_command(
+ ["dnf history", "grep -E '^\s*[0-9]+'", "head -1", "awk '{print $1}'"]
+ )
if code != CommandExitCode.SUCCEED:
LOGGER.error(stderr)
return None
@@ -898,7 +898,7 @@ class VulnerabilityManage:
# Last metadata expiration check: 3:25:24 ago on Wed 13 Sep 2023 08:16:17 AM CST.
# Gonna accept this hot patch: kernel-5.10.0-153.12.0.92.oe2203sp2/ACC-1-1
# accept hot patch 'kernel-5.10.0-153.12.0.92.oe2203sp2/ACC-1-1' failed, remain original status
- code, stdout, stderr = execute_shell_command(f"dnf hotpatch --{operation} {wait_to_remove_patch}")
+ code, stdout, stderr = execute_shell_command([f"dnf hotpatch --{operation} {wait_to_remove_patch}"])
if code != CommandExitCode.SUCCEED or 'failed' in stdout:
LOGGER.error(f"hotpatch {hotpatch} set status failed!")
return False, stdout + stderr
@@ -982,7 +982,7 @@ class VulnerabilityManage:
"CVE-XXXX-XXX": {"patch 1", "patch 2"}
}
"""
- code, stdout, _ = execute_shell_command(f"dnf hot-updateinfo list cves --installed|grep patch")
+ code, stdout, _ = execute_shell_command([f"dnf hot-updateinfo list cves --installed", "grep patch"])
if code != CommandExitCode.SUCCEED:
LOGGER.error(f"Failed to query the hotpatch list.")
return None
@@ -1016,6 +1016,6 @@ class VulnerabilityManage:
Args:
hotpatch: hotpatch package which needs to remove
"""
- cmd = f"dnf remove {hotpatch} -y"
+ cmd = [f"dnf remove {hotpatch} -y"]
_, stdout, stderr = execute_shell_command(cmd)
return True, f"Command:{cmd}\n\n{stdout}\n{stderr}\n"
--
2.33.0

View File

@ -1,82 +0,0 @@
From 5b0551698b60ea0c01ad9ee223f7009f230caa12 Mon Sep 17 00:00:00 2001
From: wang-guangge <wangguangge@huawei.com>
Date: Mon, 20 Nov 2023 20:51:57 +0800
Subject: [PATCH] add specific error information
---
hotpatch/hotupgrade.py | 9 ++++++---
hotpatch/upgrade_en.py | 8 +++++---
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/hotpatch/hotupgrade.py b/hotpatch/hotupgrade.py
index c508e07..5dfee0d 100644
--- a/hotpatch/hotupgrade.py
+++ b/hotpatch/hotupgrade.py
@@ -12,17 +12,19 @@
# ******************************************************************************/
from __future__ import print_function
+from time import sleep
+
import dnf.base
import dnf.exceptions
import hawkey
-from time import sleep
from dnf.cli import commands
from dnf.cli.option_parser import OptionParser
from dnfpluginscore import _, logger
-from .upgrade_en import UpgradeEnhanceCommand
+
from .hot_updateinfo import HotUpdateinfoCommand
-from .updateinfo_parse import HotpatchUpdateInfo
from .syscare import Syscare
+from .updateinfo_parse import HotpatchUpdateInfo
+from .upgrade_en import UpgradeEnhanceCommand
from .version import Versions
EMPTY_TAG = "-"
@@ -184,6 +186,7 @@ class HotupgradeCommand(dnf.cli.Command):
output, status = self.syscare.apply(hp_subname)
if status:
logger.info(_('Apply hot patch failed: %s.'), hp_subname)
+ logger.info(_('%s'), output)
else:
logger.info(_('Apply hot patch succeed: %s.'), hp_subname)
return status
diff --git a/hotpatch/upgrade_en.py b/hotpatch/upgrade_en.py
index 266bcae..3053179 100644
--- a/hotpatch/upgrade_en.py
+++ b/hotpatch/upgrade_en.py
@@ -10,13 +10,14 @@
# PURPOSE.
# See the Mulan PSL v2 for more details.
# ******************************************************************************/
-import dnf
import gzip
import subprocess
-from dnfpluginscore import _
+
+import dnf
from dnf.cli import commands
from dnf.cli.commands.upgrade import UpgradeCommand
from dnf.cli.option_parser import OptionParser
+from dnfpluginscore import _, logger
SUCCEED = 0
FAIL = 255
@@ -111,10 +112,11 @@ class UpgradeEnhanceCommand(dnf.cli.Command):
output, return_code = cmd_output(remove_cmd)
if return_code != SUCCEED:
print('Remove package failed: %s.' % pkg)
+ print(output)
exit(1)
else:
print('Remove package succeed: %s.' % pkg)
- # do not achieve the expected result of installing related kernel rpm
+ # do not achieve the expected result of installing related rpm
exit(1)
def rebuild_rpm_db(self):
--
2.27.0

View File

@ -0,0 +1,58 @@
From 19b611645b9be2e72c81cab5cb456f9a943d3caa Mon Sep 17 00:00:00 2001
From: rabbitali <wenxin32@foxmail.com>
Date: Wed, 7 Feb 2024 12:23:28 +0800
Subject: [PATCH 1/1] override list file method
---
ceres/manages/list_file_manage.py | 26 +++++++++++---------------
1 file changed, 11 insertions(+), 15 deletions(-)
diff --git a/ceres/manages/list_file_manage.py b/ceres/manages/list_file_manage.py
index dab55e6..081a714 100644
--- a/ceres/manages/list_file_manage.py
+++ b/ceres/manages/list_file_manage.py
@@ -14,14 +14,9 @@
# Description: default
# Date: 2023/6/14 16:31
import os
-import subprocess
from ceres.function.log import LOGGER
-from ceres.function.status import (
- UNKNOWN_ERROR,
- SUCCESS
-)
-from ceres.function.util import execute_shell_command
+from ceres.function.status import FILE_NOT_FOUND, UNKNOWN_ERROR, SUCCESS, PARAM_ERROR
class ListFileManage:
@@ -39,15 +34,16 @@ class ListFileManage:
str: status code
"""
file_list_res = []
+
+ if not os.path.exists(directory_path):
+ return FILE_NOT_FOUND, {"resp": file_list_res}
+
+ if os.path.isfile(directory_path):
+ return PARAM_ERROR, {"resp": file_list_res}
+
try:
- command = [f"ls -l {directory_path}", "awk '{print $9}'"]
- _, stdout, _ = execute_shell_command(command)
- file_list = stdout.split("\n")
- for file in file_list:
- if file:
- file_path_res = os.path.join(directory_path, file)
- file_list_res.append(file_path_res)
+ file_list_res = [os.path.join(directory_path, file) for file in os.listdir(directory_path)]
return SUCCESS, {"resp": file_list_res}
- except Exception as e:
- LOGGER.error("list the pam.d file failed, with msg{}".format(e))
+ except OSError as e:
+ LOGGER.error(f"Failed to read the file list under the path with message {e}")
return UNKNOWN_ERROR, {"resp": list()}
--
2.33.0

View File

@ -0,0 +1,25 @@
From f6cc88528868c646292f7b4d238e848b70d9246a Mon Sep 17 00:00:00 2001
From: rabbitali <wenxin32@foxmail.com>
Date: Wed, 5 Jun 2024 19:30:03 +0800
Subject: [PATCH 1/1] update register template file
---
conf/register_example.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/conf/register_example.json b/conf/register_example.json
index 4fcd642..60bcbc4 100644
--- a/conf/register_example.json
+++ b/conf/register_example.json
@@ -7,5 +7,6 @@
"host_group_name": "aops",
"management": false,
"ssh_port":22,
- "access_token": "token-string"
+ "access_token": "token-string",
+ "ssh_pkey":""
}
\ No newline at end of file
--
2.33.0

View File

@ -1,63 +0,0 @@
From 27df2fbb6c18c382e7099015915f7efb673a9e06 Mon Sep 17 00:00:00 2001
From: rabbitali <wenxin32@foxmail.com>
Date: Tue, 21 Nov 2023 09:02:09 +0800
Subject: [PATCH] update return log field of the cve fix func
---
ceres/manages/vulnerability_manage.py | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/ceres/manages/vulnerability_manage.py b/ceres/manages/vulnerability_manage.py
index da98297..23ae2ce 100644
--- a/ceres/manages/vulnerability_manage.py
+++ b/ceres/manages/vulnerability_manage.py
@@ -621,11 +621,12 @@ class VulnerabilityManage:
a tuple containing two elements (update result, log).
"""
code, stdout, stderr = execute_shell_command(f"dnf upgrade-en {rpm_name} -y")
+ log = stdout + stderr
if code != CommandExitCode.SUCCEED:
- return TaskExecuteRes.FAIL, stderr
- if "Complete" not in stdout:
- return TaskExecuteRes.FAIL, stdout
- return TaskExecuteRes.SUCCEED, stdout
+ return TaskExecuteRes.FAIL, log
+ if "Complete" not in log:
+ return TaskExecuteRes.FAIL, log
+ return TaskExecuteRes.SUCCEED, log
def _update_hotpatch_by_dnf_plugin(self, hotpatch_pkg: str) -> Tuple[str, str]:
"""
@@ -645,22 +646,23 @@ class VulnerabilityManage:
update_command = f"dnf hotupgrade {hotpatch_pkg} -y"
code, stdout, stderr = execute_shell_command(update_command)
+ log = stdout + stderr
if code != CommandExitCode.SUCCEED:
- return TaskExecuteRes.FAIL, stderr
+ return TaskExecuteRes.FAIL, log
if "Apply hot patch succeed" not in stdout and "No hot patches marked for install" not in stdout:
- return TaskExecuteRes.FAIL, stdout
+ return TaskExecuteRes.FAIL, log
if not self.takeover and self.accepted:
try:
hotpatch_name = hotpatch_pkg.rsplit(".", 1)[0].split("-", 1)[1]
- _, log = self._set_hotpatch_status_by_dnf_plugin(hotpatch_name, "accept")
- stdout += f"\n\n{log}"
+ _, hotpatch_status_set_log = self._set_hotpatch_status_by_dnf_plugin(hotpatch_name, "accept")
+ log += f"\n\n{hotpatch_status_set_log}"
except IndexError as error:
LOGGER.error(error)
- stdout += f"\n\nhotpatch status set failed due to can't get correct hotpatch name!"
+ log += f"\n\nhotpatch status set failed due to can't get correct hotpatch name!"
- return TaskExecuteRes.SUCCEED, stdout
+ return TaskExecuteRes.SUCCEED, log
@staticmethod
def _set_hotpatch_status_by_dnf_plugin(hotpatch: str, operation: str) -> Tuple[bool, str]:
--
2.33.0

Binary file not shown.

BIN
aops-ceres-v1.4.1.tar.gz Normal file

Binary file not shown.

View File

@ -1,24 +1,24 @@
%define datool_with_testing 0 %define datool_with_testing 0
Name: aops-ceres Name: aops-ceres
Version: v1.3.4 Version: v1.4.1
Release: 8 Release: 7
Summary: An agent which needs to be adopted in client, it managers some plugins, such as gala-gopher(kpi collection), fluentd(log collection) and so on. Summary: An agent which needs to be adopted in client, it managers some plugins, such as gala-gopher(kpi collection), fluentd(log collection) and so on.
License: MulanPSL2 License: MulanPSL2
URL: https://gitee.com/openeuler/%{name} URL: https://gitee.com/openeuler/%{name}
Source0: %{name}-%{version}.tar.gz Source0: %{name}-%{version}.tar.gz
Patch0001: 0001-support-kabi-check.patch
Patch0002: 0002-modify-re-of-kernel-filter.patch
Patch0003: 0003-fix-bug-in-test_hotpatch.py.patch
Patch0004: 0004-Modify-method-of-mark-invalid-data-and-add-summary.patch
Patch0005: 0005-add-specific-error-information.patch
Patch0006: 0006-update-return-log-field-of-the-cve-fix-func.patch
BuildRequires: python3-setuptools BuildRequires: python3-setuptools
Requires: python3-requests python3-jsonschema python3-libconf Requires: python3-requests python3-jsonschema python3-libconf
Requires: python3-concurrent-log-handler dmidecode dnf-hotpatch-plugin >= v1.3.4 Requires: python3-concurrent-log-handler dmidecode dnf-hotpatch-plugin >= v1.3.4
Provides: aops-ceres Provides: aops-ceres
Conflicts: aops-agent Conflicts: aops-agent
Patch0001: 0001-improve-status-judgement-and-hotupgrade-logic.patch
Patch0002: 0002-support-restore-grubby-if-kabi-check-failed.patch
Patch0003: 0003-remove-installed-rpm-if-unreboot-and-improve-log-for-rollback.patch
Patch0004: 0004-fix-cve-2021-33633.patch
Patch0005: 0005-override-list-file-method.patch
Patch0006: 0006-update-register-template-file.patch
%description %description
@ -70,9 +70,9 @@ cp -r hotpatch %{buildroot}/%{python3_sitelib}/dnf-plugins/
# install for da-tool # install for da-tool
mkdir -p ${RPM_BUILD_ROOT}%{_bindir} mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir} mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}
install -b -m640 ./extra-tools/da-tool/conf/da-tool.conf ${RPM_BUILD_ROOT}%{_sysconfdir}/ install -b -m400 ./extra-tools/da-tool/conf/da-tool.conf ${RPM_BUILD_ROOT}%{_sysconfdir}/
install -b -m755 ./extra-tools/da-tool/build/da-tool-analysis ${RPM_BUILD_ROOT}%{_bindir}/ install -b -m500 ./extra-tools/da-tool/build/da-tool-analysis ${RPM_BUILD_ROOT}%{_bindir}/
install -b -m755 ./extra-tools/da-tool/script/da-tool.sh ${RPM_BUILD_ROOT}%{_bindir}/ install -b -m500 ./extra-tools/da-tool/script/da-tool.sh ${RPM_BUILD_ROOT}%{_bindir}/
%files %files
%doc README.* %doc README.*
@ -88,10 +88,57 @@ install -b -m755 ./extra-tools/da-tool/script/da-tool.sh ${RPM_BUILD_ROOT}
%files -n da-tool %files -n da-tool
%defattr (-, root, root) %defattr (-, root, root)
%config(noreplace) %{_sysconfdir}/da-tool.conf %config(noreplace) %{_sysconfdir}/da-tool.conf
%attr(755, root, root) %{_bindir}/da-tool.sh %attr(0500, root, root) %{_bindir}/da-tool.sh
%attr(755, root, root) %{_bindir}/da-tool-analysis %attr(0500, root, root) %{_bindir}/da-tool-analysis
%changelog %changelog
* Wed Jun 05 2024 wenxin<wenxin32@foxmail.com> - v1.4.1-7
- update register template file
* Wed Feb 07 2024 wenxin<wenxin32@foxmail.com> - v1.4.1-6
- override list file method
* Sun Feb 04 2024 wenxin<wenxin32@foxmail.com> - v1.4.1-5
- fix cve-2021-33633
* Fri Dec 22 2023 wangguangge<wangguangge@huawei.com> - v1.4.1-4
- support remove installed rpm if unreboot and improve log info for rollback operation
* Wed Dec 20 2023 wangguangge<wangguangge@huawei.com> - v1.4.1-3
- support restore default grubby boot kernel if kernel kabi check failed
* Mon Dec 18 2023 wangguangge<wangguangge@huawei.com> - v1.4.1-2
- improve task execution status code and hotupgrade logic of reinstalling active/accept hotpatch
* Mon Dec 18 2023 wangguangge<wangguangge@huawei.com> - v1.4.1-1
- update to v1.4.1
- update cve fix logic
- support rollback operation for kernel hotpatch/coldpatch
* Tue Dec 12 2023 wenxin<wenxin32@foxmail.com> - v1.4.0-2
- fix unboundlocalerror with variable name log
* Tue Dec 12 2023 wenxin<wenxin32@foxmail.com> - v1.4.0-1
- Change CVE rollback task to hotpatch remove
- update cve scan method and cve fix method
* Mon Dec 4 2023 liuchanggeng<liuchanggeng@huawei.com> - v1.3.4-12
- to maintain functional stability, da-tool only releases network related analysis
- it is not allowed to modify the configuration file of the da-tool
* Tue Nov 28 2023 liuchanggeng<liuchanggeng@huawei.com> - v1.3.4-11
- da-tool consider trace as valid data when first core lost scheduling information
- update document
* Mon Nov 27 2023 liuchanggeng<liuchanggeng@huawei.com> - v1.3.4-10
- add check of command parameters and configuration files
- handling scenarios with lost scheduling information
- update document
* Thu Nov 23 2023 liuchanggeng<liuchanggeng@huawei.com> - v1.3.4-9
- da-tool add usage
- da-tool check for duplicate configurations
* Tue Nov 21 2023 wenxin<wenxin32@foxmail.com> - v1.3.4-8 * Tue Nov 21 2023 wenxin<wenxin32@foxmail.com> - v1.3.4-8
- update return log field of the cve fix func - update return log field of the cve fix func
- add specific error information - add specific error information