From 0f497a26a8974a0d157942a137edd954f0387309 Mon Sep 17 00:00:00 2001
From: Koichiro Iwao
Date: Mon, 2 Mar 2026 02:30:41 +0000
Subject: [PATCH 1/2] Add a pseudo subpackage -modules-extra-matched
to resolve dependency issue
(cherry picked from commit 52258891d45ecc8f3d68adb8982522da2f3db1c4)
---
SPECS/raspberrypi2.spec | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/SPECS/raspberrypi2.spec b/SPECS/raspberrypi2.spec
index b574701..5332e12 100644
--- a/SPECS/raspberrypi2.spec
+++ b/SPECS/raspberrypi2.spec
@@ -11,7 +11,7 @@ ExclusiveArch: aarch64
%define local_version v8
%define bcmmodel 2711
-%define extra_version 1
+%define extra_version 2
# This originally implies Kernel 4.x for RPi 2 and is not appropriate now.
# Be careful to change this not to disturb the seamless package update.
@@ -141,6 +141,20 @@ AutoProv: yes
%description kernel%{?ksuffix}-modules-extra
This package provides pseudo dependency for the packages that depends on regular
kernel-modules-extra packages.
+
+%package kernel%{?ksuffix}-modules-extra-matched
+Summary: Pseudo package for extra kernel modules
+Group: System Environment/Kernel
+Provides: kernel-modules-extra-matched = %{version}-%{release}
+Provides: kernel-modules-extra-matched-uname-r = %{version}-%{release}
+Provides: installonlypkg(kernel-module)
+Obsoletes: kernel-modules-extra-matched < %{version}-%{release}
+Requires: %{name}-kernel%{?ksuffix} = %{version}-%{release}
+AutoReq: no
+AutoProv: yes
+%description kernel%{?ksuffix}-modules-extra-matched
+This package provides pseudo dependency for the packages that depends on regular
+kernel-modules-extra-matched packages.
%endif
%if %{with_tools}
@@ -462,6 +476,10 @@ cp $(ls -1 /boot/config-kernel-*-*|sort -V|tail -1) /boot/config-kernel.inc
%files kernel%{?ksuffix}-modules-extra
# empty package
%defattr(-,root,root)
+
+%files kernel%{?ksuffix}-modules-extra-matched
+# empty package
+%defattr(-,root,root)
%endif
%endif
@@ -516,6 +534,9 @@ cp $(ls -1 /boot/config-kernel-*-*|sort -V|tail -1) /boot/config-kernel.inc
%endif
%changelog
+* Mon Mar 02 2026 Koichiro Iwao - 6.12.47-20250916.v8.2
+- Add a pseudo subpackage -modules-extra-matched to resolve dependency issue
+
* Fri Oct 03 2025 Koichiro Iwao - 6.12.47-20250916.v8.1
- Update kernel to v6.12.47 stable_20250916
- Make it buildable on Fedora
From b4df67967b82af31431cda1d62a7e83ab9439c8f Mon Sep 17 00:00:00 2001
From: Koichiro Iwao
Date: Thu, 30 Apr 2026 02:10:59 +0000
Subject: [PATCH 2/2] Apply fix for CVE-2026-31431 Copy Fail
(cherry picked from commit b9bc6b4858457a33756e73befe627cb9c507b402)
---
...ead-Revert-to-operating-out-of-place.patch | 310 ++++++++++++++++++
SPECS/raspberrypi2.spec | 9 +-
2 files changed, 318 insertions(+), 1 deletion(-)
create mode 100644 SOURCES/1100-crypto-algif_aead-Revert-to-operating-out-of-place.patch
diff --git a/SOURCES/1100-crypto-algif_aead-Revert-to-operating-out-of-place.patch b/SOURCES/1100-crypto-algif_aead-Revert-to-operating-out-of-place.patch
new file mode 100644
index 0000000..b50d4be
--- /dev/null
+++ b/SOURCES/1100-crypto-algif_aead-Revert-to-operating-out-of-place.patch
@@ -0,0 +1,310 @@
+From a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5 Mon Sep 17 00:00:00 2001
+From: Herbert Xu
+Date: Thu, 26 Mar 2026 15:30:20 +0900
+Subject: [PATCH] crypto: algif_aead - Revert to operating out-of-place
+
+This mostly reverts commit 72548b093ee3 except for the copying of
+the associated data.
+
+There is no benefit in operating in-place in algif_aead since the
+source and destination come from different mappings. Get rid of
+all the complexity added for in-place operation and just copy the
+AD directly.
+
+Backported to kernel-6.12.0-124.52.1.el10_1: this tree pre-dates upstream's
+memcpy_sglist() helper, so the AAD copy keeps using
+crypto_aead_copy_sgl(null_tfm, ...). The function signatures of
+af_alg_count_tsgl() and af_alg_pull_tsgl() are reverted to drop the
+offset parameters as in upstream.
+
+Fixes: 72548b093ee3 ("crypto: algif_aead - copy AAD from src to dst")
+Reported-by: Taeyang Lee <0wn@theori.io>
+Signed-off-by: Herbert Xu
+---
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -635,15 +635,13 @@
+ /**
+ * af_alg_count_tsgl - Count number of TX SG entries
+ *
+- * The counting starts from the beginning of the SGL to @bytes. If
+- * an @offset is provided, the counting of the SG entries starts at the @offset.
++ * The counting starts from the beginning of the SGL to @bytes.
+ *
+ * @sk: socket of connection to user space
+ * @bytes: Count the number of SG entries holding given number of bytes.
+- * @offset: Start the counting of SG entries from the given offset.
+ * Return: Number of TX SG entries found given the constraints
+ */
+-unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset)
++unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes)
+ {
+ const struct alg_sock *ask = alg_sk(sk);
+ const struct af_alg_ctx *ctx = ask->private;
+@@ -658,25 +656,11 @@
+ const struct scatterlist *sg = sgl->sg;
+
+ for (i = 0; i < sgl->cur; i++) {
+- size_t bytes_count;
+-
+- /* Skip offset */
+- if (offset >= sg[i].length) {
+- offset -= sg[i].length;
+- bytes -= sg[i].length;
+- continue;
+- }
+-
+- bytes_count = sg[i].length - offset;
+-
+- offset = 0;
+ sgl_count++;
+-
+- /* If we have seen requested number of bytes, stop */
+- if (bytes_count >= bytes)
++ if (sg[i].length >= bytes)
+ return sgl_count;
+
+- bytes -= bytes_count;
++ bytes -= sg[i].length;
+ }
+ }
+
+@@ -688,19 +672,14 @@
+ * af_alg_pull_tsgl - Release the specified buffers from TX SGL
+ *
+ * If @dst is non-null, reassign the pages to @dst. The caller must release
+- * the pages. If @dst_offset is given only reassign the pages to @dst starting
+- * at the @dst_offset (byte). The caller must ensure that @dst is large
+- * enough (e.g. by using af_alg_count_tsgl with the same offset).
++ * the pages.
+ *
+ * @sk: socket of connection to user space
+ * @used: Number of bytes to pull from TX SGL
+ * @dst: If non-NULL, buffer is reassigned to dst SGL instead of releasing. The
+ * caller must release the buffers in dst.
+- * @dst_offset: Reassign the TX SGL from given offset. All buffers before
+- * reaching the offset is released.
+ */
+-void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
+- size_t dst_offset)
++void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst)
+ {
+ struct alg_sock *ask = alg_sk(sk);
+ struct af_alg_ctx *ctx = ask->private;
+@@ -725,18 +704,10 @@
+ * SG entries in dst.
+ */
+ if (dst) {
+- if (dst_offset >= plen) {
+- /* discard page before offset */
+- dst_offset -= plen;
+- } else {
+- /* reassign page to dst after offset */
+- get_page(page);
+- sg_set_page(dst + j, page,
+- plen - dst_offset,
+- sg[i].offset + dst_offset);
+- dst_offset = 0;
+- j++;
+- }
++ /* reassign page to dst after offset */
++ get_page(page);
++ sg_set_page(dst + j, page, plen, sg[i].offset);
++ j++;
+ }
+
+ sg[i].length -= plen;
+--- a/crypto/algif_aead.c
++++ b/crypto/algif_aead.c
+@@ -96,9 +96,8 @@
+ struct aead_tfm *aeadc = pask->private;
+ struct crypto_aead *tfm = aeadc->aead;
+ struct crypto_sync_skcipher *null_tfm = aeadc->null_tfm;
+- unsigned int i, as = crypto_aead_authsize(tfm);
++ unsigned int as = crypto_aead_authsize(tfm);
+ struct af_alg_async_req *areq;
+- struct af_alg_tsgl *tsgl, *tmp;
+ struct scatterlist *rsgl_src, *tsgl_src = NULL;
+ int err = 0;
+ size_t used = 0; /* [in] TX bufs to be en/decrypted */
+@@ -178,23 +177,24 @@
+ outlen -= less;
+ }
+
++ /*
++ * Create a per request TX SGL for this request which tracks the
++ * SG entries from the global TX SGL.
++ */
+ processed = used + ctx->aead_assoclen;
+- list_for_each_entry_safe(tsgl, tmp, &ctx->tsgl_list, list) {
+- for (i = 0; i < tsgl->cur; i++) {
+- struct scatterlist *process_sg = tsgl->sg + i;
+-
+- if (!(process_sg->length) || !sg_page(process_sg))
+- continue;
+- tsgl_src = process_sg;
+- break;
+- }
+- if (tsgl_src)
+- break;
+- }
+- if (processed && !tsgl_src) {
+- err = -EFAULT;
++ areq->tsgl_entries = af_alg_count_tsgl(sk, processed);
++ if (!areq->tsgl_entries)
++ areq->tsgl_entries = 1;
++ areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
++ areq->tsgl_entries),
++ GFP_KERNEL);
++ if (!areq->tsgl) {
++ err = -ENOMEM;
+ goto free;
+ }
++ sg_init_table(areq->tsgl, areq->tsgl_entries);
++ af_alg_pull_tsgl(sk, processed, areq->tsgl);
++ tsgl_src = areq->tsgl;
+
+ /*
+ * Copy of AAD from source to destination
+@@ -203,83 +203,18 @@
+ * when user space uses an in-place cipher operation, the kernel
+ * will copy the data as it does not see whether such in-place operation
+ * is initiated.
+- *
+- * To ensure efficiency, the following implementation ensure that the
+- * ciphers are invoked to perform a crypto operation in-place. This
+- * is achieved by memory management specified as follows.
+ */
+
+- /* Use the RX SGL as source (and destination) for crypto op. */
++ /* Use the RX SGL as destination for crypto op. */
+ rsgl_src = areq->first_rsgl.sgl.sgt.sgl;
+
+- if (ctx->enc) {
+- /*
+- * Encryption operation - The in-place cipher operation is
+- * achieved by the following operation:
+- *
+- * TX SGL: AAD || PT
+- * | |
+- * | copy |
+- * v v
+- * RX SGL: AAD || PT || Tag
+- */
+- err = crypto_aead_copy_sgl(null_tfm, tsgl_src,
+- areq->first_rsgl.sgl.sgt.sgl,
+- processed);
+- if (err)
+- goto free;
+- af_alg_pull_tsgl(sk, processed, NULL, 0);
+- } else {
+- /*
+- * Decryption operation - To achieve an in-place cipher
+- * operation, the following SGL structure is used:
+- *
+- * TX SGL: AAD || CT || Tag
+- * | | ^
+- * | copy | | Create SGL link.
+- * v v |
+- * RX SGL: AAD || CT ----+
+- */
+-
+- /* Copy AAD || CT to RX SGL buffer for in-place operation. */
+- err = crypto_aead_copy_sgl(null_tfm, tsgl_src,
+- areq->first_rsgl.sgl.sgt.sgl,
+- outlen);
+- if (err)
+- goto free;
+-
+- /* Create TX SGL for tag and chain it to RX SGL. */
+- areq->tsgl_entries = af_alg_count_tsgl(sk, processed,
+- processed - as);
+- if (!areq->tsgl_entries)
+- areq->tsgl_entries = 1;
+- areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
+- areq->tsgl_entries),
+- GFP_KERNEL);
+- if (!areq->tsgl) {
+- err = -ENOMEM;
+- goto free;
+- }
+- sg_init_table(areq->tsgl, areq->tsgl_entries);
+-
+- /* Release TX SGL, except for tag data and reassign tag data. */
+- af_alg_pull_tsgl(sk, processed, areq->tsgl, processed - as);
+-
+- /* chain the areq TX SGL holding the tag with RX SGL */
+- if (usedpages) {
+- /* RX SGL present */
+- struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl;
+- struct scatterlist *sg = sgl_prev->sgt.sgl;
+-
+- sg_unmark_end(sg + sgl_prev->sgt.nents - 1);
+- sg_chain(sg, sgl_prev->sgt.nents + 1, areq->tsgl);
+- } else
+- /* no RX SGL present (e.g. authentication only) */
+- rsgl_src = areq->tsgl;
+- }
++ err = crypto_aead_copy_sgl(null_tfm, tsgl_src, rsgl_src,
++ ctx->aead_assoclen);
++ if (err)
++ goto free;
+
+ /* Initialize the crypto operation */
+- aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src,
++ aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src,
+ areq->first_rsgl.sgl.sgt.sgl, used, ctx->iv);
+ aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen);
+ aead_request_set_tfm(&areq->cra_u.aead_req, tfm);
+@@ -514,7 +449,7 @@
+ struct crypto_aead *tfm = aeadc->aead;
+ unsigned int ivlen = crypto_aead_ivsize(tfm);
+
+- af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
++ af_alg_pull_tsgl(sk, ctx->used, NULL);
+ sock_kzfree_s(sk, ctx->iv, ivlen);
+ sock_kfree_s(sk, ctx, ctx->len);
+ af_alg_release_parent(sk);
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -138,7 +138,7 @@
+ * Create a per request TX SGL for this request which tracks the
+ * SG entries from the global TX SGL.
+ */
+- areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0);
++ areq->tsgl_entries = af_alg_count_tsgl(sk, len);
+ if (!areq->tsgl_entries)
+ areq->tsgl_entries = 1;
+ areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
+@@ -149,7 +149,7 @@
+ goto free;
+ }
+ sg_init_table(areq->tsgl, areq->tsgl_entries);
+- af_alg_pull_tsgl(sk, len, areq->tsgl, 0);
++ af_alg_pull_tsgl(sk, len, areq->tsgl);
+
+ /* Initialize the crypto operation */
+ skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
+@@ -363,7 +363,7 @@
+ struct alg_sock *pask = alg_sk(psk);
+ struct crypto_skcipher *tfm = pask->private;
+
+- af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
++ af_alg_pull_tsgl(sk, ctx->used, NULL);
+ sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
+ if (ctx->state)
+ sock_kzfree_s(sk, ctx->state, crypto_skcipher_statesize(tfm));
+--- a/include/crypto/if_alg.h
++++ b/include/crypto/if_alg.h
+@@ -228,9 +228,8 @@
+ return PAGE_SIZE <= af_alg_rcvbuf(sk);
+ }
+
+-unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset);
+-void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
+- size_t dst_offset);
++unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes);
++void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst);
+ void af_alg_wmem_wakeup(struct sock *sk);
+ int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min);
+ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
diff --git a/SPECS/raspberrypi2.spec b/SPECS/raspberrypi2.spec
index 5332e12..bd30ce6 100644
--- a/SPECS/raspberrypi2.spec
+++ b/SPECS/raspberrypi2.spec
@@ -11,7 +11,7 @@ ExclusiveArch: aarch64
%define local_version v8
%define bcmmodel 2711
-%define extra_version 2
+%define extra_version 3
# This originally implies Kernel 4.x for RPi 2 and is not appropriate now.
# Be careful to change this not to disturb the seamless package update.
@@ -51,6 +51,9 @@ Patch101: config_2712.patch
Source2000: cpupower.service
Source2001: cpupower.config
Source2002: kvm_stat.logrotate
+# AlmaLinux patches
+## CVE-2026-31431
+Patch1100: 1100-crypto-algif_aead-Revert-to-operating-out-of-place.patch
BuildRequires: kmod, patch, bash, coreutils, tar
BuildRequires: bzip2, xz, findutils, gzip, m4, perl, perl-Carp, make, diffutils, gawk
@@ -230,6 +233,7 @@ glibc package.
%setup -q -n linux-stable_%{version_tag}
%patch -P 100 -p1
%patch -P 101 -p1
+%patch -P 1100 -p1
perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = -%{release}/" Makefile
perl -p -i -e "s/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=/" arch/%{Arch}/configs/bcm2711_defconfig
perl -p -i -e "s/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=/" arch/%{Arch}/configs/bcm2712_defconfig
@@ -534,6 +538,9 @@ cp $(ls -1 /boot/config-kernel-*-*|sort -V|tail -1) /boot/config-kernel.inc
%endif
%changelog
+* Thu Apr 30 2026 Koichiro Iwao - 6.12.47-20250916.v8.3
+- Apply fix for CVE-2026-31431 Copy Fail
+
* Mon Mar 02 2026 Koichiro Iwao - 6.12.47-20250916.v8.2
- Add a pseudo subpackage -modules-extra-matched to resolve dependency issue