Add x86_64_v2 to _BASEARCH_MAP

Add link to AlmaLinux bugtracker
This commit is contained in:
Eduard Abdullin 2026-05-19 19:07:05 +00:00 committed by root
commit 03de0be3e6
6 changed files with 356 additions and 3 deletions

View File

@ -0,0 +1,98 @@
From a73cc59429846abe44b19f92dc1d05ebdcab4c7b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Thu, 19 Jun 2025 13:09:35 +0200
Subject: [PATCH] automatic: Expand email_to in command_email emitter to
individual arguments
Upstream commit: aa1ba2d1566198127518d0ccb38eaf5481b4649e
If /etc/dnf/automatic.conf has:
[emitters]
emit_via = command_email
[command_email]
email_to = root,test
a command incompatible with s-nail-14.9.25, a "mail" command
implementation, was executed:
execve("/usr/bin/mail", ["mail", "-Ssendwait", "-s", "Updates available on 'fedora-43'.", "-r", "root", "root test"], ...) = 0
The cause was that s-nail does not support multiple recipients in
a single argument.
This patch changes how "{email_to}" expands in command_format
formatting string. Now it expands into multiple, space separated arguments.
The new syntax is also accepted by mailx tool.
Implementation detail: A list of email_to recipients passed in
CommandEmitterMixIn does not inherit from "list" Python class or any
other iterator. It's libdnf.module.VectorString class generated by
Swig without. There the custom ShellQuotedLists formatting dictionary
needs to refer to libdnf.module.VectorString type and include "libdnf"
Python module explicitly.
A test will be added to ci-dnf-stack repository.
Resolve: #2241
Resolve: https://issues.redhat.com/browse/RHEL-94331
---
dnf/automatic/emitter.py | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/dnf/automatic/emitter.py b/dnf/automatic/emitter.py
index 1c8ff6bf8..ee1954296 100644
--- a/dnf/automatic/emitter.py
+++ b/dnf/automatic/emitter.py
@@ -22,6 +22,7 @@ from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
from dnf.i18n import _
+import libdnf
import logging
import dnf.pycomp
import smtplib
@@ -132,6 +133,20 @@ class EmailEmitter(Emitter):
logger.error(msg)
+class ShellQuotedLists(dict):
+ """
+ Dictionary which returns values quoted with dnf.pycomp.shlex_quote().
+ If a looked-up value is a list or libdnf.module.VectorString, it will
+ quote the list members and then concatenate them with a space and return
+ the resulting string.
+ """
+ def __getitem__(self, key):
+ value = super(ShellQuotedLists, self).__getitem__(key)
+ if isinstance(value, (list, libdnf.module.VectorString)):
+ return ' '.join(dnf.pycomp.shlex_quote(item) for item in value)
+ else:
+ return dnf.pycomp.shlex_quote(value)
+
class CommandEmitterMixIn(object):
"""
Executes a desired command, and pushes data into its stdin.
@@ -147,9 +162,7 @@ class CommandEmitterMixIn(object):
msg = self._prepare_msg()
# all strings passed to shell should be quoted to avoid accidental code
# execution
- quoted_msg = dict((key, dnf.pycomp.shlex_quote(val))
- for key, val in msg.items())
- command = command_fmt.format(**quoted_msg)
+ command = command_fmt.format_map(ShellQuotedLists(msg))
stdin_feed = stdin_fmt.format(**msg).encode('utf-8')
# Execute the command
@@ -177,7 +190,7 @@ class CommandEmailEmitter(CommandEmitterMixIn, EmailEmitter):
return {'subject': subject,
'body': body,
'email_from': self._conf.email_from,
- 'email_to': ' '.join(self._conf.email_to)}
+ 'email_to': self._conf.email_to}
class StdIoEmitter(Emitter):
--
2.52.0

View File

@ -0,0 +1,99 @@
From c930603f8a62c53862ffc6fee8800610f79d6a1b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Wed, 21 Jan 2026 17:38:02 +0100
Subject: [PATCH] rpmkeys: Ignore untrusted signatures if there is trusted one
Upstream commit: 00fef9ad0d761eccf8d86580e031f442af9cd8ef
With RPMv6 signatures, there can be multiple signatures attached to
a single package. If some signatures are made with an algorithm
disabled in a system-wide crypto policy (e.g. rsa4096 = "never" in
/etc/crypto-policies/back-ends/rpm-sequoia.config), but other
signatures are valid and trusted, so that the package is overall
correctly signed:
# rpmkeys -v -K ./foo-0-1.fc43.noarch.rpm; echo $?
./foo-0-1.fc43.noarch.rpm:
Header OpenPGP V4 EdDSA/SHA512 signature, key fingerprint: 111e11e164e61b51a1f62abe496099dbe2b145f3: OK
Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: 9b02d881fe4185e9ea52e78888cd83a4b5e56945: NOTTRUSTED
Header SHA256 digest: OK
Payload SHA256 digest: OK
0
DNF failed like this:
[...]
Is this ok [y/N]: y
Downloading Packages:
rsa-edsa 633 kB/s | 648 B 00:00
Importing GPG key 0xE2B145F3:
Userid : "test2 <test@localhost>"
Fingerprint: 111E 11E1 64E6 1B51 A1F6 2ABE 4960 99DB E2B1 45F3
From : /root/repos/rsa-edsa/edsa.pub
Is this ok [y/N]: y
Key imported successfully
rsa-edsa 1.6 MB/s | 1.6 kB 00:00
Importing GPG key 0xB5E56945:
Userid : ""
Fingerprint: 9B02 D881 FE41 85E9 EA52 E788 88CD 83A4 B5E5 6945
From : /root/repos/rsa-edsa/rsa.pub
Is this ok [y/N]: y
error: Certificate 88CD83A4B5E56945:
Policy rejects 88CD83A4B5E56945: Policy rejected asymmetric algorithm
Key import failed (code 2). Failing package is: foo-0-1.fc43.noarch
GPG Keys are configured as: file:///root/repos/rsa-edsa/edsa.pub, file:///root/repos/rsa-edsa/rsa.pub
Error: GPG check FAILED
The cause was that an output of "rpmkeys -v -K" tool executed indirectly by
dnf.rpm.miscutils.checkSig() was incorrectly parsed in _process_rpm_output()
function. That function assumed that only one signature can exist and
reported on any NOTTRUSTED record that the package is not trustfully
signed.
As a result, DNF attempted to (re)import all the signing keys. But
importing a key with the disabled algorithm failed and DNF errored.
This patch fixes parsing the rpmkeys output to ignore all untrusted
signatures if there is at least one signature trusted.
Resolve: https://issues.redhat.com/browse/RHEL-112730
---
dnf/rpm/miscutils.py | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/dnf/rpm/miscutils.py b/dnf/rpm/miscutils.py
index 1b85301da..61b0c2da5 100644
--- a/dnf/rpm/miscutils.py
+++ b/dnf/rpm/miscutils.py
@@ -39,7 +39,7 @@ def _process_rpm_output(data):
# last newline.
if len(data) < 3 or data[0] != b'-:' or data[-1]:
return 2
- seen_sig, missing_key, not_trusted, not_signed = False, False, False, False
+ trusted_sig, missing_key, not_trusted, not_signed = False, False, False, False
for i in data[1:-1]:
if b': BAD' in i:
return 2
@@ -49,12 +49,16 @@ def _process_rpm_output(data):
not_trusted = True
elif i.endswith(b': NOTFOUND'):
not_signed = True
+ # Some rpmkeys versions print Signature, some signature, accept both.
+ elif i.endswith(b': OK') and b'ignature,' in i:
+ trusted_sig = True
elif not i.endswith(b': OK'):
return 2
- if not_trusted:
- return 3
- elif missing_key:
+ if missing_key:
return 1
+ elif not trusted_sig and not_trusted:
+ # Do not report untrusted signatures if there is a trusted one
+ return 3
elif not_signed:
return 4
# we still check return code, so this is safe
--
2.53.0

View File

@ -0,0 +1,43 @@
From 93a1bdc09ad6ef345cf8cecc059b649ee2ccbf40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Mon, 26 Jan 2026 12:29:11 +0100
Subject: [PATCH 1/2] autoremove: warn and skip dangling protected dependencies
Requires new libdnf 0.76.0 API.
---
dnf/base.py | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/dnf/base.py b/dnf/base.py
index 7117dbe3..1d6ae6e2 100644
--- a/dnf/base.py
+++ b/dnf/base.py
@@ -2311,9 +2311,23 @@ class Base(object):
logger.warning(_('No packages marked for removal.'))
else:
- pkgs = self.sack.query()._unneeded(self.history.swdb,
+ unneeded_pkgs = self.sack.query()._unneeded(self.history.swdb,
debug_solver=self.conf.debug_solver)
- for pkg in pkgs:
+
+ protected = self.sack.query().installed().filterm(name=self.conf.protected_packages)
+ protected_found = False
+ for pkg in protected:
+ if pkg in unneeded_pkgs:
+ msg = _('Unneeded protected package: %s (and its dependencies) cannot be removed, '
+ 'either mark it as user-installed or change protected_packages configuration option.')
+ logger.warning(msg, pkg)
+ protected_found = True
+
+ if protected_found:
+ unneeded_pkgs = self.sack.query()._unneeded_extra_userinstalled(self.history.swdb, protected,
+ debug_solver=self.conf.debug_solver)
+
+ for pkg in unneeded_pkgs:
self.package_remove(pkg)
def remove(self, pkg_spec, reponame=None, forms=None):
--
2.53.0

View File

@ -0,0 +1,57 @@
From c1c66613c04a476a3b85582ae5214a3f9301d485 Mon Sep 17 00:00:00 2001
From: Evan Goode <mail@evangoo.de>
Date: Mon, 1 Dec 2025 13:40:26 -0500
Subject: [PATCH 1/2] bootc: unlock only if /usr is read-only
DNF should only run `ostree admin unlock --transient` if `/usr` is
actually read-only. `/usr` may be writable via OSTree's `root.transient =
true` even if the `ostree admin status` is not transient.
Resolves: https://redhat.atlassian.net/browse/RHEL-145780
---
dnf/cli/cli.py | 4 +++-
dnf/util.py | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
index d4bf811c1..07cc62cb1 100644
--- a/dnf/cli/cli.py
+++ b/dnf/cli/cli.py
@@ -225,6 +225,7 @@ class BaseCli(dnf.Base):
# Handle bootc transactions. `--transient` must be specified if
# /usr is not already writeable.
bootc_system = None
+ bootc_system_needs_unlock = False
if is_bootc_transaction:
if self.conf.persistence == "persist":
logger.info(_("Persistent transactions aren't supported on bootc systems."))
@@ -246,6 +247,7 @@ class BaseCli(dnf.Base):
logger.info(_("A transient overlay will be created on /usr that will be discarded on reboot. "
"Keep in mind that changes to /etc and /var will still persist, and packages "
"commonly modify these directories."))
+ bootc_system_needs_unlock = True
self._persistence = libdnf.transaction.TransactionPersistence_TRANSIENT
# Check whether the transaction modifies usr_drift_protected_paths
@@ -276,7 +278,7 @@ class BaseCli(dnf.Base):
if self.conf.assumeno or not self.output.userconfirm():
raise CliError(_("Operation aborted."))
- if bootc_system:
+ if bootc_system and bootc_system_needs_unlock:
bootc_system.make_writable()
else:
logger.info(_('Nothing to do.'))
diff --git a/dnf/util.py b/dnf/util.py
index eb987bb8a..e058bc187 100644
--- a/dnf/util.py
+++ b/dnf/util.py
@@ -749,4 +749,4 @@ class _BootcSystem:
# read-only. Set up a mount namespace for DNF.
self._set_up_mountns()
- assert os.access(self.usr, os.W_OK)
+ assert self.is_writable()
--
2.53.0

View File

@ -0,0 +1,37 @@
From 0b6ed2e107d1fe8744f45a771729cb0290413d67 Mon Sep 17 00:00:00 2001
From: Evan Goode <mail@evangoo.de>
Date: Fri, 20 Mar 2026 16:28:14 -0400
Subject: [PATCH 2/2] bootc: Call make_writable when
DeploymentUnlockedState.TRANSIENT
Fixes a bug in 1afe4328334f27b45b5c4599b6f1e8ac69d465e4.
bootc_system.make_writable should still be called even when the system
is already in DeploymentUnlockedState.TRANSIENT, since the DNF mount
namespace needs to be set up either way.
---
dnf/cli/cli.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
index 07cc62cb1..17cf9165e 100644
--- a/dnf/cli/cli.py
+++ b/dnf/cli/cli.py
@@ -235,6 +235,7 @@ class BaseCli(dnf.Base):
bootc_system = dnf.util._BootcSystem()
if not bootc_system.is_writable():
+ bootc_system_needs_unlock = True
if self.conf.persistence == "auto":
logger.info(_("This bootc system is configured to be read-only. Pass --transient to "
"perform this transaction in a transient overlay which will reset when "
@@ -247,7 +248,6 @@ class BaseCli(dnf.Base):
logger.info(_("A transient overlay will be created on /usr that will be discarded on reboot. "
"Keep in mind that changes to /etc and /var will still persist, and packages "
"commonly modify these directories."))
- bootc_system_needs_unlock = True
self._persistence = libdnf.transaction.TransactionPersistence_TRANSIENT
# Check whether the transaction modifies usr_drift_protected_paths
--
2.53.0

View File

@ -24,7 +24,7 @@
%endif
%if 0%{?rhel} == 10
%global hawkey_version 0.73.1-11
%global hawkey_version 0.73.1-14
%endif
# override dependencies for fedora 26
@ -72,7 +72,7 @@ It supports RPMs, modules and comps groups & environments.
Name: dnf
Version: 4.20.0
Release: 18%{?dist}.alma.1
Release: 22%{?dist}.alma.1
Summary: %{pkg_summary}
# For a breakdown of the licensing, see PACKAGE-LICENSING
License: GPL-2.0-or-later AND GPL-1.0-only
@ -114,6 +114,11 @@ Patch33: 0033-Obsolete-RHEL-9-only-multisig-DNF-plugin.patch
Patch34: 0034-Add-deprecation-warning-for-module-commands.patch
Patch35: 0035-Add-modularity-deprecation-warning-to-doc-pages.patch
Patch36: 0036-automatic-Fix-detecting-releasever_minor.patch
Patch37: 0037-automatic-Expand-email_to-in-command_email-emitter-t.patch
Patch38: 0038-rpmkeys-Ignore-untrusted-signatures-if-there-is-trus.patch
Patch39: 0039-autoremove-warn-and-skip-dangling-protected-dependen.patch
Patch40: 0040-bootc-unlock-only-if-usr-is-read-only.patch
Patch41: 0041-bootc-Call-make_writable-when-DeploymentUnlockedStat.patch
# AlmaLinux Patch
Patch1001: 0001-Add-link-to-AlmaLinux-bugtracker.patch
@ -479,10 +484,24 @@ popd
# bootc subpackage does not include any files
%changelog
* Tue Nov 11 2025 Eduard Abdullin <eabdullin@almalinux.org> - 4.20.0-18.alma.1
* Tue May 19 2026 Eduard Abdullin <eabdullin@almalinux.org> - 4.20.0-22.alma.1
- Add x86_64_v2 to _BASEARCH_MAP
- Add link to AlmaLinux bugtracker
* Wed Mar 25 2026 Evan Goode <egoode@redhat.com> - 4.20.0-22
- bootc: unlock only if /usr is read-only (RHEL-145780)
* Mon Feb 16 2026 Ales Matej <amatej@redhat.com> - 4.20.0-21
- autoremove: when a dangling protected dependency is found produce a warning
and skip it (RHEL-128445)
* Fri Jan 23 2026 Petr Pisar <ppisar@redhat.com> - 4.20.0-20
- Ignore untrusted signatures if there is trusted one (RHEL-112730)
* Fri Jan 09 2026 Petr Pisar <ppisar@redhat.com> - 4.20.0-19
- automatic: Expand email_to in command_email emitter to individual arguments
(RHEL-94331)
* Tue Jul 29 2025 Petr Pisar <ppisar@redhat.com> - 4.20.0-18
- Fix detecting releasever_minor in dnf-automatic (RHEL-106141)