import CS git sos-4.11.2-4.el8_10

This commit is contained in:
AlmaLinux RelEng Bot 2026-08-26 06:16:43 -04:00
parent 2dd39933dd
commit 215aaca98b
12 changed files with 1972 additions and 96 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/sos-4.11.0.tar.gz
SOURCES/sos-4.11.2.tar.gz
SOURCES/sos-audit-0.3-1.tgz

View File

@ -1,2 +1,2 @@
b95a041f0826234fcdc7ee452d31609972d5d556 SOURCES/sos-4.11.0.tar.gz
d8d5e3e1eb124345417341ef9e9aa84f5cae609f SOURCES/sos-4.11.2.tar.gz
00752b68ec5e1141192a9dab7d44377b8d637bf7 SOURCES/sos-audit-0.3-1.tgz

View File

@ -23,22 +23,25 @@
res.append(ls[0])
except Exception as err:
self.log_debug(f"Error parsing sos help: {err}")
--- a/sos/report/plugins/mongodb.py
+++ b/sos/report/plugins/mongodb.py
@@ -87,9 +87,11 @@
--- a/sos/report/plugins/mongodb.py 2026-07-02 09:06:03.860609746 +0200
+++ b/sos/report/plugins/mongodb.py 2026-07-02 09:08:00.003595562 +0200
@@ -87,10 +87,13 @@
)
def setup(self):
- if get_juju_info := self.path_exists('/var/lib/juju/db'):
+ if self.path_exists('/var/lib/juju/db'):
+ get_juju_info = self.path_exists('/var/lib/juju/db')
+ get_juju_info = self.path_exists('/var/lib/juju/db')
+ if get_juju_info:
self.db_folder = "/var/lib/juju/db"
- elif get_juju_info := self.path_exists('/var/snap/juju-db/curent/db'):
+ elif self.path_exists('/var/snap/juju-db/curent/db'):
+ get_juju_info = self.path_exists('/var/snap/juju-db/curent/db')
self.db_folder = "/var/snap/juju-db/current/db"
- self.db_folder = "/var/snap/juju-db/current/db"
+ else:
+ get_juju_info = self.path_exists('/var/snap/juju-db/current/db')
+ if get_juju_info:
+ self.db_folder = "/var/snap/juju-db/current/db"
super().setup()
--- a/sos/report/plugins/loki.py 2025-11-24 11:20:56.237814760 +0100
+++ b/sos/report/plugins/loki.py 2025-11-24 11:28:37.466603011 +0100
@@ -143,7 +143,8 @@
@ -51,43 +54,29 @@
if isinstance(labels_option, str) and labels_option:
self.labels.extend(labels_option.split(":"))
--- a/sos/cleaner/archives/__init__.py 2025-09-22 19:44:51.272619200 +0200
+++ b/sos/cleaner/archives/__init__.py 2025-09-22 23:28:15.116001268 +0200
@@ -118,6 +118,8 @@ class SoSObfuscationArchive():
self.parsers = parsers # TODO: include this in __init__?
def load_parser_entries(self):
+ self.soslog = logging.getLogger('sos')
+ self.ui_log = logging.getLogger('sos_ui')
for parser in self.parsers:
parser.load_map_entries()
@@ -150,6 +152,7 @@ class SoSObfuscationArchive():
return line, count
def obfuscate_arc_files(self, flist):
+ self.load_parser_entries()
for filename in flist:
self.log_debug(f" pid={os.getpid()}: obfuscating {filename}")
try:
--- a/sos/cleaner/__init__.py 2025-09-22 19:44:51.272619200 +0200
+++ b/sos/cleaner/__init__.py 2025-09-22 23:32:17.606745778 +0200
@@ -720,10 +720,11 @@ third party.
# based on files' sizes.
--- a/sos/cleaner/__init__.py
+++ b/sos/cleaner/__init__.py
@@ -40,6 +40,8 @@ from sos.utilities import (get_human_rea
# an auxiliary method to kick off child processes over its instances
def _obfuscate_arc_files(arc, input_queue, output_queue):
+ arc.soslog = logging.getLogger('sos')
+ arc.ui_log = logging.getLogger('sos_ui')
while True:
try:
file = input_queue.get()
--- a/sos/cleaner/__init__.py 2026-07-01 13:45:34.298955340 +0200
+++ b/sos/cleaner/__init__.py 2026-07-01 13:47:15.978445308 +0200
@@ -795,6 +795,9 @@
# sentinel mark. That triggers the child processes to report back
# to output_queue some stats, and finish.
files_obfuscated_count = total_sub_count = removed_file_count = 0
+ # two nullification required before processes cloning
+ archive.soslog = None
+ archive.ui_log = None
archive_list = [archive for i in range(self.opts.jobs)]
- with ProcessPoolExecutor(
- max_workers=self.opts.jobs,
- initializer=archive.load_parser_entries) as executor:
+ with ProcessPoolExecutor(max_workers=self.opts.jobs) as executor:
futures = executor.map(obfuscate_arc_files, archive_list,
[file_list[i::self.opts.jobs] for i in
range(self.opts.jobs)])
input_queue = multiprocessing.Queue()
output_queue = multiprocessing.Queue()
--- a/sos/collector/sosnode.py 2026-04-02 10:15:34.743009569 +0200
+++ b/sos/collector/sosnode.py 2026-04-02 10:17:42.557250748 +0200
@@ -163,7 +163,8 @@
@ -114,3 +103,65 @@
else:
confs += glob.glob(_ent)
--- a/sos/report/plugins/charmed_cruise_control.py 2026-07-16 13:00:22.269714807 +0200
+++ b/sos/report/plugins/charmed_cruise_control.py 2026-07-16 13:01:56.710522628 +0200
@@ -35,7 +35,8 @@
) as f:
content = f.read().strip()
- if match := re.match(r"balancer: (?P<pwd>\w+),ADMIN", content):
+ match = re.match(r"balancer: (?P<pwd>\w+),ADMIN", content)
+ if match:
pwd = match.group("pwd")
return f"-u balancer:{pwd}"
--- a/sos/report/plugins/__init__.py
+++ b/sos/report/plugins/__init__.py
@@ -3262,7 +3262,10 @@
# skip forbidden paths; since we might recursivelly copied
# whole directory, we must find the forbidden files in dest
# path and delete the unwanted
- base_dir = dest.removesuffix(f"{path.lstrip('/')}")
+ _suffix = path.lstrip('/')
+ base_dir = (dest[:-len(_suffix)]
+ if dest.endswith(_suffix) and _suffix
+ else dest)
for relname in [file.relative_to(base_dir).as_posix()
for file in Path(dest).rglob('*')]:
absname = f"/{relname}"
--- a/sos/cleaner/__init__.py
+++ b/sos/cleaner/__init__.py
@@ -846,6 +846,8 @@
# *all* mapping.all(item) methods - so replaying this will
# generate the right datasets!
archive.load_parser_entries()
+ archive.soslog = logging.getLogger('sos')
+ archive.ui_log = logging.getLogger('sos_ui')
try:
self.obfuscate_directory_names(archive)
--- a/sos/report/plugins/charmed_mongodb.py 2026-07-16 14:48:09.639484635 +0200
+++ b/sos/report/plugins/charmed_mongodb.py 2026-07-16 14:49:02.337015148 +0200
@@ -122,8 +122,8 @@
encoding="utf-8",
) as f:
data = yaml.safe_load(f)
-
- if sharding_conf := data.get("sharding", {}):
+ sharding_conf = data.get("sharding", {})
+ if sharding_conf:
role = sharding_conf.get("clusterRole", "")
return self._match_role(role)
@@ -144,7 +144,8 @@
return None
data = yaml.safe_load(result.get("output", ""))
- if sharding_conf := data.get("sharding", {}):
+ sharding_conf = data.get("sharding", {})
+ if sharding_conf:
role = sharding_conf.get("clusterRole", "")
return self._match_role(role)

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +0,0 @@
--- a/sos/upload/targets/__init__.py 2025-09-16 19:57:27.294642506 +0200
+++ b/sos/upload/targets/__init__.py 2025-09-16 19:59:44.498573843 +0200
@@ -465,7 +465,7 @@
self.upload_password or
self._upload_password)
- def upload_sftp(self, user=None, password=None, user_dir=None):
+ def upload_sftp(self, user=None, password=None):
"""Attempts to upload the archive to an SFTP location.
Due to the lack of well maintained, secure, and generally widespread
@@ -540,13 +540,10 @@
raise Exception("Unable to connect via SFTP to "
f"{self.get_upload_url_string()}")
- # certain implementations require file to be put in the user dir
- put_cmd = (
- f"put {self.upload_archive_name} "
- f"{f'{user_dir}/' if user_dir else ''}"
- f"{self._get_sftp_upload_name()}"
- )
+ put_cmd = (f'put {self.upload_archive_name} '
+ f'{self._get_sftp_upload_name()}')
ret.sendline(put_cmd)
+
put_expects = [
'100%',
pexpect.TIMEOUT,
--- a/sos/upload/targets/redhat.py 2025-09-16 19:57:36.804628207 +0200
+++ b/sos/upload/targets/redhat.py 2025-09-16 20:00:52.578728154 +0200
@@ -145,7 +145,7 @@
return fname
# pylint: disable=too-many-branches
- def upload_sftp(self, user=None, password=None, user_dir=None):
+ def upload_sftp(self, user=None, password=None):
"""Override the base upload_sftp to allow for setting an on-demand
generated anonymous login for the RH SFTP server if a username and
password are not given
@@ -217,8 +217,7 @@
f"{anon.status_code}): {anon.json()}"
)
if _user and _token:
- return super().upload_sftp(user=_user, password=_token,
- user_dir=_user)
+ return super().upload_sftp(user=_user, password=_token)
raise Exception("Could not retrieve valid or anonymous credentials")
def check_file_too_big(self, archive):

View File

@ -0,0 +1,121 @@
diff --git a/sos/upload/targets/__init__.py b/sos/upload/targets/__init__.py
index 9e905e1063..6f72d963ea 100644
--- a/sos/upload/targets/__init__.py
+++ b/sos/upload/targets/__init__.py
@@ -540,36 +540,7 @@ def upload_sftp(self, user=None, password=None, user_dir=None):
raise Exception("Unable to connect via SFTP to "
f"{self.get_upload_url_string()}")
- # user_dir indicates that we need to switch into a specific user
- # directory. If ChRootDirectory is set, this happens automatically
- # so check if the PWD contains the user. If it does, we are
- # already in the user directory so set user_dir to None
- if user_dir:
- user_match = False
- ret.sendline('pwd')
- pwd_expects = [
- 'sftp>',
- 'Invalid command.',
- pexpect.TIMEOUT,
- pexpect.EOF
- ]
- pwd_cmd = ret.expect(pwd_expects, timeout=10) == 0
- if pwd_cmd:
- # Extract the path from child.before
- raw_output = ret.before
- user_match = re.search(user, raw_output)
- else:
- self.ui_log.warning("This server does not support the PWD "
- "command - unable to verify user "
- "directory. Attempting upload without "
- "changing to user directory.")
- user_dir = None
-
- if user_match:
- user_dir = None
-
# certain implementations require file to be put in the user dir
- # so we prepend the user directory to the file path
put_cmd = (
f"put {self.upload_archive_name} "
f"{f'{user_dir}/' if user_dir else ''}"
diff --git a/sos/upload/targets/redhat.py b/sos/upload/targets/redhat.py
index 636a645fe6..0cfb80eecd 100644
--- a/sos/upload/targets/redhat.py
+++ b/sos/upload/targets/redhat.py
@@ -158,7 +158,6 @@ def upload_sftp(self, user=None, password=None, user_dir=None):
" for obtaining SFTP auth token.")
_token = None
_user = None
- _user_dir = None
# We may have a device token already if we attempted
# to upload via http but the upload failed. So
@@ -192,7 +191,6 @@ def upload_sftp(self, user=None, password=None, user_dir=None):
# credentials are valid
_user = json.loads(ret.text)['username']
_token = json.loads(ret.text)['token']
- _user_dir = f"/users/{_user}"
else:
self.ui_log.debug(
f"DEBUG: auth attempt failed (status: {ret.status_code}): "
@@ -220,7 +218,7 @@ def upload_sftp(self, user=None, password=None, user_dir=None):
)
if _user and _token:
return super().upload_sftp(user=_user, password=_token,
- user_dir=_user_dir)
+ user_dir=_user)
raise Exception("Could not retrieve valid or anonymous credentials")
def check_file_too_big(self, archive):
--
2.47.0
--- a/sos/upload/targets/__init__.py 2025-09-16 19:57:27.294642506 +0200
+++ b/sos/upload/targets/__init__.py 2025-09-16 19:59:44.498573843 +0200
@@ -465,7 +465,7 @@
self.upload_password or
self._upload_password)
- def upload_sftp(self, user=None, password=None, user_dir=None):
+ def upload_sftp(self, user=None, password=None):
"""Attempts to upload the archive to an SFTP location.
Due to the lack of well maintained, secure, and generally widespread
@@ -540,13 +540,10 @@
raise Exception("Unable to connect via SFTP to "
f"{self.get_upload_url_string()}")
- # certain implementations require file to be put in the user dir
- put_cmd = (
- f"put {self.upload_archive_name} "
- f"{f'{user_dir}/' if user_dir else ''}"
- f"{self._get_sftp_upload_name()}"
- )
+ put_cmd = (f'put {self.upload_archive_name} '
+ f'{self._get_sftp_upload_name()}')
ret.sendline(put_cmd)
+
put_expects = [
'100%',
pexpect.TIMEOUT,
--- a/sos/upload/targets/redhat.py 2025-09-16 19:57:36.804628207 +0200
+++ b/sos/upload/targets/redhat.py 2025-09-16 20:00:52.578728154 +0200
@@ -145,7 +145,7 @@
return fname
# pylint: disable=too-many-branches
- def upload_sftp(self, user=None, password=None, user_dir=None):
+ def upload_sftp(self, user=None, password=None):
"""Override the base upload_sftp to allow for setting an on-demand
generated anonymous login for the RH SFTP server if a username and
password are not given
@@ -217,8 +217,7 @@
f"{anon.status_code}): {anon.json()}"
)
if _user and _token:
- return super().upload_sftp(user=_user, password=_token,
- user_dir=_user)
+ return super().upload_sftp(user=_user, password=_token)
raise Exception("Could not retrieve valid or anonymous credentials")
def check_file_too_big(self, archive):

View File

@ -0,0 +1,37 @@
From 2fab657e3909f76e31bc6c56a5ad26f86a9925e5 Mon Sep 17 00:00:00 2001
From: Pavel Moravec <pmoravec@redhat.com>
Date: Tue, 23 Jun 2026 17:17:01 +0200
Subject: [PATCH] [foreman-installer] Scrub secrets in CLI arg dumps
Installer logs dump CLI args we need to scrub.
Closes: #4367
Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
---
sos/report/plugins/foreman_installer.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/sos/report/plugins/foreman_installer.py b/sos/report/plugins/foreman_installer.py
index f55cde23..89eef2e4 100644
--- a/sos/report/plugins/foreman_installer.py
+++ b/sos/report/plugins/foreman_installer.py
@@ -54,11 +54,12 @@ class ForemanInstaller(Plugin, DebianPlugin, UbuntuPlugin):
r"::(.*(token|secret|key|passw).*)\") value:) "
r"(.*)")
self.do_path_regex_sub(install_logs, logs_debug_reg, r"\1 \2 ********")
- # also hide passwords in yet different formats
+ # also hide passwords in yet different formats, including CLI arg dumps
self.do_path_regex_sub(
install_logs,
- r"password(\", \"|=|\" value: \"|\": \")(.*?)(\", \".*|\"]]|\"|$)",
- r"password\1********\3")
+ r"((?:password|consumer-key|consumer-secret|key-secret|secret-key|"
+ r"oauth-key|oauth-secret)(?:\", \"|\": \"|=))([^\"\n]*)(\"|$)",
+ r"\1********\3")
self.do_path_regex_sub(
"/var/log/foreman-installer/foreman-proxy*",
r"(\s*proxy_password\s=) (.*)",
--
2.54.0

View File

@ -0,0 +1,97 @@
From 5e7a01d9df2bc4e1f2659ace959ea52228ee1eee Mon Sep 17 00:00:00 2001
From: akumari <akumari@redhat.com>
Date: Wed, 1 Jul 2026 09:26:52 +0530
Subject: [PATCH 1/2] [foremanctl] Enable plugin for containerized deployments
The plugin required foremanctl package which doesn't exist in
containerized mode. Add container detection to enable the plugin
and collect foremanctl health diagnostics for support cases.
Signed-off-by: akumari <akumari@redhat.com>
---
sos/report/plugins/foremanctl.py | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/sos/report/plugins/foremanctl.py b/sos/report/plugins/foremanctl.py
index 1b6ba4a4..0425cc05 100644
--- a/sos/report/plugins/foremanctl.py
+++ b/sos/report/plugins/foremanctl.py
@@ -19,6 +19,7 @@ class Foremanctl(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
plugin_name = 'foremanctl'
profiles = ('sysmgmt',)
packages = ('foremanctl', )
+ containers = ('foreman', 'foreman-proxy',)
def setup(self):
self.add_copy_spec([
@@ -29,14 +30,34 @@ class Foremanctl(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
self.add_cmd_output([
"foremanctl features",
+ "foremanctl health",
])
self.add_dir_listing(["/var/lib/foremanctl/"], recursive=True)
def postproc(self):
- self.do_path_regex_sub("/var/lib/foremanctl/parameters.yaml",
- r"(foreman_initial_admin_password:\s*)(.*)",
- r"\1********")
-
+ # Scrub passwords, credentials, tokens, secrets, and keys
+ self.do_path_regex_sub(
+ "/var/lib/foremanctl/parameters.yaml",
+ r"((.*)?(passw|cred|token|secret|key).*(\:\s|=))(.*)",
+ r"\1********")
+
+ # Scrub passwords from foremanctl logs - Pattern 1: key=value format
+ self.do_path_regex_sub(
+ "/var/log/foremanctl/foremanctl.*log*",
+ r"((passw|cred|token|secret|key)\w*\s*=\s*)(.*?)(\s|,|\"|'|$)",
+ r"\1********\4")
+
+ # Scrub passwords from foremanctl logs - Pattern 2: "password something" format
+ self.do_path_regex_sub(
+ "/var/log/foremanctl/foremanctl.*log*",
+ r"(password\s+)(.*?)(\s|,|\"|$)",
+ r"\1********\3")
+
+ # Scrub admin credentials in username:password format
+ self.do_path_regex_sub(
+ "/var/log/foremanctl/foremanctl.*log*",
+ r"(Admin credentials:\s+\w+:)(.*?)(\"|,|$)",
+ r"\1********\3")
# vim: set et ts=4 sw=4 :
--
2.54.0
From 3b6bbcb819e05aecf0fec4767588ea0376c9f218 Mon Sep 17 00:00:00 2001
From: akumari <akumari@redhat.com>
Date: Tue, 7 Jul 2026 14:06:40 +0530
Subject: [PATCH 2/2] [valkey] Add container support for containerized
deployments
Adds container support to the valkey plugin to enable it
for containerized deployments using foremanctl/quadlet.
Signed-off-by: akumari <akumari@redhat.com>
---
sos/report/plugins/valkey.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/sos/report/plugins/valkey.py b/sos/report/plugins/valkey.py
index 26a74a56..f7b49253 100644
--- a/sos/report/plugins/valkey.py
+++ b/sos/report/plugins/valkey.py
@@ -19,6 +19,7 @@ class Valkey(Plugin, IndependentPlugin):
profiles = ('services',)
packages = ('valkey',)
+ containers = ('valkey',)
var_puppet_gen = "/var/lib/config-data/puppet-generated/valkey"
--
2.54.0

View File

@ -0,0 +1,74 @@
From 6085b2580173a7a43de8b541584c82481c617aa2 Mon Sep 17 00:00:00 2001
From: asadawar <asadawar@users.noreply.github.com>
Date: Mon, 27 Jul 2026 17:50:42 +0530
Subject: [PATCH] [policies] Prefer most specific policy when multiple match
When multiple policies within the same module return True from
check(), the policy loader now selects the most specific one
(deepest in the class hierarchy) instead of whichever happens
to sort first alphabetically.
Previously, import_policy() returned classes sorted by name via
inspect.getmembers(), and load() picked the first match. This
caused RHELPolicy to always win over RedHatCoreOSPolicy inside
a toolbox container on RHCOS, because uppercase 'H' sorts before
lowercase 'e' in ASCII. Both policies return True in that context
(RHEL for the container's /etc/redhat-release, RHCOS for the
host's /host/etc/os-release), but the more specific RHCOS policy
was never reached.
This has existed since RedHatCoreOSPolicy was introduced in 2019
(commit fa06bc09c95c) but was never visible because RHCOS had no
behavioral differences from RHEL until the archive naming change
in commit 0e919b6.
The fix collects all matching policies from a module and sorts by
MRO depth (descending), so a subclass is always preferred over
its parent. This is safe because a subclass that returns True from
check() is by definition a more precise match than its parent.
Assisted-by: Claude Code <https://claude.ai/code>
Signed-off-by: asadawar <asadawar@users.noreply.github.com>
---
sos/policies/__init__.py | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py
index 35b3a532..b4920e82 100644
--- a/sos/policies/__init__.py
+++ b/sos/policies/__init__.py
@@ -29,20 +29,24 @@ def import_policy(name):
return None
-def load(cache={}, sysroot=None, init=None, probe_runtime=True,
+def load(cache=None, sysroot=None, init=None, probe_runtime=True,
remote_exec=None, remote_check=''):
+ if cache is None:
+ cache = {}
if 'policy' in cache:
return cache.get('policy')
import sos.policies.distros
helper = ImporterHelper(sos.policies.distros)
+ matches = []
for module in helper.get_modules():
- for policy in import_policy(module):
- if policy.check(remote=remote_check):
- cache['policy'] = policy(sysroot=sysroot, init=init,
- probe_runtime=probe_runtime,
- remote_exec=remote_exec)
- break
+ matches.extend([policy for policy in (import_policy(module) or [])
+ if policy.check(remote=remote_check)])
+ if matches:
+ matches.sort(key=lambda p: len(p.__mro__), reverse=True)
+ cache['policy'] = matches[0](sysroot=sysroot, init=init,
+ probe_runtime=probe_runtime,
+ remote_exec=remote_exec)
if sys.platform != 'linux':
raise Exception("SoS is not supported on this platform")
--
2.55.0

View File

@ -0,0 +1,90 @@
From d94095e55d69d5e4135df0193c9726c2789526ab Mon Sep 17 00:00:00 2001
From: Pavel Moravec <pmoravec@redhat.com>
Date: Wed, 29 Jul 2026 10:46:25 +0200
Subject: [PATCH] [processor] Limit /sys/devices/system/cpu/cpu* subdirs
collected
For systems with >500 CPUs, collecting all such directories means
millions of files to be collected, what excessivelly slows down the
plugin until its timeout.
Limit the default number of such directories to 64, configurable via a
plugin option.
Resolves: #4399
Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
---
sos/report/plugins/processor.py | 41 ++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/sos/report/plugins/processor.py b/sos/report/plugins/processor.py
index 9375b5a1..593bd36b 100644
--- a/sos/report/plugins/processor.py
+++ b/sos/report/plugins/processor.py
@@ -6,7 +6,9 @@
#
# See the LICENSE file in the source distribution for further information.
-from sos.report.plugins import Plugin, IndependentPlugin, SoSPredicate
+import re
+from sos.report.plugins import (Plugin, IndependentPlugin, SoSPredicate,
+ PluginOpt)
from sos.policies.distros.ubuntu import UbuntuPolicy
@@ -18,6 +20,11 @@ class Processor(Plugin, IndependentPlugin):
profiles = ('system', 'hardware', 'memory')
files = ('/proc/cpuinfo',)
packages = ('cpufreq-utils', 'cpuid')
+ option_list = [
+ PluginOpt('max_cpu_dirs', default=64, val_type=int,
+ desc='Maximum number of cpu[0-9]+ directories '
+ 'to collect from /sys/devices/system/cpu'),
+ ]
cpu_kmods = []
@@ -43,7 +50,39 @@ class Processor(Plugin, IndependentPlugin):
# copy /sys/devices/system/cpu/cpuX with separately applied sizelimit
# this is required for systems with tens/hundreds of CPUs where the
# cumulative directory size exceeds 25MB or even 100MB.
+ # Limit cpu[0-9]* directories to avoid excessive collection.
+ # All non-cpu* directories are always collected.
+ max_cpu_dirs = self.get_option('max_cpu_dirs')
+ if max_cpu_dirs < 0:
+ self._log_info(f"Invalid max_cpu_dirs={max_cpu_dirs} value "
+ f"provided, replacing by 0."
+ )
+ max_cpu_dirs = 0
cdirs = self.listdir('/sys/devices/system/cpu')
+
+ if len(cdirs) > max_cpu_dirs:
+ # separate cpu from non-cpu, then limit cpu dirs
+ cpu_pattern = re.compile(r'cpu(\d+)')
+ cpu_dirs = []
+ other_dirs = []
+
+ for cdir in cdirs:
+ if cpu_pattern.fullmatch(cdir):
+ cpu_dirs.append(cdir)
+ else:
+ other_dirs.append(cdir)
+
+ # Only limit if cpu_dirs specifically exceeds max
+ if len(cpu_dirs) > max_cpu_dirs:
+ self._log_info(
+ f"Limiting cpu directories from {len(cpu_dirs)} to "
+ f"{max_cpu_dirs} (use '-k processor.max_cpu_dirs=N' "
+ f"to change)."
+ )
+ cpu_dirs = sorted(cpu_dirs)[:max_cpu_dirs]
+
+ cdirs = other_dirs + cpu_dirs
+
self.add_copy_spec([
self.path_join('/sys/devices/system/cpu', cdir) for cdir in cdirs
])
--
2.55.0

View File

@ -4,8 +4,8 @@
Summary: A set of tools to gather troubleshooting information from a system
Name: sos
Version: 4.11.0
Release: 1%{?dist}
Version: 4.11.2
Release: 4%{?dist}
Group: Applications/System
Source0: https://github.com/sosreport/sos/archive/%{version}/sos-%{version}.tar.gz
Source1: sos-audit-%{auditversion}.tgz
@ -23,8 +23,13 @@ Recommends: python3-pyyaml
Conflicts: vdsm < 4.40
Obsoletes: sos-collector
Patch1: 0001-python3-walrus-operator-and-rhel8-changes-only.patch
Patch2: 0002-sosreport-binary.patch
Patch3: 0003-revert-PR4092.patch
Patch2: 0002-remove-unsupported-python36-plugins.patch
Patch3: 0003-sosreport-binary.patch
Patch4: 0004-revert-PR4092-and-PR4275.patch
Patch5: 0005-foreman-installer-Scrub-secrets-in-CLI-arg-dumps.patch
Patch6: 0006-foremanctl-valkey-PR4376.patch
Patch7: 0007-policies-Prefer-most-specific-policy-when-multiple-m.patch
Patch8: 0008-processor-Limit-sys-devices-system-cpu-cpu-subdirs-c.patch
%description
Sos is a set of tools that gathers information about system
@ -38,6 +43,11 @@ support technicians and developers.
%patch -P 1 -p1
%patch -P 2 -p1
%patch -P 3 -p1
%patch -P 4 -p1
%patch -P 5 -p1
%patch -P 6 -p1
%patch -P 7 -p1
%patch -P 8 -p1
%build
%py3_build
@ -110,6 +120,15 @@ of the system. Currently storage and filesystem commands are audited.
%license LICENSE
%changelog
* Wed Aug 05 2026 Jan Jansky <jjansky@redhat.com> = 4.11.2-4
- Update to 4.11.2-4
* Fri Jul 17 2026 Jan Jansky <jjansky@redhat.com> = 4.11.2-2
- Update to 4.11.2-2
* Wed Jul 15 2026 Jan Jansky <jjansky@redhat.com> = 4.11.2-1
- Update to 4.11.2-1
* Thu Apr 02 2026 Jan Jansky <jjansky@redhat.com> = 4.11.0-1
- Update to 4.11.0-1
Resolves: RHEL-157813