From 2a546bf3cac687e8ace307bf2eae861ed3e71e3e Mon Sep 17 00:00:00 2001 From: Marek Blaha Date: Fri, 13 Dec 2024 15:03:47 +0100 Subject: [PATCH] Backport dnf-automatic patch to check config file availability Upstream patches: 13ecc3921fb1566c2af7b80d5cb515d8fc4e5ec9 130d6b91694a93a142be8c3767bfc711245dea1c Resolves: RHEL-68979 --- ...ic-check-availability-of-config-file.patch | 131 ++++++++++++++++++ dnf.spec | 7 +- 2 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 0011-Automatic-check-availability-of-config-file.patch diff --git a/0011-Automatic-check-availability-of-config-file.patch b/0011-Automatic-check-availability-of-config-file.patch new file mode 100644 index 0000000..b707da9 --- /dev/null +++ b/0011-Automatic-check-availability-of-config-file.patch @@ -0,0 +1,131 @@ +From 36389b63b12c2f6996772bd2bc7e98b6f3bacdf0 Mon Sep 17 00:00:00 2001 +From: Marek Blaha +Date: Thu, 17 Oct 2024 13:30:21 +0200 +Subject: [PATCH 1/2] automatic: Check availability of config file + +Upstream commit: 13ecc3921fb1566c2af7b80d5cb515d8fc4e5ec9 + +If a configuration file is explicitly specified on the command line, +ensure that it exists and is readable. If the file is not found, notify +the user immediately and terminate the process. + +This resolves issues where users may run dnf-automatic with unrecognized +positional arguments, such as `dnf-automatic install`. + +The most natural approach to handle a non-existing config file would be +by catching the exception thrown by the `read()` method of the +`libdnf.conf.ConfigParser` class. Unfortunately, the Python bindings +override the `read()` method at the SWIG level, causing it to suppress any +potentially raised IOError. +For details see this section of the commit +https://github.com/rpm-software-management/libdnf/commit/8f1fedf8551b72d6bc24018f5980714b3a103aeb + +def ConfigParser__newRead(self, filenames): + parsedFNames = [] + try: + if isinstance(filenames, str) or isinstance(filenames, unicode): + filenames = [filenames] + except NameError: + pass + for fname in filenames: + try: + self.readFileName(fname) + parsedFNames.append(fname) + except IOError: + pass + except Exception as e: + raise RuntimeError("Parsing file '%s' failed: %s" % (fname, str(e))) + return parsedFNames +ConfigParser.read = ConfigParser__newRead + +Resolves: https://issues.redhat.com/browse/RHEL-68979 +--- + dnf/automatic/main.py | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py +index 243e3015..21aa82b7 100644 +--- a/dnf/automatic/main.py ++++ b/dnf/automatic/main.py +@@ -74,7 +74,7 @@ def build_emitters(conf): + + def parse_arguments(args): + parser = argparse.ArgumentParser() +- parser.add_argument('conf_path', nargs='?', default=dnf.const.CONF_AUTOMATIC_FILENAME) ++ parser.add_argument('conf_path', nargs='?') + parser.add_argument('--timer', action='store_true') + parser.add_argument('--installupdates', dest='installupdates', action='store_true') + parser.add_argument('--downloadupdates', dest='downloadupdates', action='store_true') +@@ -89,7 +89,17 @@ def parse_arguments(args): + class AutomaticConfig(object): + def __init__(self, filename=None, downloadupdates=None, + installupdates=None): +- if not filename: ++ if filename: ++ # Specific config file was explicitely requested. Check that it exists ++ # and is readable. ++ if os.access(filename, os.F_OK): ++ if not os.access(filename, os.R_OK): ++ raise dnf.exceptions.Error( ++ "Configuration file \"{}\" is not readable.".format(filename)) ++ else: ++ raise dnf.exceptions.Error( ++ "Configuration file \"{}\" not found.".format(filename)) ++ else: + filename = dnf.const.CONF_AUTOMATIC_FILENAME + self.commands = CommandsConfig() + self.email = EmailConfig() +@@ -302,11 +312,12 @@ def wait_for_network(repos, timeout): + + def main(args): + (opts, parser) = parse_arguments(args) ++ conf = None ++ emitters = None + + try: + conf = AutomaticConfig(opts.conf_path, opts.downloadupdates, + opts.installupdates) +- emitters = None + with dnf.Base() as base: + cli = dnf.cli.Cli(base) + cli._read_conf_file() +@@ -371,7 +382,7 @@ def main(args): + raise dnf.exceptions.Error('reboot command returned nonzero exit code: %d', exit_code) + except dnf.exceptions.Error as exc: + logger.error(_('Error: %s'), ucd(exc)) +- if conf.emitters.send_error_messages and emitters != None: ++ if conf is not None and conf.emitters.send_error_messages and emitters is not None: + emitters.notify_error(_('Error: %s') % str(exc)) + emitters.commit() + return 1 +-- +2.47.1 + + +From bfc4d7ae2d9a567aaf656388c8b914b7a03db39d Mon Sep 17 00:00:00 2001 +From: Marek Blaha +Date: Thu, 12 Dec 2024 08:09:48 +0100 +Subject: [PATCH 2/2] automatic: Fix incorrect Error class instantiation + +dnf.exceptions.Error class constructor accepts only one argument - error +message. +--- + dnf/automatic/main.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py +index 21aa82b7..1a1e1cf0 100644 +--- a/dnf/automatic/main.py ++++ b/dnf/automatic/main.py +@@ -379,7 +379,7 @@ def main(args): + (conf.commands.reboot == 'when-needed' and base.reboot_needed())): + exit_code = os.waitstatus_to_exitcode(os.system(conf.commands.reboot_command)) + if exit_code != 0: +- raise dnf.exceptions.Error('reboot command returned nonzero exit code: %d', exit_code) ++ raise dnf.exceptions.Error('reboot command returned nonzero exit code: %d' % exit_code) + except dnf.exceptions.Error as exc: + logger.error(_('Error: %s'), ucd(exc)) + if conf is not None and conf.emitters.send_error_messages and emitters is not None: +-- +2.47.1 + diff --git a/dnf.spec b/dnf.spec index b53f8a4..bf77e00 100644 --- a/dnf.spec +++ b/dnf.spec @@ -68,7 +68,7 @@ It supports RPMs, modules and comps groups & environments. Name: dnf Version: 4.20.0 -Release: 9%{?dist} +Release: 10%{?dist} Summary: %{pkg_summary} # For a breakdown of the licensing, see PACKAGE-LICENSING License: GPL-2.0-or-later AND GPL-1.0-only @@ -84,6 +84,8 @@ Patch7: 0007-Update-ostree-bootc-host-system-check.patch Patch8: 0008-Update-bootc-hosts-message-to-point-to-bootc-help.patch Patch9: 0009-Allow-installroot-on-read-only-bootc-system.patch Patch10: 0010-Allow-downloadonly-on-read-only-bootc-system.patch +Patch11: 0011-Automatic-check-availability-of-config-file.patch + BuildArch: noarch BuildRequires: cmake BuildRequires: gettext @@ -424,6 +426,9 @@ popd %{python3_sitelib}/%{name}/automatic/ %changelog +* Fri Dec 13 2024 Marek Blaha - 4.20.0-10 +- automatic: Check availability of config file + * Tue Oct 29 2024 Troy Dawson - 4.20.0-9 - Bump release for October 2024 mass rebuild: Resolves: RHEL-64018