* [PATCH] rhashtable: Use irq work for shrinking
From: Herbert Xu @ 2026-06-04 2:17 UTC (permalink / raw)
To: Mykyta Yatsenko
Cc: bot+bpf-ci, bpf, ast, andrii, daniel, kafai, kernel-team, eddyz87,
memxor, yatsenko, martin.lau, yonghong.song, clm, ihor.solodrai,
Tejun Heo, Linux Crypto Mailing List
In-Reply-To: <3960ffc3-78f3-46da-baaf-ce72b6495698@gmail.com>
On Wed, Jun 03, 2026 at 02:08:25PM +0100, Mykyta Yatsenko wrote:
>
> For v7 I'm dropping automatic_shrinking, because it adds a risk of
> calling schedule_work() on element deletion path (__rhashtable_remove_fast_one())
> when hashtable size drops below 30% of the capacity.
Now that expansion uses irq work I think shrinking should switch
to that as well.
---8<---
Use irq work for automatic shrinking so that this may be called
in NMI context.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index ef5230cece36..0693bce6f890 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -1117,7 +1117,7 @@ static __always_inline int __rhashtable_remove_fast_one(
atomic_dec(&ht->nelems);
if (unlikely(ht->p.automatic_shrinking &&
rht_shrink_below_30(ht, tbl)))
- schedule_work(&ht->run_work);
+ irq_work_queue(&ht->run_irq_work);
err = 0;
}
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related
* Re: [PATCH v3] crypto/algapi: fix refcount leak in crypto_register_alg()
From: Herbert Xu @ 2026-06-04 2:01 UTC (permalink / raw)
To: Wentao Liang; +Cc: davem, linux-crypto, linux-kernel, stable
In-Reply-To: <20260603082140.3719314-1-vulab@iscas.ac.cn>
On Wed, Jun 03, 2026 at 08:21:40AM +0000, Wentao Liang wrote:
> When crypto_register_alg() calls crypto_check_alg() successfully,
> the algorithm's refcount is set to one. If the subsequent handling
The algorithm wasn't registered anywhere and the refcount isn't used.
I fail to see the point of your patch.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH] crypto: omap - use min3 to simplify omap_crypto_copy_data
From: Thorsten Blum @ 2026-06-04 0:10 UTC (permalink / raw)
To: Herbert Xu, David S. Miller; +Cc: Thorsten Blum, linux-crypto, linux-kernel
Replace two consecutive min() calls with min3() to simplify the code.
Change the function parameters and local variables from int to size_t
since these represent unsigned values and to prevent a signedness error.
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
drivers/crypto/omap-crypto.c | 12 ++++++------
drivers/crypto/omap-crypto.h | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/crypto/omap-crypto.c b/drivers/crypto/omap-crypto.c
index 0345c9383d50..c0400fbe313e 100644
--- a/drivers/crypto/omap-crypto.c
+++ b/drivers/crypto/omap-crypto.c
@@ -156,11 +157,11 @@ EXPORT_SYMBOL_GPL(omap_crypto_align_sg);
static void omap_crypto_copy_data(struct scatterlist *src,
struct scatterlist *dst,
- int offset, int len)
+ size_t offset, size_t len)
{
- int amt;
+ size_t amt;
void *srcb, *dstb;
- int srco = 0, dsto = offset;
+ size_t srco = 0, dsto = offset;
while (src && dst && len) {
if (srco >= src->length) {
@@ -175,8 +176,7 @@ static void omap_crypto_copy_data(struct scatterlist *src,
continue;
}
- amt = min(src->length - srco, dst->length - dsto);
- amt = min(len, amt);
+ amt = min3(src->length - srco, dst->length - dsto, len);
srcb = kmap_atomic(sg_page(src)) + srco + src->offset;
dstb = kmap_atomic(sg_page(dst)) + dsto + dst->offset;
@@ -195,7 +195,7 @@ static void omap_crypto_copy_data(struct scatterlist *src,
}
void omap_crypto_cleanup(struct scatterlist *sg, struct scatterlist *orig,
- int offset, int len, u8 flags_shift,
+ size_t offset, size_t len, u8 flags_shift,
unsigned long flags)
{
void *buf;
diff --git a/drivers/crypto/omap-crypto.h b/drivers/crypto/omap-crypto.h
index 506ccde6f380..436f45f3bb7d 100644
--- a/drivers/crypto/omap-crypto.h
+++ b/drivers/crypto/omap-crypto.h
@@ -28,7 +28,7 @@ int omap_crypto_align_sg(struct scatterlist **sg, int total, int bs,
struct scatterlist *new_sg, u16 flags,
u8 flags_shift, unsigned long *dd_flags);
void omap_crypto_cleanup(struct scatterlist *sg, struct scatterlist *orig,
- int offset, int len, u8 flags_shift,
+ size_t offset, size_t len, u8 flags_shift,
unsigned long flags);
#endif
^ permalink raw reply related
* [PATCH] crypto: talitos: replace in_be32/out_be32 with ioread32be/iowrite32be
From: Rosen Penev @ 2026-06-03 19:33 UTC (permalink / raw)
To: linux-crypto; +Cc: Herbert Xu, David S. Miller, open list
Convert ppc4xx-specific in_be32/out_be32 and the setbits32/clrbits32
macros to the portable ioread32be/iowrite32be helpers.
Add HAS_IOMEM dependency as these accessors need it.
Add COMPILE_TEST for extra compile coverage.
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/crypto/Kconfig | 3 +-
drivers/crypto/talitos.c | 379 ++++++++++++++++++++-------------------
2 files changed, 192 insertions(+), 190 deletions(-)
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 3449b3c9c6ad..d5d2a663d171 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -262,7 +262,8 @@ config CRYPTO_DEV_TALITOS
select CRYPTO_HASH
select CRYPTO_LIB_DES
select HW_RANDOM
- depends on FSL_SOC
+ depends on FSL_SOC || COMPILE_TEST
+ depends on HAS_IOMEM
help
Say 'Y' here to use the Freescale Security Engine (SEC)
to offload cryptographic algorithm computation.
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 584508963241..583bfbe118b5 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -143,18 +143,20 @@ static int reset_channel(struct device *dev, int ch)
bool is_sec1 = has_ftr_sec1(priv);
if (is_sec1) {
- setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
- TALITOS1_CCCR_LO_RESET);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) |
+ (TALITOS1_CCCR_LO_RESET),
+ priv->chan[ch].reg + TALITOS_CCCR_LO);
- while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
- TALITOS1_CCCR_LO_RESET) && --timeout)
+ while ((ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) &
+ TALITOS1_CCCR_LO_RESET) &&
+ --timeout)
cpu_relax();
} else {
- setbits32(priv->chan[ch].reg + TALITOS_CCCR,
- TALITOS2_CCCR_RESET);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR) | (TALITOS2_CCCR_RESET),
+ priv->chan[ch].reg + TALITOS_CCCR);
- while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
- TALITOS2_CCCR_RESET) && --timeout)
+ while ((ioread32be(priv->chan[ch].reg + TALITOS_CCCR) & TALITOS2_CCCR_RESET) &&
+ --timeout)
cpu_relax();
}
@@ -164,17 +166,19 @@ static int reset_channel(struct device *dev, int ch)
}
/* set 36-bit addressing, done writeback enable and done IRQ enable */
- setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
- TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) |
+ (TALITOS_CCCR_LO_EAE | TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE),
+ priv->chan[ch].reg + TALITOS_CCCR_LO);
/* enable chaining descriptors */
if (is_sec1)
- setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
- TALITOS_CCCR_LO_NE);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) | (TALITOS_CCCR_LO_NE),
+ priv->chan[ch].reg + TALITOS_CCCR_LO);
/* and ICCR writeback, if available */
if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
- setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
- TALITOS_CCCR_LO_IWSE);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) |
+ (TALITOS_CCCR_LO_IWSE),
+ priv->chan[ch].reg + TALITOS_CCCR_LO);
return 0;
}
@@ -186,15 +190,14 @@ static int reset_device(struct device *dev)
bool is_sec1 = has_ftr_sec1(priv);
u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
- setbits32(priv->reg + TALITOS_MCR, mcr);
+ iowrite32be(ioread32be(priv->reg + TALITOS_MCR) | (mcr), priv->reg + TALITOS_MCR);
- while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
- && --timeout)
+ while ((ioread32be(priv->reg + TALITOS_MCR) & mcr) && --timeout)
cpu_relax();
if (priv->irq[1]) {
mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
- setbits32(priv->reg + TALITOS_MCR, mcr);
+ iowrite32be(ioread32be(priv->reg + TALITOS_MCR) | (mcr), priv->reg + TALITOS_MCR);
}
if (timeout == 0) {
@@ -237,19 +240,25 @@ static int init_device(struct device *dev)
/* enable channel done and error interrupts */
if (is_sec1) {
- clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
- clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) & ~(TALITOS1_IMR_INIT),
+ priv->reg + TALITOS_IMR);
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR_LO) & ~(TALITOS1_IMR_LO_INIT),
+ priv->reg + TALITOS_IMR_LO);
/* disable parity error check in DEU (erroneous? test vect.) */
- setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
+ iowrite32be(ioread32be(priv->reg_deu + TALITOS_EUICR) | (TALITOS1_DEUICR_KPE),
+ priv->reg_deu + TALITOS_EUICR);
} else {
- setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
- setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) | (TALITOS2_IMR_INIT),
+ priv->reg + TALITOS_IMR);
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR_LO) | (TALITOS2_IMR_LO_INIT),
+ priv->reg + TALITOS_IMR_LO);
}
/* disable integrity check error interrupts (use writeback instead) */
if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
- setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
- TALITOS_MDEUICR_LO_ICE);
+ iowrite32be(ioread32be(priv->reg_mdeu + TALITOS_EUICR_LO) |
+ (TALITOS_MDEUICR_LO_ICE),
+ priv->reg_mdeu + TALITOS_EUICR_LO);
return 0;
}
@@ -342,10 +351,8 @@ static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
/* GO! */
wmb();
- out_be32(priv->chan[ch].reg + TALITOS_FF,
- upper_32_bits(request->dma_desc));
- out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
- lower_32_bits(request->dma_desc));
+ iowrite32be(upper_32_bits(request->dma_desc), priv->chan[ch].reg + TALITOS_FF);
+ iowrite32be(lower_32_bits(request->dma_desc), priv->chan[ch].reg + TALITOS_FF_LO);
spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
@@ -463,56 +470,60 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
/*
* process completed requests for channels that have done status
*/
-#define DEF_TALITOS1_DONE(name, ch_done_mask) \
-static void talitos1_done_##name(unsigned long data) \
-{ \
- struct device *dev = (struct device *)data; \
- struct talitos_private *priv = dev_get_drvdata(dev); \
- unsigned long flags; \
- \
- if (ch_done_mask & 0x10000000) \
- flush_channel(dev, 0, 0, 0); \
- if (ch_done_mask & 0x40000000) \
- flush_channel(dev, 1, 0, 0); \
- if (ch_done_mask & 0x00010000) \
- flush_channel(dev, 2, 0, 0); \
- if (ch_done_mask & 0x00040000) \
- flush_channel(dev, 3, 0, 0); \
- \
- /* At this point, all completed channels have been processed */ \
- /* Unmask done interrupts for channels completed later on. */ \
- spin_lock_irqsave(&priv->reg_lock, flags); \
- clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
- clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
-}
+#define DEF_TALITOS1_DONE(name, ch_done_mask) \
+ static void talitos1_done_##name(unsigned long data) \
+ { \
+ struct device *dev = (struct device *)data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ unsigned long flags; \
+ \
+ if (ch_done_mask & 0x10000000) \
+ flush_channel(dev, 0, 0, 0); \
+ if (ch_done_mask & 0x40000000) \
+ flush_channel(dev, 1, 0, 0); \
+ if (ch_done_mask & 0x00010000) \
+ flush_channel(dev, 2, 0, 0); \
+ if (ch_done_mask & 0x00040000) \
+ flush_channel(dev, 3, 0, 0); \
+ \
+ /* At this point, all completed channels have been processed */ \
+ /* Unmask done interrupts for channels completed later on. */ \
+ spin_lock_irqsave(&priv->reg_lock, flags); \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) & ~(ch_done_mask), \
+ priv->reg + TALITOS_IMR); \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR_LO) & ~(TALITOS1_IMR_LO_INIT), \
+ priv->reg + TALITOS_IMR_LO); \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ }
DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
-#define DEF_TALITOS2_DONE(name, ch_done_mask) \
-static void talitos2_done_##name(unsigned long data) \
-{ \
- struct device *dev = (struct device *)data; \
- struct talitos_private *priv = dev_get_drvdata(dev); \
- unsigned long flags; \
- \
- if (ch_done_mask & 1) \
- flush_channel(dev, 0, 0, 0); \
- if (ch_done_mask & (1 << 2)) \
- flush_channel(dev, 1, 0, 0); \
- if (ch_done_mask & (1 << 4)) \
- flush_channel(dev, 2, 0, 0); \
- if (ch_done_mask & (1 << 6)) \
- flush_channel(dev, 3, 0, 0); \
- \
- /* At this point, all completed channels have been processed */ \
- /* Unmask done interrupts for channels completed later on. */ \
- spin_lock_irqsave(&priv->reg_lock, flags); \
- setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
- setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
-}
+#define DEF_TALITOS2_DONE(name, ch_done_mask) \
+ static void talitos2_done_##name(unsigned long data) \
+ { \
+ struct device *dev = (struct device *)data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ unsigned long flags; \
+ \
+ if (ch_done_mask & 1) \
+ flush_channel(dev, 0, 0, 0); \
+ if (ch_done_mask & (1 << 2)) \
+ flush_channel(dev, 1, 0, 0); \
+ if (ch_done_mask & (1 << 4)) \
+ flush_channel(dev, 2, 0, 0); \
+ if (ch_done_mask & (1 << 6)) \
+ flush_channel(dev, 3, 0, 0); \
+ \
+ /* At this point, all completed channels have been processed */ \
+ /* Unmask done interrupts for channels completed later on. */ \
+ spin_lock_irqsave(&priv->reg_lock, flags); \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) | (ch_done_mask), \
+ priv->reg + TALITOS_IMR); \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR_LO) | (TALITOS2_IMR_LO_INIT), \
+ priv->reg + TALITOS_IMR_LO); \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ }
DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
@@ -549,8 +560,8 @@ static __be32 current_desc_hdr(struct device *dev, int ch)
dma_addr_t cur_desc;
__be32 hdr = 0;
- cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
- cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
+ cur_desc = ((u64)ioread32be(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
+ cur_desc |= ioread32be(priv->chan[ch].reg + TALITOS_CDPR_LO);
if (!cur_desc) {
dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
@@ -584,70 +595,60 @@ static void report_eu_error(struct device *dev, int ch, __be32 desc_hdr)
int i;
if (!desc_hdr)
- desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF));
+ desc_hdr = cpu_to_be32(ioread32be(priv->chan[ch].reg + TALITOS_DESCBUF));
switch (desc_hdr & DESC_HDR_SEL0_MASK) {
case DESC_HDR_SEL0_AFEU:
- dev_err(dev, "AFEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_afeu + TALITOS_EUISR),
- in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
+ dev_err(dev, "AFEUISR 0x%08x_%08x\n", ioread32be(priv->reg_afeu + TALITOS_EUISR),
+ ioread32be(priv->reg_afeu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_DEU:
- dev_err(dev, "DEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_deu + TALITOS_EUISR),
- in_be32(priv->reg_deu + TALITOS_EUISR_LO));
+ dev_err(dev, "DEUISR 0x%08x_%08x\n", ioread32be(priv->reg_deu + TALITOS_EUISR),
+ ioread32be(priv->reg_deu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_MDEUA:
case DESC_HDR_SEL0_MDEUB:
- dev_err(dev, "MDEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_mdeu + TALITOS_EUISR),
- in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
+ dev_err(dev, "MDEUISR 0x%08x_%08x\n", ioread32be(priv->reg_mdeu + TALITOS_EUISR),
+ ioread32be(priv->reg_mdeu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_RNG:
- dev_err(dev, "RNGUISR 0x%08x_%08x\n",
- in_be32(priv->reg_rngu + TALITOS_ISR),
- in_be32(priv->reg_rngu + TALITOS_ISR_LO));
+ dev_err(dev, "RNGUISR 0x%08x_%08x\n", ioread32be(priv->reg_rngu + TALITOS_ISR),
+ ioread32be(priv->reg_rngu + TALITOS_ISR_LO));
break;
case DESC_HDR_SEL0_PKEU:
- dev_err(dev, "PKEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_pkeu + TALITOS_EUISR),
- in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
+ dev_err(dev, "PKEUISR 0x%08x_%08x\n", ioread32be(priv->reg_pkeu + TALITOS_EUISR),
+ ioread32be(priv->reg_pkeu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_AESU:
- dev_err(dev, "AESUISR 0x%08x_%08x\n",
- in_be32(priv->reg_aesu + TALITOS_EUISR),
- in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
+ dev_err(dev, "AESUISR 0x%08x_%08x\n", ioread32be(priv->reg_aesu + TALITOS_EUISR),
+ ioread32be(priv->reg_aesu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_CRCU:
- dev_err(dev, "CRCUISR 0x%08x_%08x\n",
- in_be32(priv->reg_crcu + TALITOS_EUISR),
- in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
+ dev_err(dev, "CRCUISR 0x%08x_%08x\n", ioread32be(priv->reg_crcu + TALITOS_EUISR),
+ ioread32be(priv->reg_crcu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_KEU:
- dev_err(dev, "KEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_pkeu + TALITOS_EUISR),
- in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
+ dev_err(dev, "KEUISR 0x%08x_%08x\n", ioread32be(priv->reg_pkeu + TALITOS_EUISR),
+ ioread32be(priv->reg_pkeu + TALITOS_EUISR_LO));
break;
}
switch (desc_hdr & DESC_HDR_SEL1_MASK) {
case DESC_HDR_SEL1_MDEUA:
case DESC_HDR_SEL1_MDEUB:
- dev_err(dev, "MDEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_mdeu + TALITOS_EUISR),
- in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
+ dev_err(dev, "MDEUISR 0x%08x_%08x\n", ioread32be(priv->reg_mdeu + TALITOS_EUISR),
+ ioread32be(priv->reg_mdeu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL1_CRCU:
- dev_err(dev, "CRCUISR 0x%08x_%08x\n",
- in_be32(priv->reg_crcu + TALITOS_EUISR),
- in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
+ dev_err(dev, "CRCUISR 0x%08x_%08x\n", ioread32be(priv->reg_crcu + TALITOS_EUISR),
+ ioread32be(priv->reg_crcu + TALITOS_EUISR_LO));
break;
}
for (i = 0; i < 8; i++)
dev_err(dev, "DESCBUF 0x%08x_%08x\n",
- in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
- in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
+ ioread32be(priv->chan[ch].reg + TALITOS_DESCBUF + 8 * i),
+ ioread32be(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8 * i));
}
/*
@@ -675,7 +676,7 @@ static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
error = -EINVAL;
- v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
+ v_lo = ioread32be(priv->chan[ch].reg + TALITOS_CCPSR_LO);
if (v_lo & TALITOS_CCPSR_LO_DOF) {
dev_err(dev, "double fetch fifo overflow error\n");
@@ -718,11 +719,14 @@ static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
if (reset_ch) {
reset_channel(dev, ch);
} else {
- setbits32(priv->chan[ch].reg + TALITOS_CCCR,
- TALITOS2_CCCR_CONT);
- setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
- while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
- TALITOS2_CCCR_CONT) && --timeout)
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR) |
+ (TALITOS2_CCCR_CONT),
+ priv->chan[ch].reg + TALITOS_CCCR);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) | (0),
+ priv->chan[ch].reg + TALITOS_CCCR_LO);
+ while ((ioread32be(priv->chan[ch].reg + TALITOS_CCCR) &
+ TALITOS2_CCCR_CONT) &&
+ --timeout)
cpu_relax();
if (timeout == 0) {
dev_err(dev, "failed to restart channel %d\n",
@@ -749,73 +753,71 @@ static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
}
}
-#define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
-static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \
-{ \
- struct device *dev = data; \
- struct talitos_private *priv = dev_get_drvdata(dev); \
- u32 isr, isr_lo; \
- unsigned long flags; \
- \
- spin_lock_irqsave(&priv->reg_lock, flags); \
- isr = in_be32(priv->reg + TALITOS_ISR); \
- isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
- /* Acknowledge interrupt */ \
- out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
- out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
- \
- if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
- talitos_error(dev, isr & ch_err_mask, isr_lo); \
- } \
- else { \
- if (likely(isr & ch_done_mask)) { \
- /* mask further done interrupts. */ \
- setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
- /* done_task will unmask done interrupts at exit */ \
- tasklet_schedule(&priv->done_task[tlet]); \
- } \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
- } \
- \
- return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
- IRQ_NONE; \
-}
+#define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
+ static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \
+ { \
+ struct device *dev = data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ u32 isr, isr_lo; \
+ unsigned long flags; \
+ \
+ spin_lock_irqsave(&priv->reg_lock, flags); \
+ isr = ioread32be(priv->reg + TALITOS_ISR); \
+ isr_lo = ioread32be(priv->reg + TALITOS_ISR_LO); \
+ /* Acknowledge interrupt */ \
+ iowrite32be(isr & (ch_done_mask | ch_err_mask), priv->reg + TALITOS_ICR); \
+ iowrite32be(isr_lo, priv->reg + TALITOS_ICR_LO); \
+ \
+ if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ talitos_error(dev, isr & ch_err_mask, isr_lo); \
+ } else { \
+ if (likely(isr & ch_done_mask)) { \
+ /* mask further done interrupts. */ \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) | (ch_done_mask), \
+ priv->reg + TALITOS_IMR); \
+ /* done_task will unmask done interrupts at exit */ \
+ tasklet_schedule(&priv->done_task[tlet]); \
+ } \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ } \
+ \
+ return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : IRQ_NONE; \
+ }
DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
-#define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
-static irqreturn_t talitos2_interrupt_##name(int irq, void *data) \
-{ \
- struct device *dev = data; \
- struct talitos_private *priv = dev_get_drvdata(dev); \
- u32 isr, isr_lo; \
- unsigned long flags; \
- \
- spin_lock_irqsave(&priv->reg_lock, flags); \
- isr = in_be32(priv->reg + TALITOS_ISR); \
- isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
- /* Acknowledge interrupt */ \
- out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
- out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
- \
- if (unlikely(isr & ch_err_mask || isr_lo)) { \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
- talitos_error(dev, isr & ch_err_mask, isr_lo); \
- } \
- else { \
- if (likely(isr & ch_done_mask)) { \
- /* mask further done interrupts. */ \
- clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
- /* done_task will unmask done interrupts at exit */ \
- tasklet_schedule(&priv->done_task[tlet]); \
- } \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
- } \
- \
- return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
- IRQ_NONE; \
-}
+#define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
+ static irqreturn_t talitos2_interrupt_##name(int irq, void *data) \
+ { \
+ struct device *dev = data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ u32 isr, isr_lo; \
+ unsigned long flags; \
+ \
+ spin_lock_irqsave(&priv->reg_lock, flags); \
+ isr = ioread32be(priv->reg + TALITOS_ISR); \
+ isr_lo = ioread32be(priv->reg + TALITOS_ISR_LO); \
+ /* Acknowledge interrupt */ \
+ iowrite32be(isr & (ch_done_mask | ch_err_mask), priv->reg + TALITOS_ICR); \
+ iowrite32be(isr_lo, priv->reg + TALITOS_ICR_LO); \
+ \
+ if (unlikely(isr & ch_err_mask || isr_lo)) { \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ talitos_error(dev, isr & ch_err_mask, isr_lo); \
+ } else { \
+ if (likely(isr & ch_done_mask)) { \
+ /* mask further done interrupts. */ \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) & ~(ch_done_mask), \
+ priv->reg + TALITOS_IMR); \
+ /* done_task will unmask done interrupts at exit */ \
+ tasklet_schedule(&priv->done_task[tlet]); \
+ } \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ } \
+ \
+ return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : IRQ_NONE; \
+ }
DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
@@ -834,8 +836,7 @@ static int talitos_rng_data_present(struct hwrng *rng, int wait)
int i;
for (i = 0; i < 20; i++) {
- ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
- TALITOS_RNGUSR_LO_OFL;
+ ofl = ioread32be(priv->reg_rngu + TALITOS_EUSR_LO) & TALITOS_RNGUSR_LO_OFL;
if (ofl || !wait)
break;
udelay(10);
@@ -850,8 +851,8 @@ static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
struct talitos_private *priv = dev_get_drvdata(dev);
/* rng fifo requires 64-bit accesses */
- *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
- *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
+ *data = ioread32be(priv->reg_rngu + TALITOS_EU_FIFO);
+ *data = ioread32be(priv->reg_rngu + TALITOS_EU_FIFO_LO);
return sizeof(u32);
}
@@ -862,10 +863,9 @@ static int talitos_rng_init(struct hwrng *rng)
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
- setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
- while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
- & TALITOS_RNGUSR_LO_RD)
- && --timeout)
+ iowrite32be(ioread32be(priv->reg_rngu + TALITOS_EURCR_LO) | (TALITOS_RNGURCR_LO_SR),
+ priv->reg_rngu + TALITOS_EURCR_LO);
+ while (!(ioread32be(priv->reg_rngu + TALITOS_EUSR_LO) & TALITOS_RNGUSR_LO_RD) && --timeout)
cpu_relax();
if (timeout == 0) {
dev_err(dev, "failed to reset rng hw\n");
@@ -873,7 +873,8 @@ static int talitos_rng_init(struct hwrng *rng)
}
/* start generating */
- setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
+ iowrite32be(ioread32be(priv->reg_rngu + TALITOS_EUDSR_LO) | (0),
+ priv->reg_rngu + TALITOS_EUDSR_LO);
return 0;
}
--
2.54.0
^ permalink raw reply related
* [PATCH 2/2] crypto: atmel-ecc - clean up and improve ECDH comments
From: Thorsten Blum @ 2026-06-03 19:27 UTC (permalink / raw)
To: Thorsten Blum, Herbert Xu, David S. Miller, Nicolas Ferre,
Alexandre Belloni, Claudiu Beznea
Cc: linux-crypto, linux-arm-kernel, linux-kernel
In-Reply-To: <20260603192708.1237715-4-thorsten.blum@linux.dev>
Improve the kerneldoc for struct atmel_ecdh_ctx by removing the stale
"unsupported curves" wording, since the device only supports a single
curve (P-256), and move the set_secret() constraint to the description.
In atmel_ecdh_set_secret(), clarify that the device generates the
private key, and drop the redundant "only supports NIST P256" comment.
In atmel_ecdh_done() and atmel_ecdh_generate_public_key(), clarify the
truncation comments. Also note that a P-256 public key consists of two
32-byte coordinates in atmel_ecdh_compute_shared_secret(), and remove
the unnecessary fall-through comment and other redundant comments.
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
drivers/crypto/atmel-ecc.c | 37 ++++++++++++++-----------------------
1 file changed, 14 insertions(+), 23 deletions(-)
diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 9387eea4513d..1443e18a9cee 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -27,15 +27,15 @@ static struct atmel_ecc_driver_data driver_data;
/**
* struct atmel_ecdh_ctx - transformation context
- * @client : pointer to i2c client device
- * @fallback : used for unsupported curves or when user wants to use its own
- * private key.
- * @public_key : generated when calling set_secret(). It's the responsibility
- * of the user to not call set_secret() while
- * generate_public_key() or compute_shared_secret() are in flight.
+ * @client : I2C client device
+ * @fallback : ECDH fallback used for caller-provided private keys
+ * @public_key : cached public key corresponding to the device-generated
+ * private key
* @curve_id : elliptic curve id
- * @do_fallback: true when the device doesn't support the curve or when the user
- * wants to use its own private key.
+ * @do_fallback: true when ECDH operations should use @fallback
+ *
+ * The caller must not invoke set_secret() while generate_public_key()
+ * or compute_shared_secret() are in flight.
*/
struct atmel_ecdh_ctx {
struct i2c_client *client;
@@ -55,7 +55,7 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq,
if (status)
goto free_work_data;
- /* might want less than we've got */
+ /* copy only as much as requested, capped at 32 bytes */
n_sz = min(ATMEL_ECC_NIST_P256_N_SIZE, req->dst_len);
/* copy the shared secret */
@@ -64,15 +64,15 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq,
if (copied != n_sz)
status = -EINVAL;
- /* fall through */
free_work_data:
kfree_sensitive(work_data);
kpp_request_complete(req, status);
}
/*
- * A random private key is generated and stored in the device. The device
- * returns the pair public key.
+ * If no private key is provided, generate one in the device and cache
+ * the corresponding public key. The generated private key never leaves
+ * the device.
*/
static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
unsigned int len)
@@ -83,9 +83,7 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
struct ecdh params;
int ret = -ENOMEM;
- /* free the old public key, if any */
kfree(ctx->public_key);
- /* make sure you don't free the old public key twice */
ctx->public_key = NULL;
if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0) {
@@ -94,7 +92,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
}
if (params.key_size) {
- /* fallback to ecdh software implementation */
ctx->do_fallback = true;
return crypto_kpp_set_secret(ctx->fallback, buf, len);
}
@@ -103,11 +100,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
if (!cmd)
return -ENOMEM;
- /*
- * The device only supports NIST P256 ECC keys. The public key size will
- * always be the same. Use a macro for the key size to avoid unnecessary
- * computations.
- */
public_key = kmalloc(ATMEL_ECC_PUBKEY_SIZE, GFP_KERNEL);
if (!public_key)
goto free_cmd;
@@ -120,7 +112,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
if (ret)
goto free_public_key;
- /* save the public key */
memcpy(public_key, &cmd->data[RSP_DATA_IDX], ATMEL_ECC_PUBKEY_SIZE);
ctx->public_key = public_key;
@@ -149,7 +140,7 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req)
if (!ctx->public_key)
return -EINVAL;
- /* might want less than we've got */
+ /* copy only as much as requested, capped at 64 bytes */
nbytes = min(ATMEL_ECC_PUBKEY_SIZE, req->dst_len);
/* public key was saved at private key generation */
@@ -175,7 +166,7 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_request *req)
return crypto_kpp_compute_shared_secret(req);
}
- /* must have exactly two points to be on the curve */
+ /* A P-256 public key must contain two 32-byte coordinates */
if (req->src_len != ATMEL_ECC_PUBKEY_SIZE)
return -EINVAL;
^ permalink raw reply related
* [PATCH 1/2] crypto: atmel-i2c - improve comment in atmel_i2c_init_ecdh_cmd
From: Thorsten Blum @ 2026-06-03 19:27 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea
Cc: Thorsten Blum, linux-crypto, linux-arm-kernel, linux-kernel
Clarify that a P-256 public key is encoded as two 32-byte coordinates.
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
drivers/crypto/atmel-i2c.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c
index ff19857894d0..24bded47a32b 100644
--- a/drivers/crypto/atmel-i2c.c
+++ b/drivers/crypto/atmel-i2c.c
@@ -138,9 +138,8 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd,
cmd->param2 = cpu_to_le16(DATA_SLOT_2);
/*
- * The device only supports NIST P256 ECC keys. The public key size will
- * always be the same. Use a macro for the key size to avoid unnecessary
- * computations.
+ * The device only supports P-256. Its public key is encoded as
+ * two 32-byte coordinates.
*/
copied = sg_copy_to_buffer(pubkey,
sg_nents_for_len(pubkey,
^ permalink raw reply related
* Re: [PATCH] crypto: testmgr - allow authenc(hmac(sha{256,384}),cts(cbc(aes))) in FIPS mode
From: Viacheslav Dubeyko @ 2026-06-03 17:12 UTC (permalink / raw)
To: Ilya Dryomov, Herbert Xu
Cc: David Howells, linux-crypto, ceph-devel, linux-kernel
In-Reply-To: <20260603155008.736872-1-idryomov@gmail.com>
On Wed, 2026-06-03 at 17:50 +0200, Ilya Dryomov wrote:
> hmac(sha256), hmac(sha384) and cts(cbc(aes)) algorithms have been
> marked as FIPS allowed for years. Mark the respective authenc()
> constructions per RFC 8009 ("AES Encryption with HMAC-SHA2 for
> Kerberos 5") as such as well.
>
> SP 800-57 Part 3 Rev. 1 from Jan 2015 [1] links the draft of what
> became RFC 8009 in Oct 2016 as approved in section 6.3 Procurement
> Guidance (item/recommendation 3).
>
> [1] https://csrc.nist.gov/pubs/sp/800/57/pt3/r1/final
>
> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
> ---
> crypto/testmgr.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index 4d86efae65b2..7788e6fa80ce 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -4215,6 +4215,7 @@ static const struct alg_test_desc
> alg_test_descs[] = {
> .alg = "authenc(hmac(sha256),cts(cbc(aes)))",
> .generic_driver = "authenc(hmac-sha256-
> lib,cts(cbc(aes-lib)))",
> .test = alg_test_aead,
> + .fips_allowed = 1,
> .suite = {
> .aead =
> __VECS(krb5_test_aes128_cts_hmac_sha256_128)
> }
> @@ -4256,6 +4257,7 @@ static const struct alg_test_desc
> alg_test_descs[] = {
> .alg = "authenc(hmac(sha384),cts(cbc(aes)))",
> .generic_driver = "authenc(hmac-sha384-
> lib,cts(cbc(aes-lib)))",
> .test = alg_test_aead,
> + .fips_allowed = 1,
> .suite = {
> .aead =
> __VECS(krb5_test_aes256_cts_hmac_sha384_192)
> }
Makes sense.
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Thanks,
Slava.
^ permalink raw reply
* [PATCH] crypto: testmgr - allow authenc(hmac(sha{256,384}),cts(cbc(aes))) in FIPS mode
From: Ilya Dryomov @ 2026-06-03 15:50 UTC (permalink / raw)
To: Herbert Xu; +Cc: David Howells, linux-crypto, ceph-devel, linux-kernel
hmac(sha256), hmac(sha384) and cts(cbc(aes)) algorithms have been
marked as FIPS allowed for years. Mark the respective authenc()
constructions per RFC 8009 ("AES Encryption with HMAC-SHA2 for
Kerberos 5") as such as well.
SP 800-57 Part 3 Rev. 1 from Jan 2015 [1] links the draft of what
became RFC 8009 in Oct 2016 as approved in section 6.3 Procurement
Guidance (item/recommendation 3).
[1] https://csrc.nist.gov/pubs/sp/800/57/pt3/r1/final
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
---
crypto/testmgr.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 4d86efae65b2..7788e6fa80ce 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4215,6 +4215,7 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "authenc(hmac(sha256),cts(cbc(aes)))",
.generic_driver = "authenc(hmac-sha256-lib,cts(cbc(aes-lib)))",
.test = alg_test_aead,
+ .fips_allowed = 1,
.suite = {
.aead = __VECS(krb5_test_aes128_cts_hmac_sha256_128)
}
@@ -4256,6 +4257,7 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "authenc(hmac(sha384),cts(cbc(aes)))",
.generic_driver = "authenc(hmac-sha384-lib,cts(cbc(aes-lib)))",
.test = alg_test_aead,
+ .fips_allowed = 1,
.suite = {
.aead = __VECS(krb5_test_aes256_cts_hmac_sha384_192)
}
--
2.54.0
^ permalink raw reply related
* Re: [PATCH 2/3] AF_ALG: Drop support for off-CPU cryptography
From: Harald Freudenberger @ 2026-06-03 13:33 UTC (permalink / raw)
To: devnull+demiobenour.gmail.com
Cc: acme, adrian.hunter, alexander.shishkin, ardb, axboe, corbet,
davem, demiobenour, ebiggers, edumazet, herbert, horms, io-uring,
irogers, james.clark, jolsa, kuba, kuniyu, linux-crypto,
linux-doc, linux-kernel, linux-perf-users, mark.rutland, mingo,
namhyung, netdev, pabeni, peterz, skhan, willemb, linux-s390
In-Reply-To: <20260523-af-alg-harden-v1-2-c76755c3a5c5@gmail.com>
> AF_ALG is deprecated and exposed to unprivileged userspace. Only
> use the least buggy algorithm implementations: the pure software ones.
>
I thought AF_ALG is marked as deprecated but still usable. This patch
now actively disables groups of crypto implementations. Also it just
assumes that all algorithms which are asynchronously implemented or
do not have a fallback are to be disabled via AF_ALG.
There are may reasons for not having a synchronous implementation. For
example if you need to fetch (asynch) some information from a HSM before
doing the job of the algorithm. Also all secure key operations can't
by definition run directly on the CPU but need to be fed into some
hardware. Same is true with just acceleration - and acceleration via
special hardware (crypto hw, or AI hardware for example) is very common
on platforms priced by CPU cycles.
I also can't find any arguments for the statement 'Hardware accelerator
drivers are frequently buggy.' Does this mean that the linux kernel
from now on will not accept any hardware accelerator drivers any more?
Statements about code quality should be addressed to the driver
maintainer but not lead to tagging of groups of drivers.
I can understand that the AF_ALG shall be deprecated and fade away.
But this patch out of the sudden disables the long standing AF_ALG
interface at least for testing purpose and causes some failures in
the s390 crypto test area without any chance to react at all.
> This removes one of the main advantages of AF_ALG, which is the
> ability to use it with off-CPU accelerators. However, using off-CPU
> accelerators has huge overheads, both in performance and attack surface.
> I have yet to see real-world, performance-critical workloads where using
> an accelerator via AF_ALG is actually a win over doing cryptography in
> userspace.
>
> If using an off-CPU accelerator really does turn out to be a win, a new
> API should be developed that is actually a good fit for it.
>
> Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
> ---
> Documentation/crypto/userspace-if.rst | 7 ++++++-
> crypto/af_alg.c | 2 +-
> crypto/algif_aead.c | 4 ++--
> crypto/algif_hash.c | 4 ++--
> crypto/algif_rng.c | 4 ++--
> crypto/algif_skcipher.c | 4 ++--
> include/crypto/if_alg.h | 14 +++++++++++++-
> 7 files changed, 28 insertions(+), 11 deletions(-)
>
> diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst
> index ea1b1b3f4049fd4673528dc2a6234f6376a3489f..b31117d4415dda6ad6ca36275e615bec7df9552e 100644
> --- a/Documentation/crypto/userspace-if.rst
> +++ b/Documentation/crypto/userspace-if.rst
> @@ -9,7 +9,8 @@ symmetric cipher, AEAD, and RNG algorithms that are implemented in kernel-mode
> code.
>
> AF_ALG is insecure and is deprecated. Originally added to the kernel in 2010,
> -most kernel developers now consider it to be a mistake.
> +most kernel developers now consider it to be a mistake. Support for hardware
> +accelerators, which was the original purpose of AF_ALG, has been removed.
>
> AF_ALG continues to be supported only for backwards compatibility. On systems
> where no programs using AF_ALG remain, the support for it should be disabled by
> @@ -59,6 +60,10 @@ Some of the examples include:
> - CVE-2013-7421
> - CVE-2011-4081
>
> +Hardware accelerator drivers are frequently buggy. To reduce attack surface,
> +AF_ALG now only provides access to algorithms implemented in software. This
> +means that AF_ALG no longer fulfills its original purpose.
> +
> It is recommended that, whenever possible, userspace programs be migrated to
> userspace crypto code (which again, is what is normally used anyway) and
> ``CONFIG_CRYPTO_USER_API_*`` be disabled. On systems that use SELinux, SELinux
> diff --git a/crypto/af_alg.c b/crypto/af_alg.c
> index 8ccf7a737cd6ca9a5d5bf47050c9afea0dfd61bf..cce000e8590e469927b5a5a0ceccfdf0ef54633d 100644
> --- a/crypto/af_alg.c
> +++ b/crypto/af_alg.c
> @@ -181,7 +181,7 @@ static int alg_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int add
> if (IS_ERR(type))
> return PTR_ERR(type);
>
> - private = type->bind(sa->salg_name, sa->salg_feat, sa->salg_mask);
> + private = type->bind(sa->salg_name);
> if (IS_ERR(private)) {
> module_put(type->owner);
> return PTR_ERR(private);
> diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
> index 60f06597cb0b13036bc975641a0b02ea8a41ad03..787aac8aeb24eed128f08345ba730478113919b3 100644
> --- a/crypto/algif_aead.c
> +++ b/crypto/algif_aead.c
> @@ -342,9 +342,9 @@ static struct proto_ops algif_aead_ops_nokey = {
> .poll = af_alg_poll,
> };
>
> -static void *aead_bind(const char *name, u32 type, u32 mask)
> +static void *aead_bind(const char *name)
> {
> - return crypto_alloc_aead(name, type, mask);
> + return crypto_alloc_aead(name, 0, AF_ALG_CRYPTOAPI_MASK);
> }
>
> static void aead_release(void *private)
> diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
> index 4d3dfc60a16a6d8b677d903d209df18d67202c98..5452ad6c15069c3cb0ff78fe58868fe7ce4b0fc3 100644
> --- a/crypto/algif_hash.c
> +++ b/crypto/algif_hash.c
> @@ -380,9 +380,9 @@ static struct proto_ops algif_hash_ops_nokey = {
> .accept = hash_accept_nokey,
> };
>
> -static void *hash_bind(const char *name, u32 type, u32 mask)
> +static void *hash_bind(const char *name)
> {
> - return crypto_alloc_ahash(name, type, mask);
> + return crypto_alloc_ahash(name, 0, AF_ALG_CRYPTOAPI_MASK);
> }
>
> static void hash_release(void *private)
> diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
> index a9fb492e929a70c94476f296f5f5e7c42f0313b7..4dfe7899f8fa4ce82d5f2236297230fb44bc35d6 100644
> --- a/crypto/algif_rng.c
> +++ b/crypto/algif_rng.c
> @@ -197,7 +197,7 @@ static struct proto_ops __maybe_unused algif_rng_test_ops = {
> .sendmsg = rng_test_sendmsg,
> };
>
> -static void *rng_bind(const char *name, u32 type, u32 mask)
> +static void *rng_bind(const char *name)
> {
> struct rng_parent_ctx *pctx;
> struct crypto_rng *rng;
> @@ -206,7 +206,7 @@ static void *rng_bind(const char *name, u32 type, u32 mask)
> if (!pctx)
> return ERR_PTR(-ENOMEM);
>
> - rng = crypto_alloc_rng(name, type, mask);
> + rng = crypto_alloc_rng(name, 0, AF_ALG_CRYPTOAPI_MASK);
> if (IS_ERR(rng)) {
> kfree(pctx);
> return ERR_CAST(rng);
> diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
> index 9dbccabd87b13920c27aff5a450a235cc6a27d59..df20bdfe1f1f4e453782dee3b743dd1939ab4c6c 100644
> --- a/crypto/algif_skcipher.c
> +++ b/crypto/algif_skcipher.c
> @@ -307,9 +307,9 @@ static struct proto_ops algif_skcipher_ops_nokey = {
> .poll = af_alg_poll,
> };
>
> -static void *skcipher_bind(const char *name, u32 type, u32 mask)
> +static void *skcipher_bind(const char *name)
> {
> - return crypto_alloc_skcipher(name, type, mask);
> + return crypto_alloc_skcipher(name, 0, AF_ALG_CRYPTOAPI_MASK);
> }
>
> static void skcipher_release(void *private)
> diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
> index 62867daca47d76c9ea1a7ed233188788c5f6c3c0..7643ba954125aba0c06aaf19de087985325885ad 100644
> --- a/include/crypto/if_alg.h
> +++ b/include/crypto/if_alg.h
> @@ -41,7 +41,7 @@ struct af_alg_control {
> };
>
> struct af_alg_type {
> - void *(*bind)(const char *name, u32 type, u32 mask);
> + void *(*bind)(const char *name);
> void (*release)(void *private);
> int (*setkey)(void *private, const u8 *key, unsigned int keylen);
> int (*setentropy)(void *private, sockptr_t entropy, unsigned int len);
> @@ -243,4 +243,16 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
> struct af_alg_async_req *areq, size_t maxsize,
> size_t *outlen);
>
> +/*
> + * Mask used to disable unsupported algorithm implementations.
> + *
> + * This is the same as FSCRYPT_CRYPTOAPI_MASK in fs/crypto/fscrypt_private.h.
> + * In additions to the motivations there, this API is exposed to userspace
> + * that might not be fully trusted.
> + */
> +#define AF_ALG_CRYPTOAPI_MASK \
> + (CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | \
> + CRYPTO_ALG_KERN_DRIVER_ONLY)
> +
> +
> #endif /* _CRYPTO_IF_ALG_H */
>
> --
> 2.54.0
>
Harald Freudenberger
^ permalink raw reply
* Re: [PATCH] MAINTAINERS: make myself the maintainer of the Qualcomm QCE driver
From: Konrad Dybcio @ 2026-06-03 11:35 UTC (permalink / raw)
To: Bartosz Golaszewski, Demi Marie Obenour, Herbert Xu,
David S. Miller, Thara Gopinath, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio, Russell King,
Eric Biggers, Ard Biesheuvel, Kuldeep Singh
Cc: linux-crypto, linux-arm-msm, linux-kernel, brgl
In-Reply-To: <20260602-qcom-qce-broken-v1-1-a4ef756089e0@oss.qualcomm.com>
On 02-Jun-26 14:46, Bartosz Golaszewski wrote:
> Qualcomm wants to keep supporting and extending the crypto engine driver.
> Thara has not been active for many months, so change the maintainer to
> myself and upgrade the driver to Supported.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* [PATCH] hwrng: jh7110: fix refcount leak in starfive_trng_read()
From: Wentao Liang @ 2026-06-03 11:03 UTC (permalink / raw)
To: jiajie.ho, olivia, herbert
Cc: linux-crypto, linux-kernel, Wentao Liang, stable
The starfive_trng_read() function acquires a runtime PM reference
via pm_runtime_get_sync() but fails to release it on two error
paths. If starfive_trng_wait_idle() or starfive_trng_cmd() returns
an error, the function exits without calling
pm_runtime_put_sync_autosuspend(), leaving the runtime PM usage
counter permanently elevated and preventing the device from entering
runtime suspend.
Refactor the function to use a unified error path that calls
pm_runtime_put_sync_autosuspend() before returning.
Cc: stable@vger.kernel.org
Fixes: c388f458bc34 ("hwrng: starfive - Add TRNG driver for StarFive SoC")
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
drivers/char/hw_random/jh7110-trng.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/char/hw_random/jh7110-trng.c b/drivers/char/hw_random/jh7110-trng.c
index 9776f4daa044..4712c3c530e4 100644
--- a/drivers/char/hw_random/jh7110-trng.c
+++ b/drivers/char/hw_random/jh7110-trng.c
@@ -256,19 +256,22 @@ static int starfive_trng_read(struct hwrng *rng, void *buf, size_t max, bool wai
if (wait) {
ret = starfive_trng_wait_idle(trng);
- if (ret)
- return -ETIMEDOUT;
+ if (ret) {
+ ret = -ETIMEDOUT;
+ goto out_put;
+ }
}
ret = starfive_trng_cmd(trng, STARFIVE_CTRL_GENE_RANDNUM, wait);
if (ret)
- return ret;
+ goto out_put;
memcpy_fromio(buf, trng->base + STARFIVE_RAND0, max);
+ ret = max;
+out_put:
pm_runtime_put_sync_autosuspend(trng->dev);
-
- return max;
+ return ret;
}
static int starfive_trng_probe(struct platform_device *pdev)
--
2.34.1
^ permalink raw reply related
* [PATCH 5.10] crypto: lzo - Fix compression buffer overrun
From: Viktoriya Danchenko @ 2026-06-03 9:42 UTC (permalink / raw)
To: lvc-project, David S. Miller, David Sterba, Herbert Xu,
linux-crypto
From: Herbert Xu <herbert@gondor.apana.org.au>
[ Upstream commit cc47f07234f72cbd8e2c973cdbf2a6730660a463 ]
Unlike the decompression code, the compression code in LZO never
checked for output overruns. It instead assumes that the caller
always provides enough buffer space, disregarding the buffer length
provided by the caller.
Add a safe compression interface that checks for the end of buffer
before each write. Use the safe interface in crypto/lzo.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Roman Smirnov <r.smirnov@omp.ru>
Fixes: 64c70b1cf43d ("Add LZO1X algorithm to the kernel")
Signed-off-by: Viktoriya Danchenko <v.danchenko@omp.ru>
---
Backport fix for CVE-2025-38068
---
crypto/lzo-rle.c | 2 +-
crypto/lzo.c | 2 +-
include/linux/lzo.h | 8 +++
lib/lzo/Makefile | 2 +-
lib/lzo/lzo1x_compress.c | 101 +++++++++++++++++++++++++---------
lib/lzo/lzo1x_compress_safe.c | 18 ++++++
6 files changed, 105 insertions(+), 28 deletions(-)
create mode 100644 lib/lzo/lzo1x_compress_safe.c
diff --git a/crypto/lzo-rle.c b/crypto/lzo-rle.c
index 0631d975bfac..0abc2d87f042 100644
--- a/crypto/lzo-rle.c
+++ b/crypto/lzo-rle.c
@@ -55,7 +55,7 @@ static int __lzorle_compress(const u8 *src, unsigned int slen,
size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
int err;
- err = lzorle1x_1_compress(src, slen, dst, &tmp_len, ctx);
+ err = lzorle1x_1_compress_safe(src, slen, dst, &tmp_len, ctx);
if (err != LZO_E_OK)
return -EINVAL;
diff --git a/crypto/lzo.c b/crypto/lzo.c
index ebda132dd22b..8338851c7406 100644
--- a/crypto/lzo.c
+++ b/crypto/lzo.c
@@ -55,7 +55,7 @@ static int __lzo_compress(const u8 *src, unsigned int slen,
size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
int err;
- err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx);
+ err = lzo1x_1_compress_safe(src, slen, dst, &tmp_len, ctx);
if (err != LZO_E_OK)
return -EINVAL;
diff --git a/include/linux/lzo.h b/include/linux/lzo.h
index e95c7d1092b2..4d30e3624acd 100644
--- a/include/linux/lzo.h
+++ b/include/linux/lzo.h
@@ -24,10 +24,18 @@
int lzo1x_1_compress(const unsigned char *src, size_t src_len,
unsigned char *dst, size_t *dst_len, void *wrkmem);
+/* Same as above but does not write more than dst_len to dst. */
+int lzo1x_1_compress_safe(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len, void *wrkmem);
+
/* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */
int lzorle1x_1_compress(const unsigned char *src, size_t src_len,
unsigned char *dst, size_t *dst_len, void *wrkmem);
+/* Same as above but does not write more than dst_len to dst. */
+int lzorle1x_1_compress_safe(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len, void *wrkmem);
+
/* safe decompression with overrun testing */
int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
unsigned char *dst, size_t *dst_len);
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
index 2f58fafbbddd..fc7b2b7ef4b2 100644
--- a/lib/lzo/Makefile
+++ b/lib/lzo/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
-lzo_compress-objs := lzo1x_compress.o
+lzo_compress-objs := lzo1x_compress.o lzo1x_compress_safe.o
lzo_decompress-objs := lzo1x_decompress_safe.o
obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
index 8ad5ba2b86e2..941d7337f273 100644
--- a/lib/lzo/lzo1x_compress.c
+++ b/lib/lzo/lzo1x_compress.c
@@ -18,11 +18,22 @@
#include <linux/lzo.h>
#include "lzodefs.h"
-static noinline size_t
-lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
- unsigned char *out, size_t *out_len,
- size_t ti, void *wrkmem, signed char *state_offset,
- const unsigned char bitstream_version)
+#undef LZO_UNSAFE
+
+#ifndef LZO_SAFE
+#define LZO_UNSAFE 1
+#define LZO_SAFE(name) name
+#define HAVE_OP(x) 1
+#endif
+
+#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun
+
+static noinline int
+LZO_SAFE(lzo1x_1_do_compress)(const unsigned char *in, size_t in_len,
+ unsigned char **out, unsigned char *op_end,
+ size_t *tp, void *wrkmem,
+ signed char *state_offset,
+ const unsigned char bitstream_version)
{
const unsigned char *ip;
unsigned char *op;
@@ -30,8 +41,9 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
const unsigned char * const ip_end = in + in_len - 20;
const unsigned char *ii;
lzo_dict_t * const dict = (lzo_dict_t *) wrkmem;
+ size_t ti = *tp;
- op = out;
+ op = *out;
ip = in;
ii = ip;
ip += ti < 4 ? 4 - ti : 0;
@@ -118,25 +130,32 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
if (t != 0) {
if (t <= 3) {
op[*state_offset] |= t;
+ NEED_OP(4);
COPY4(op, ii);
op += t;
} else if (t <= 16) {
+ NEED_OP(17);
*op++ = (t - 3);
COPY8(op, ii);
COPY8(op + 8, ii + 8);
op += t;
} else {
if (t <= 18) {
+ NEED_OP(1);
*op++ = (t - 3);
} else {
size_t tt = t - 18;
+ NEED_OP(1);
*op++ = 0;
while (unlikely(tt > 255)) {
tt -= 255;
+ NEED_OP(1);
*op++ = 0;
}
+ NEED_OP(1);
*op++ = tt;
}
+ NEED_OP(t);
do {
COPY8(op, ii);
COPY8(op + 8, ii + 8);
@@ -153,6 +172,7 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
if (unlikely(run_length)) {
ip += run_length;
run_length -= MIN_ZERO_RUN_LENGTH;
+ NEED_OP(4);
put_unaligned_le32((run_length << 21) | 0xfffc18
| (run_length & 0x7), op);
op += 4;
@@ -245,10 +265,12 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
ip += m_len;
if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
m_off -= 1;
+ NEED_OP(2);
*op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2));
*op++ = (m_off >> 3);
} else if (m_off <= M3_MAX_OFFSET) {
m_off -= 1;
+ NEED_OP(1);
if (m_len <= M3_MAX_LEN)
*op++ = (M3_MARKER | (m_len - 2));
else {
@@ -256,14 +278,18 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
*op++ = M3_MARKER | 0;
while (unlikely(m_len > 255)) {
m_len -= 255;
+ NEED_OP(1);
*op++ = 0;
}
+ NEED_OP(1);
*op++ = (m_len);
}
+ NEED_OP(2);
*op++ = (m_off << 2);
*op++ = (m_off >> 6);
} else {
m_off -= 0x4000;
+ NEED_OP(1);
if (m_len <= M4_MAX_LEN)
*op++ = (M4_MARKER | ((m_off >> 11) & 8)
| (m_len - 2));
@@ -284,11 +310,14 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
m_len -= M4_MAX_LEN;
*op++ = (M4_MARKER | ((m_off >> 11) & 8));
while (unlikely(m_len > 255)) {
+ NEED_OP(1);
m_len -= 255;
*op++ = 0;
}
+ NEED_OP(1);
*op++ = (m_len);
}
+ NEED_OP(2);
*op++ = (m_off << 2);
*op++ = (m_off >> 6);
}
@@ -297,14 +326,20 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
ii = ip;
goto next;
}
- *out_len = op - out;
- return in_end - (ii - ti);
+ *out = op;
+ *tp = in_end - (ii - ti);
+ return LZO_E_OK;
+
+output_overrun:
+ return LZO_E_OUTPUT_OVERRUN;
}
-int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
- unsigned char *out, size_t *out_len,
- void *wrkmem, const unsigned char bitstream_version)
+static int LZO_SAFE(lzogeneric1x_1_compress)(
+ const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ void *wrkmem, const unsigned char bitstream_version)
{
+ unsigned char * const op_end = out + *out_len;
const unsigned char *ip = in;
unsigned char *op = out;
unsigned char *data_start;
@@ -312,6 +347,7 @@ int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
size_t t = 0;
signed char state_offset = -2;
unsigned int m4_max_offset;
+ int err;
// LZO v0 will never write 17 as first byte (except for zero-length
// input), so this is used to version the bitstream
@@ -332,10 +368,12 @@ int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
break;
BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
- t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem,
- &state_offset, bitstream_version);
+ err = LZO_SAFE(lzo1x_1_do_compress)(
+ ip, ll, &op, op_end, &t, wrkmem,
+ &state_offset, bitstream_version);
+ if (err != LZO_E_OK)
+ return err;
ip += ll;
- op += *out_len;
l -= ll;
}
t += l;
@@ -344,20 +382,26 @@ int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
const unsigned char *ii = in + in_len - t;
if (op == data_start && t <= 238) {
+ NEED_OP(1);
*op++ = (17 + t);
} else if (t <= 3) {
op[state_offset] |= t;
} else if (t <= 18) {
+ NEED_OP(1);
*op++ = (t - 3);
} else {
size_t tt = t - 18;
+ NEED_OP(1);
*op++ = 0;
while (tt > 255) {
tt -= 255;
+ NEED_OP(1);
*op++ = 0;
}
+ NEED_OP(1);
*op++ = tt;
}
+ NEED_OP(t);
if (t >= 16) do {
COPY8(op, ii);
COPY8(op + 8, ii + 8);
@@ -370,31 +414,38 @@ int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
} while (--t > 0);
}
+ NEED_OP(3);
*op++ = M4_MARKER | 1;
*op++ = 0;
*op++ = 0;
*out_len = op - out;
return LZO_E_OK;
+
+output_overrun:
+ return LZO_E_OUTPUT_OVERRUN;
}
-int lzo1x_1_compress(const unsigned char *in, size_t in_len,
- unsigned char *out, size_t *out_len,
- void *wrkmem)
+int LZO_SAFE(lzo1x_1_compress)(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ void *wrkmem)
{
- return lzogeneric1x_1_compress(in, in_len, out, out_len, wrkmem, 0);
+ return LZO_SAFE(lzogeneric1x_1_compress)(
+ in, in_len, out, out_len, wrkmem, 0);
}
-int lzorle1x_1_compress(const unsigned char *in, size_t in_len,
- unsigned char *out, size_t *out_len,
- void *wrkmem)
+int LZO_SAFE(lzorle1x_1_compress)(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ void *wrkmem)
{
- return lzogeneric1x_1_compress(in, in_len, out, out_len,
- wrkmem, LZO_VERSION);
+ return LZO_SAFE(lzogeneric1x_1_compress)(
+ in, in_len, out, out_len, wrkmem, LZO_VERSION);
}
-EXPORT_SYMBOL_GPL(lzo1x_1_compress);
-EXPORT_SYMBOL_GPL(lzorle1x_1_compress);
+EXPORT_SYMBOL_GPL(LZO_SAFE(lzo1x_1_compress));
+EXPORT_SYMBOL_GPL(LZO_SAFE(lzorle1x_1_compress));
+#ifndef LZO_UNSAFE
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LZO1X-1 Compressor");
+#endif
diff --git a/lib/lzo/lzo1x_compress_safe.c b/lib/lzo/lzo1x_compress_safe.c
new file mode 100644
index 000000000000..371c9f849492
--- /dev/null
+++ b/lib/lzo/lzo1x_compress_safe.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * LZO1X Compressor from LZO
+ *
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for Linux kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#define LZO_SAFE(name) name##_safe
+#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x))
+
+#include "lzo1x_compress.c"
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] crypto: use two-argument strscpy where destination size is known
From: David Laight @ 2026-06-03 9:45 UTC (permalink / raw)
To: Thorsten Blum
Cc: Herbert Xu, David S. Miller, Tom Lendacky, John Allen, Weili Qian,
Zhou Wang, Giovanni Cabiddu, Srujana Challa, Bharat Bhushan,
linux-crypto, linux-kernel, qat-linux
In-Reply-To: <20260525103038.825690-4-thorsten.blum@linux.dev>
On Mon, 25 May 2026 12:30:41 +0200
Thorsten Blum <thorsten.blum@linux.dev> wrote:
> To simplify the code, drop explicit and hard-coded size arguments from
> strscpy() where the destination buffer has a fixed size and strscpy()
> can automatically determine it using sizeof().
I'm not entirely sure these changes are worth the churn.
A more interesting exercise might be to get the compiler to look
for places when the three argument form is used with the destination
being an array and the length a constant that doesn't match the
size of the array.
There might be some false positives, but the size shouldn't be larger.
Note that you can't rely on builtin_sizeof() to give you the actual
size of an array.
It just lets you overrun past the end of an array that ends and the
end of a structure you have a pointer to.
The size has to come from sizeof() as in the 2 argument form.
-- David
>
> Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
> ---
> crypto/api.c | 2 +-
> crypto/crypto_user.c | 9 ++++-----
> crypto/hctr2.c | 3 +--
> crypto/lrw.c | 2 +-
> crypto/lskcipher.c | 3 +--
> crypto/xts.c | 3 ++-
> drivers/crypto/cavium/nitrox/nitrox_hal.c | 3 ++-
> drivers/crypto/ccp/ccp-crypto-sha.c | 2 +-
> drivers/crypto/hisilicon/qm.c | 5 +----
> drivers/crypto/intel/qat/qat_common/adf_cfg.c | 7 ++++---
> drivers/crypto/intel/qat/qat_common/adf_cfg_services.c | 2 +-
> drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c | 3 ++-
> drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c | 3 ++-
> .../crypto/intel/qat/qat_common/adf_transport_debug.c | 3 ++-
> drivers/crypto/intel/qat/qat_common/qat_compression.c | 3 ++-
> drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c | 6 +++---
> drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c | 4 ++--
> 17 files changed, 32 insertions(+), 31 deletions(-)
>
> diff --git a/crypto/api.c b/crypto/api.c
> index 74e17d5049c9..040b7a965c2f 100644
> --- a/crypto/api.c
> +++ b/crypto/api.c
> @@ -116,7 +116,7 @@ struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask)
> larval->alg.cra_priority = -1;
> larval->alg.cra_destroy = crypto_larval_destroy;
>
> - strscpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME);
> + strscpy(larval->alg.cra_name, name);
> init_completion(&larval->completion);
>
> return larval;
> diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
> index e8b6ae75f31f..d3ccb507153b 100644
> --- a/crypto/crypto_user.c
> +++ b/crypto/crypto_user.c
> @@ -11,6 +11,7 @@
> #include <linux/cryptouser.h>
> #include <linux/sched.h>
> #include <linux/security.h>
> +#include <linux/string.h>
> #include <net/netlink.h>
> #include <net/net_namespace.h>
> #include <net/sock.h>
> @@ -87,11 +88,9 @@ static int crypto_report_one(struct crypto_alg *alg,
> {
> memset(ualg, 0, sizeof(*ualg));
>
> - strscpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
> - strscpy(ualg->cru_driver_name, alg->cra_driver_name,
> - sizeof(ualg->cru_driver_name));
> - strscpy(ualg->cru_module_name, module_name(alg->cra_module),
> - sizeof(ualg->cru_module_name));
> + strscpy(ualg->cru_name, alg->cra_name);
> + strscpy(ualg->cru_driver_name, alg->cra_driver_name);
> + strscpy(ualg->cru_module_name, module_name(alg->cra_module));
>
> ualg->cru_type = 0;
> ualg->cru_mask = 0;
> diff --git a/crypto/hctr2.c b/crypto/hctr2.c
> index ad5edf9366ac..cfc2343bcc1c 100644
> --- a/crypto/hctr2.c
> +++ b/crypto/hctr2.c
> @@ -354,8 +354,7 @@ static int hctr2_create_common(struct crypto_template *tmpl, struct rtattr **tb,
> err = -EINVAL;
> if (strncmp(xctr_alg->base.cra_name, "xctr(", 5))
> goto err_free_inst;
> - len = strscpy(blockcipher_name, xctr_alg->base.cra_name + 5,
> - sizeof(blockcipher_name));
> + len = strscpy(blockcipher_name, xctr_alg->base.cra_name + 5);
> if (len < 1)
> goto err_free_inst;
> if (blockcipher_name[len - 1] != ')')
> diff --git a/crypto/lrw.c b/crypto/lrw.c
> index aa31ab03a597..e306e85d7ced 100644
> --- a/crypto/lrw.c
> +++ b/crypto/lrw.c
> @@ -359,7 +359,7 @@ static int lrw_create(struct crypto_template *tmpl, struct rtattr **tb)
> if (!memcmp(cipher_name, "ecb(", 4)) {
> int len;
>
> - len = strscpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
> + len = strscpy(ecb_name, cipher_name + 4);
> if (len < 2)
> goto err_free_inst;
>
> diff --git a/crypto/lskcipher.c b/crypto/lskcipher.c
> index e4328df6e26c..d7ec215e2b3a 100644
> --- a/crypto/lskcipher.c
> +++ b/crypto/lskcipher.c
> @@ -528,8 +528,7 @@ struct lskcipher_instance *lskcipher_alloc_instance_simple(
> int len;
>
> err = -EINVAL;
> - len = strscpy(ecb_name, &cipher_alg->co.base.cra_name[4],
> - sizeof(ecb_name));
> + len = strscpy(ecb_name, &cipher_alg->co.base.cra_name[4]);
> if (len < 2)
> goto err_free_inst;
>
> diff --git a/crypto/xts.c b/crypto/xts.c
> index ad97c8091582..1dc948745444 100644
> --- a/crypto/xts.c
> +++ b/crypto/xts.c
> @@ -16,6 +16,7 @@
> #include <linux/module.h>
> #include <linux/scatterlist.h>
> #include <linux/slab.h>
> +#include <linux/string.h>
>
> #include <crypto/xts.h>
> #include <crypto/b128ops.h>
> @@ -400,7 +401,7 @@ static int xts_create(struct crypto_template *tmpl, struct rtattr **tb)
> if (!memcmp(cipher_name, "ecb(", 4)) {
> int len;
>
> - len = strscpy(name, cipher_name + 4, sizeof(name));
> + len = strscpy(name, cipher_name + 4);
> if (len < 2)
> goto err_free_inst;
>
> diff --git a/drivers/crypto/cavium/nitrox/nitrox_hal.c b/drivers/crypto/cavium/nitrox/nitrox_hal.c
> index 1b5abdb6cc5e..e36c1741bb78 100644
> --- a/drivers/crypto/cavium/nitrox/nitrox_hal.c
> +++ b/drivers/crypto/cavium/nitrox/nitrox_hal.c
> @@ -1,5 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0
> #include <linux/delay.h>
> +#include <linux/string.h>
>
> #include "nitrox_dev.h"
> #include "nitrox_csr.h"
> @@ -647,7 +648,7 @@ void nitrox_get_hwinfo(struct nitrox_device *ndev)
> ndev->hw.revision_id);
>
> /* copy partname */
> - strscpy(ndev->hw.partname, name, sizeof(ndev->hw.partname));
> + strscpy(ndev->hw.partname, name);
> }
>
> void enable_pf2vf_mbox_interrupts(struct nitrox_device *ndev)
> diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c
> index 85058a89f35b..ff9bb253dbb2 100644
> --- a/drivers/crypto/ccp/ccp-crypto-sha.c
> +++ b/drivers/crypto/ccp/ccp-crypto-sha.c
> @@ -426,7 +426,7 @@ static int ccp_register_hmac_alg(struct list_head *head,
> *ccp_alg = *base_alg;
> INIT_LIST_HEAD(&ccp_alg->entry);
>
> - strscpy(ccp_alg->child_alg, def->name, CRYPTO_MAX_ALG_NAME);
> + strscpy(ccp_alg->child_alg, def->name);
>
> alg = &ccp_alg->alg;
> alg->setkey = ccp_sha_setkey;
> diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
> index 3ca47e2a9719..0c8cc0d7a82a 100644
> --- a/drivers/crypto/hisilicon/qm.c
> +++ b/drivers/crypto/hisilicon/qm.c
> @@ -2870,11 +2870,8 @@ static int qm_alloc_uacce(struct hisi_qm *qm)
> .flags = UACCE_DEV_SVA,
> .ops = &uacce_qm_ops,
> };
> - int ret;
>
> - ret = strscpy(interface.name, dev_driver_string(&pdev->dev),
> - sizeof(interface.name));
> - if (ret < 0)
> + if (strscpy(interface.name, dev_driver_string(&pdev->dev)) < 0)
> return -ENAMETOOLONG;
>
> uacce = uacce_alloc(&pdev->dev, &interface);
> diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.c b/drivers/crypto/intel/qat/qat_common/adf_cfg.c
> index c202209f17d5..24c2618af68d 100644
> --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.c
> +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.c
> @@ -2,6 +2,7 @@
> /* Copyright(c) 2014 - 2020 Intel Corporation */
> #include <linux/mutex.h>
> #include <linux/slab.h>
> +#include <linux/string.h>
> #include <linux/list.h>
> #include <linux/seq_file.h>
> #include "adf_accel_devices.h"
> @@ -294,13 +295,13 @@ int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
> return -ENOMEM;
>
> INIT_LIST_HEAD(&key_val->list);
> - strscpy(key_val->key, key, sizeof(key_val->key));
> + strscpy(key_val->key, key);
>
> if (type == ADF_DEC) {
> snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
> "%ld", (*((long *)val)));
> } else if (type == ADF_STR) {
> - strscpy(key_val->val, (char *)val, sizeof(key_val->val));
> + strscpy(key_val->val, (char *)val);
> } else if (type == ADF_HEX) {
> snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
> "0x%lx", (unsigned long)val);
> @@ -360,7 +361,7 @@ int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
> if (!sec)
> return -ENOMEM;
>
> - strscpy(sec->name, name, sizeof(sec->name));
> + strscpy(sec->name, name);
> INIT_LIST_HEAD(&sec->param_head);
> down_write(&cfg->lock);
> list_add_tail(&sec->list, &cfg->sec_list);
> diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c
> index 7d00bcb41ce7..11cba347d12d 100644
> --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c
> +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c
> @@ -60,7 +60,7 @@ static int adf_service_string_to_mask(struct adf_accel_dev *accel_dev, const cha
> if (len > ADF_CFG_MAX_VAL_LEN_IN_BYTES - 1)
> return -EINVAL;
>
> - strscpy(services, buf, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
> + strscpy(services, buf);
> substr = services;
>
> while ((token = strsep(&substr, ADF_SERVICES_DELIMITER))) {
> diff --git a/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c
> index c2e6f0cb7480..ae10b91da5ba 100644
> --- a/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c
> +++ b/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c
> @@ -5,6 +5,7 @@
> #include <linux/module.h>
> #include <linux/mutex.h>
> #include <linux/slab.h>
> +#include <linux/string.h>
> #include <linux/fs.h>
> #include <linux/bitops.h>
> #include <linux/pci.h>
> @@ -350,7 +351,7 @@ static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
> dev_info.num_logical_accel = hw_data->num_logical_accel;
> dev_info.banks_per_accel = hw_data->num_banks
> / hw_data->num_logical_accel;
> - strscpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name));
> + strscpy(dev_info.name, hw_data->dev_class->name);
> dev_info.instance_id = hw_data->instance_id;
> dev_info.type = hw_data->dev_class->type;
> dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number;
> diff --git a/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c b/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c
> index f9017e03ec0f..32aeb795cc03 100644
> --- a/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c
> +++ b/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c
> @@ -2,6 +2,7 @@
> /* Copyright(c) 2024 Intel Corporation */
>
> #include <linux/slab.h>
> +#include <linux/string.h>
> #include <linux/types.h>
> #include "adf_mstate_mgr.h"
>
> @@ -158,7 +159,7 @@ static struct adf_mstate_sect_h *adf_mstate_sect_add_header(struct adf_mstate_mg
> return NULL;
> }
>
> - strscpy(sect->id, id, sizeof(sect->id));
> + strscpy(sect->id, id);
> sect->size = 0;
> sect->sub_sects = 0;
> mgr->state += sizeof(*sect);
> diff --git a/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c b/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c
> index a8f853516a3f..fc5d88a2bb17 100644
> --- a/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c
> +++ b/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c
> @@ -2,6 +2,7 @@
> /* Copyright(c) 2014 - 2020 Intel Corporation */
> #include <linux/mutex.h>
> #include <linux/slab.h>
> +#include <linux/string.h>
> #include <linux/seq_file.h>
> #include "adf_accel_devices.h"
> #include "adf_transport_internal.h"
> @@ -103,7 +104,7 @@ int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name)
> if (!ring_debug)
> return -ENOMEM;
>
> - strscpy(ring_debug->ring_name, name, sizeof(ring_debug->ring_name));
> + strscpy(ring_debug->ring_name, name);
> snprintf(entry_name, sizeof(entry_name), "ring_%02d",
> ring->ring_number);
>
> diff --git a/drivers/crypto/intel/qat/qat_common/qat_compression.c b/drivers/crypto/intel/qat/qat_common/qat_compression.c
> index 1424d7a9bcd3..8129ad0c32d8 100644
> --- a/drivers/crypto/intel/qat/qat_common/qat_compression.c
> +++ b/drivers/crypto/intel/qat/qat_common/qat_compression.c
> @@ -2,6 +2,7 @@
> /* Copyright(c) 2022 Intel Corporation */
> #include <linux/module.h>
> #include <linux/slab.h>
> +#include <linux/string.h>
> #include "adf_accel_devices.h"
> #include "adf_common_drv.h"
> #include "adf_transport.h"
> @@ -144,7 +145,7 @@ static int qat_compression_create_instances(struct adf_accel_dev *accel_dev)
> int i;
>
> INIT_LIST_HEAD(&accel_dev->compression_list);
> - strscpy(key, ADF_NUM_DC, sizeof(key));
> + strscpy(key, ADF_NUM_DC);
> ret = adf_cfg_get_param_value(accel_dev, SEC, key, val);
> if (ret)
> return ret;
> diff --git a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c
> index e0f38d32bc93..5c3636080757 100644
> --- a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c
> +++ b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c
> @@ -99,7 +99,7 @@ static int dev_supports_eng_type(struct otx_cpt_eng_grps *eng_grps,
> static void set_ucode_filename(struct otx_cpt_ucode *ucode,
> const char *filename)
> {
> - strscpy(ucode->filename, filename, OTX_CPT_UCODE_NAME_LENGTH);
> + strscpy(ucode->filename, filename);
> }
>
> static char *get_eng_type_str(int eng_type)
> @@ -140,7 +140,7 @@ static int get_ucode_type(struct otx_cpt_ucode_hdr *ucode_hdr, int *ucode_type)
> u32 i, val = 0;
> u8 nn;
>
> - strscpy(tmp_ver_str, ucode_hdr->ver_str, OTX_CPT_UCODE_VER_STR_SZ);
> + strscpy(tmp_ver_str, ucode_hdr->ver_str);
> for (i = 0; i < strlen(tmp_ver_str); i++)
> tmp_ver_str[i] = tolower(tmp_ver_str[i]);
>
> @@ -1331,7 +1331,7 @@ static ssize_t ucode_load_store(struct device *dev,
>
> eng_grps = container_of(attr, struct otx_cpt_eng_grps, ucode_load_attr);
> err_msg = "Invalid engine group format";
> - strscpy(tmp_buf, buf, OTX_CPT_UCODE_NAME_LENGTH);
> + strscpy(tmp_buf, buf);
> start = tmp_buf;
>
> has_se = has_ie = has_ae = false;
> diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c
> index 9b0887d7e62c..465f00e74623 100644
> --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c
> +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c
> @@ -74,7 +74,7 @@ static int is_2nd_ucode_used(struct otx2_cpt_eng_grp_info *eng_grp)
> static void set_ucode_filename(struct otx2_cpt_ucode *ucode,
> const char *filename)
> {
> - strscpy(ucode->filename, filename, OTX2_CPT_NAME_LENGTH);
> + strscpy(ucode->filename, filename);
> }
>
> static char *get_eng_type_str(int eng_type)
> @@ -130,7 +130,7 @@ static int get_ucode_type(struct device *dev,
> int i, val = 0;
> u8 nn;
>
> - strscpy(tmp_ver_str, ucode_hdr->ver_str, OTX2_CPT_UCODE_VER_STR_SZ);
> + strscpy(tmp_ver_str, ucode_hdr->ver_str);
> for (i = 0; i < strlen(tmp_ver_str); i++)
> tmp_ver_str[i] = tolower(tmp_ver_str[i]);
>
>
^ permalink raw reply
* [PATCH v3] crypto/algapi: fix refcount leak in crypto_register_alg()
From: Wentao Liang @ 2026-06-03 8:21 UTC (permalink / raw)
To: herbert, davem; +Cc: linux-crypto, linux-kernel, Wentao Liang, stable
When crypto_register_alg() calls crypto_check_alg() successfully,
the algorithm's refcount is set to one. If the subsequent handling
for CRYPTO_ALG_DUP_FIRST fails with ENOMEM due to a kmemdup()
error, the function returns without decrementing the refcount.
This leaves the algorithm forever pinned with a leaked reference.
Fix it by calling crypto_alg_put() on the kmemdup() failure path,
matching the error handling used elsewhere in the function.
Cc: stable@vger.kernel.org
Fixes: f1440a90465b ("crypto: api - Add support for duplicating algorithms before registration")
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
Changes in v2:
- Clarify the refcount lifecycle.
- Fix code error.
---
crypto/algapi.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 37de377719ae..260d03b328ec 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -446,8 +446,10 @@ int crypto_register_alg(struct crypto_alg *alg)
u8 *p = (u8 *)alg - algsize;
p = kmemdup(p, algsize + sizeof(*alg), GFP_KERNEL);
- if (!p)
+ if (!p) {
+ crypto_alg_put(alg);
return -ENOMEM;
+ }
alg = (void *)(p + algsize);
alg->cra_destroy = crypto_free_alg;
--
2.34.1
^ permalink raw reply related
* [PATCH v2] crypto: fix refcount leak in crypto_register_alg()
From: Wentao Liang @ 2026-06-03 8:15 UTC (permalink / raw)
To: herbert, davem; +Cc: linux-crypto, linux-kernel, Wentao Liang, stable
When crypto_check_alg() succeeds it sets the algorithm's refcount
to 1. In crypto_register_alg(), if the algorithm type requires
duplication (CRYPTO_ALG_DUP_FIRST), the code attempts a kmemdup of
the algorithm descriptor. If that allocation fails the function
returns -ENOMEM without calling crypto_alg_put() to release the
reference obtained by crypto_check_alg(), resulting in a refcount
leak.
Fix this by adding the missing crypto_alg_put() before the early
return, matching the handling of the other error paths in the
function.
Cc: stable@vger.kernel.org
Fixes: f1440a90465b ("crypto: api - Add support for duplicating algorithms before registration")
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
Changes in v2:
- Clarify the refcount lifecycle.
- Fix code error.
---
crypto/algapi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index b0e4b13131c3..260d03b328ec 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -446,9 +446,10 @@ int crypto_register_alg(struct crypto_alg *alg)
u8 *p = (u8 *)alg - algsize;
p = kmemdup(p, algsize + sizeof(*alg), GFP_KERNEL);
- if (!p)
+ if (!p) {
crypto_alg_put(alg);
return -ENOMEM;
+ }
alg = (void *)(p + algsize);
alg->cra_destroy = crypto_free_alg;
--
2.34.1
^ permalink raw reply related
* 回复: [PATCH v3 1/2] dt-bindings: rng: starfive,jh7110-trng: add jhb100, drop jh8100
From: Lianfeng Ouyang @ 2026-06-03 5:29 UTC (permalink / raw)
To: Conor Dooley
Cc: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, linux-crypto@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20260602-staple-rehire-00045d4cb667@spud>
> -----邮件原件-----
> 发件人: Conor Dooley <conor@kernel.org>
> 发送时间: 2026年6月3日 0:59
> 收件人: Lianfeng Ouyang <lianfeng.ouyang@starfivetech.com>
> 抄送: Olivia Mackall <olivia@selenic.com>; Herbert Xu
> <herbert@gondor.apana.org.au>; Rob Herring <robh@kernel.org>; Krzysztof
> Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Philipp
> Zabel <p.zabel@pengutronix.de>; linux-crypto@vger.kernel.org;
> devicetree@vger.kernel.org; linux-kernel@vger.kernel.org
> 主题: Re: [PATCH v3 1/2] dt-bindings: rng: starfive,jh7110-trng: add jhb100, drop
> jh8100
>
> On Mon, Jun 01, 2026 at 05:37:43PM +0800, lianfeng.ouyang wrote:
> > From: Lianfeng Ouyang <lianfeng.ouyang@starfivetech.com>
> >
> > - Drop "starfive,jh8100-trng" since JH8100 SoC is no longer
> > supported
> > - Add "starfive,jhb100-trng" for the JHB100 SoC TRNG.
> > - Update maintainer to current owner
> >
> > Signed-off-by: Lianfeng Ouyang <lianfeng.ouyang@starfivetech.com>
>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> pw-bot: not-applicable
>
> Although, commit messages really should not be bullet point lists,
> please keep that in mind for the future.
Thanks for the review. I'll make some changes
Best Regards,
Lianfeng Ouyang
^ permalink raw reply
* Re: [PATCH net-next v2 0/5] Consolidate FCrypt and PCBC code into net/rxrpc/
From: Eric Biggers @ 2026-06-03 5:05 UTC (permalink / raw)
To: Marc Dionne
Cc: netdev, linux-afs, David Howells, linux-crypto, linux-kernel,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman
In-Reply-To: <CAB9dFduBir-41_Ef4noEJPHsFU-++JHDxMU-6S7B8pBYynvadA@mail.gmail.com>
On Fri, May 22, 2026 at 10:06:49AM -0300, Marc Dionne wrote:
> On Fri, May 22, 2026 at 2:07 AM Eric Biggers <ebiggers@kernel.org> wrote:
> >
> > The FCrypt "block cipher" and the PCBC mode of operation are obsolete
> > and insecure. Since their only user is net/rxrpc/, they belong there,
> > not in the crypto API.
> >
> > Therefore, this series removes these algorithms from the crypto API and
> > replaces them with local implementations in net/rxrpc/.
> >
> > The local implementations are simpler too, as they avoid the crypto API
> > boilerplate.
> >
> > I don't know how to test all the code in net/rxrpc/, but everything
> > should still work. I added a KUnit test for the crypto functions.
> >
> > Changed in v2:
> > - Added missing export of fcrypt_preparekey().
> > - Write "RxRPC crypto KUnit test" instead of "RxRPC KUnit test".
> > - Rebased onto latest net-next where decryption now happens in the
> > linear buffer rxrpc_call::rx_dec_buffer, simplifying the code.
>
> Looks good in testing with our kafs test suite, forcing the use of
> rxkad with encryption.
>
> Feel free to add for the series:
> Tested-by: Marc Dionne <marc.dionne@auristor.com>
Thanks!
If there's no more feedback, could this be applied to net-next?
- Eric
^ permalink raw reply
* Re: [PATCH] crypto/algapi: fix refcount leak in crypto_register_alg()
From: Herbert Xu @ 2026-06-03 2:47 UTC (permalink / raw)
To: Wentao Liang; +Cc: davem, linux-crypto, linux-kernel, stable
In-Reply-To: <20260603024119.3693829-1-vulab@iscas.ac.cn>
On Wed, Jun 03, 2026 at 02:41:19AM +0000, Wentao Liang wrote:
> In crypto_register_alg(), if the algorithm registration fails after
> a successful crypto_alg_get() on the template algorithm, the acquired
> reference is never released. This can occur when the new algorithm is
> not allowed to be registered due to a constraint check failure.
>
> Fix the leak by adding a corresponding crypto_alg_put() call in the
> error path before returning.
>
> Cc: stable@vger.kernel.org
> Fixes: f1440a90465b ("crypto: api - Add support for duplicating algorithms before registration")
> Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
> ---
> crypto/algapi.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/crypto/algapi.c b/crypto/algapi.c
> index 37de377719ae..b0e4b13131c3 100644
> --- a/crypto/algapi.c
> +++ b/crypto/algapi.c
> @@ -447,6 +447,7 @@ int crypto_register_alg(struct crypto_alg *alg)
>
> p = kmemdup(p, algsize + sizeof(*alg), GFP_KERNEL);
> if (!p)
> + crypto_alg_put(alg);
> return -ENOMEM;
Where is this reference count coming from?
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH] crypto/algapi: fix refcount leak in crypto_register_alg()
From: Wentao Liang @ 2026-06-03 2:41 UTC (permalink / raw)
To: herbert, davem; +Cc: linux-crypto, linux-kernel, Wentao Liang, stable
In crypto_register_alg(), if the algorithm registration fails after
a successful crypto_alg_get() on the template algorithm, the acquired
reference is never released. This can occur when the new algorithm is
not allowed to be registered due to a constraint check failure.
Fix the leak by adding a corresponding crypto_alg_put() call in the
error path before returning.
Cc: stable@vger.kernel.org
Fixes: f1440a90465b ("crypto: api - Add support for duplicating algorithms before registration")
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
crypto/algapi.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 37de377719ae..b0e4b13131c3 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -447,6 +447,7 @@ int crypto_register_alg(struct crypto_alg *alg)
p = kmemdup(p, algsize + sizeof(*alg), GFP_KERNEL);
if (!p)
+ crypto_alg_put(alg);
return -ENOMEM;
alg = (void *)(p + algsize);
--
2.34.1
^ permalink raw reply related
* [PATCH v3 4/4] crypto: ccp: Fix memory leak in SEV INIT_EX path
From: Atish Patra @ 2026-06-02 22:36 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Tom Lendacky, Peter Gonda, Brijesh Singh,
Youngjae Lee, Ashish Kalra, Michael Roth, John Allen, Herbert Xu
Cc: clm, kvm, linux-kernel, linux-crypto, stable, Atish Patra,
Sashiko
In-Reply-To: <20260602-sev_snp_fixes-v3-0-24bfd3ae047c@meta.com>
From: Atish Patra <atishp@meta.com>
allocated pages in _init_ext_path are never freed and sev_init_ex_buffer
is left pointing at the leaked memory in case of any failures during the
function..
Fix by adding an error path that frees the pages and clears
sev_init_ex_buffer. Make sure we only free the memory if the failure
happens before the conversion. Otherwise, we may end up trying to free
up converted pages in case of reclaim failure. rmp_mark_pages_firmware
failures should be rare enough to avoid more code complexity to track
down which pages were reclaimed/leaked vs which are not.
Fixes: 7364a6fbca45 ("crypto: ccp: Handle non-volatile INIT_EX data when SNP is enabled")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Atish Patra <atishp@meta.com>
---
drivers/crypto/ccp/sev-dev.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index 3d4793e8e34b..57b4c1e79589 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -1540,7 +1540,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
if (sev_init_ex_buffer)
return 0;
- page = alloc_pages(GFP_KERNEL, get_order(NV_LENGTH));
+ page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(NV_LENGTH));
if (!page) {
dev_err(sev->dev, "SEV: INIT_EX NV memory allocation failed\n");
return -ENOMEM;
@@ -1550,7 +1550,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
rc = sev_read_init_ex_file();
if (rc)
- return rc;
+ goto err_free;
/* If SEV-SNP is initialized, transition to firmware page. */
if (sev->snp_initialized) {
@@ -1559,11 +1559,22 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
npages = 1UL << get_order(NV_LENGTH);
if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, true)) {
dev_err(sev->dev, "SEV: INIT_EX NV memory page state change failed.\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ /*
+ * Pages can be in an inconsistent state, don't release them back to the
+ * system.
+ */
+ goto err_reset;
}
}
return 0;
+
+err_free:
+ __free_pages(page, get_order(NV_LENGTH));
+err_reset:
+ sev_init_ex_buffer = NULL;
+ return rc;
}
static int __sev_platform_init_locked(int *error)
--
2.53.0-Meta
^ permalink raw reply related
* [PATCH v3 3/4] crypto: ccp: Fix possible deadlock in SEV init failure path
From: Atish Patra @ 2026-06-02 22:36 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Tom Lendacky, Peter Gonda, Brijesh Singh,
Youngjae Lee, Ashish Kalra, Michael Roth, John Allen, Herbert Xu
Cc: clm, kvm, linux-kernel, linux-crypto, stable, Atish Patra
In-Reply-To: <20260602-sev_snp_fixes-v3-0-24bfd3ae047c@meta.com>
From: Atish Patra <atishp@meta.com>
__sev_platform_init_handle_init_ex_path() calls
rmp_mark_pages_firmware() with locked=false while the parent
function of init_ex_path already acquired the sev_cmd_mutex.
In the case of an RMPUPDATE failure for any page after the first, the cleanup
path would invoke reclaim pages which would result in a deadlock in
sev_do_cmd.
Pass locked=true to honor the lock status of the parent function.
Fixes: 7364a6fbca45 ("crypto: ccp: Handle non-volatile INIT_EX data when SNP is enabled")
Reported-by: Chris Mason <clm@meta.com>
Assisted-by: Claude:claude-opus-4-6
Fixes: 7364a6fbca45 ("crypto: ccp: Handle non-volatile INIT_EX data when SNP is enabled")
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Atish Patra <atishp@meta.com>
---
drivers/crypto/ccp/sev-dev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index d1e9e0ac63b6..3d4793e8e34b 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -1557,7 +1557,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
unsigned long npages;
npages = 1UL << get_order(NV_LENGTH);
- if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, false)) {
+ if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, true)) {
dev_err(sev->dev, "SEV: INIT_EX NV memory page state change failed.\n");
return -ENOMEM;
}
--
2.53.0-Meta
^ permalink raw reply related
* [PATCH v3 2/4] KVM: selftests: Verify SNP VMs are rejected from migration and mirroring
From: Atish Patra @ 2026-06-02 22:36 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Tom Lendacky, Peter Gonda, Brijesh Singh,
Youngjae Lee, Ashish Kalra, Michael Roth, John Allen, Herbert Xu
Cc: clm, kvm, linux-kernel, linux-crypto, stable, Atish Patra
In-Reply-To: <20260602-sev_snp_fixes-v3-0-24bfd3ae047c@meta.com>
From: Atish Patra <atishp@meta.com>
Migration and mirroring of SEV-SNP VMs are not supported yet.
Add two selftests that verify KVM rejects intra-host migration and
mirroring when the source VM is an SNP VM, so the restriction stays enforced
until proper SNP state transfer is implemented.
Signed-off-by: Atish Patra <atishp@meta.com>
---
.../testing/selftests/kvm/x86/sev_migrate_tests.c | 47 ++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/tools/testing/selftests/kvm/x86/sev_migrate_tests.c b/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
index 6b0928e69051..acef6ab26d3d 100644
--- a/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
+++ b/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
@@ -313,6 +313,49 @@ static void test_sev_mirror_parameters(void)
kvm_vm_free(vm_no_vcpu);
}
+static void test_sev_snp_migrate_reject(void)
+{
+ struct kvm_vm *src_vm, *dst_vm;
+ int ret;
+
+ src_vm = vm_create_barebones_type(KVM_X86_SNP_VM);
+ snp_vm_init(src_vm);
+ __vm_vcpu_add(src_vm, 0);
+ vm_sev_launch(src_vm, snp_default_policy(), NULL);
+
+ dst_vm = vm_create_barebones_type(KVM_X86_SNP_VM);
+ __vm_vcpu_add(dst_vm, 0);
+
+ ret = __sev_migrate_from(dst_vm, src_vm);
+ TEST_ASSERT(ret == -1 && errno == EINVAL,
+ "SNP VM migration should be rejected. ret: %d, errno: %d",
+ ret, errno);
+
+ kvm_vm_free(src_vm);
+ kvm_vm_free(dst_vm);
+}
+
+static void test_sev_snp_mirror_reject(void)
+{
+ struct kvm_vm *src_vm, *dst_vm;
+ int ret;
+
+ src_vm = vm_create_barebones_type(KVM_X86_SNP_VM);
+ snp_vm_init(src_vm);
+ __vm_vcpu_add(src_vm, 0);
+ vm_sev_launch(src_vm, snp_default_policy(), NULL);
+
+ dst_vm = aux_vm_create(false);
+
+ ret = __sev_mirror_create(dst_vm, src_vm);
+ TEST_ASSERT(ret == -1 && errno == EINVAL,
+ "SNP VM mirroring should be rejected. ret: %d, errno: %d",
+ ret, errno);
+
+ kvm_vm_free(src_vm);
+ kvm_vm_free(dst_vm);
+}
+
static void test_sev_move_copy(void)
{
struct kvm_vm *dst_vm, *dst2_vm, *dst3_vm, *sev_vm, *mirror_vm,
@@ -384,12 +427,16 @@ int main(int argc, char *argv[])
test_sev_migrate_parameters();
if (kvm_has_cap(KVM_CAP_VM_COPY_ENC_CONTEXT_FROM))
test_sev_move_copy();
+ if (kvm_cpu_has(X86_FEATURE_SEV_SNP))
+ test_sev_snp_migrate_reject();
}
if (kvm_has_cap(KVM_CAP_VM_COPY_ENC_CONTEXT_FROM)) {
test_sev_mirror(/* es= */ false);
if (have_sev_es)
test_sev_mirror(/* es= */ true);
test_sev_mirror_parameters();
+ if (kvm_cpu_has(X86_FEATURE_SEV_SNP))
+ test_sev_snp_mirror_reject();
}
return 0;
}
--
2.53.0-Meta
^ permalink raw reply related
* [PATCH v3 1/4] KVM: SEV: Do not allow intra-host migration/mirroring of SNP VMs
From: Atish Patra @ 2026-06-02 22:36 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Tom Lendacky, Peter Gonda, Brijesh Singh,
Youngjae Lee, Ashish Kalra, Michael Roth, John Allen, Herbert Xu
Cc: clm, kvm, linux-kernel, linux-crypto, stable, Atish Patra,
Sashiko
In-Reply-To: <20260602-sev_snp_fixes-v3-0-24bfd3ae047c@meta.com>
From: Atish Patra <atishp@meta.com>
The intra-host migration/mirroring feature is not fully implemented for
SEV-SNP VMs. The proper migration requires additional SNP-specific
state such as guest_req_mutex, guest_req_buf, and guest_resp_buf to be
transferred or initialized on the destination.
The SNP VM mirroring requires vmsa features to be copied as well otherwise
ASID would be bound to SNP range while VM is detected as a SEV VM.
Reject SNP source VMs in migration/mirroring until proper SNP state
transfer is implemented.
Fixes: 1dfe571c12cf ("KVM: SEV: Add initial SEV-SNP support")
Reported-by: Chris Mason <clm@meta.com>
Reported-by: Sashiko <sashiko-bot@kernel.org>
Assisted-by: Claude:claude-opus-4-6
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Atish Patra <atishp@meta.com>
---
arch/x86/kvm/svm/sev.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index c2126b3c3072..a34326a77290 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -2141,8 +2141,10 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
if (ret)
return ret;
+ /* Do not allow SNP VM migration until additional state transfer is implemented */
if (kvm->arch.vm_type != source_kvm->arch.vm_type ||
- sev_guest(kvm) || !sev_guest(source_kvm)) {
+ sev_guest(kvm) || !sev_guest(source_kvm) ||
+ sev_snp_guest(source_kvm)) {
ret = -EINVAL;
goto out_unlock;
}
@@ -2863,8 +2865,10 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
* disallow out-of-band SEV/SEV-ES init if the target is already an
* SEV guest, or if vCPUs have been created. KVM relies on vCPUs being
* created after SEV/SEV-ES initialization, e.g. to init intercepts.
+ * Also do not allow SNP VM mirroring until additional state transfer is implemented.
*/
if (sev_guest(kvm) || !sev_guest(source_kvm) ||
+ sev_snp_guest(source_kvm) ||
is_mirroring_enc_context(source_kvm) || kvm->created_vcpus) {
ret = -EINVAL;
goto e_unlock;
--
2.53.0-Meta
^ permalink raw reply related
* [PATCH v3 0/4] KVM: Miscellaneous SEV/SNP related fixes
From: Atish Patra @ 2026-06-02 22:36 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Borislav Petkov, Dave Hansen,
x86, H. Peter Anvin, Tom Lendacky, Peter Gonda, Brijesh Singh,
Youngjae Lee, Ashish Kalra, Michael Roth, John Allen, Herbert Xu
Cc: clm, kvm, linux-kernel, linux-crypto, stable, Atish Patra,
Sashiko
This series addresses a few issues found during code audit of the
KVM SEV/SNP and CCP driver code. The fixes include a incorrect lock state
and incomplete state handling during intra-host migration for SNP VMs.
To: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
To: Borislav Petkov <bp@alien8.de>
To: Dave Hansen <dave.hansen@linux.intel.com>
To: x86@kernel.org
To: H. Peter Anvin <hpa@zytor.com>
To: Tom Lendacky <thomas.lendacky@amd.com>
To: Peter Gonda <pgonda@google.com>
To: Brijesh Singh <brijesh.singh@amd.com>
To: Youngjae Lee <youngjaelee@meta.com>
To: Ashish Kalra <ashish.kalra@amd.com>
To: Michael Roth <michael.roth@amd.com>
To: John Allen <john.allen@amd.com>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: clm@meta.com
Cc: kvm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-crypto@vger.kernel.org
Cc: stable@vger.kernel.org
Signed-off-by: Atish Patra <atishp@meta.com>
---
Changes in v3:
- Added comments, fixed commit messages and fixes tag as per discussions on v2.
- sev_init_ex_buffer initialized with zero at allocation to prevent any kernel
data leak in case of init_ex_file is not present. Reported by Sashiko
- Link to v2: https://lore.kernel.org/r/20260601-sev_snp_fixes-v2-0-611891b28a86@meta.com
Changes in v2:
- Added fixes based on the reports by Sashiko.
- Added a kselftest for validating SNP VM mirroring/migration rejection.
- Link to v1: https://lore.kernel.org/r/20260528-sev_snp_fixes-v1-0-d67a08151779@meta.com
---
Atish Patra (4):
KVM: SEV: Do not allow intra-host migration/mirroring of SNP VMs
KVM: selftests: Verify SNP VMs are rejected from migration and mirroring
crypto: ccp: Fix possible deadlock in SEV init failure path
crypto: ccp: Fix memory leak in SEV INIT_EX path
arch/x86/kvm/svm/sev.c | 6 ++-
drivers/crypto/ccp/sev-dev.c | 19 +++++++--
.../testing/selftests/kvm/x86/sev_migrate_tests.c | 47 ++++++++++++++++++++++
3 files changed, 67 insertions(+), 5 deletions(-)
---
base-commit: e7ae89a0c97ce2b68b0983cd01eda67cf373517d
change-id: 20260525-sev_snp_fixes-0b73789c1a91
Best regards,
--
Atish Patra <atishp@meta.com>
^ permalink raw reply
* [PATCH] crypto: atmel-ecc - drop dead code in atmel_ecdh_max_size
From: Thorsten Blum @ 2026-06-02 22:25 UTC (permalink / raw)
To: Thorsten Blum, Herbert Xu, David S. Miller, Nicolas Ferre,
Alexandre Belloni, Claudiu Beznea
Cc: linux-crypto, linux-arm-kernel, linux-kernel
atmel_ecdh_init_tfm() always allocates ctx->fallback, so it is never
NULL in atmel_ecdh_max_size(). Remove the dead code and return
crypto_kpp_maxsize() directly.
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
drivers/crypto/atmel-ecc.c | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 9c380351d2f9..6a1716175b30 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -284,15 +284,7 @@ static unsigned int atmel_ecdh_max_size(struct crypto_kpp *tfm)
{
struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm);
- if (ctx->fallback)
- return crypto_kpp_maxsize(ctx->fallback);
-
- /*
- * The device only supports NIST P256 ECC keys. The public key size will
- * always be the same. Use a macro for the key size to avoid unnecessary
- * computations.
- */
- return ATMEL_ECC_PUBKEY_SIZE;
+ return crypto_kpp_maxsize(ctx->fallback);
}
static struct kpp_alg atmel_ecdh_nist_p256 = {
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox