* [PATCH] lib/crypto/mpi: Fix heap OOB write in mpi_powm() when res aliases input
@ 2026-11-02 6:42 Maholi Tumanggor
2026-11-02 6:49 ` sashiko-bot
2026-11-02 9:25 ` [PATCH v2] " Maholi Tumanggor
0 siblings, 2 replies; 5+ messages in thread
From: Maholi Tumanggor @ 2026-11-02 6:42 UTC (permalink / raw)
To: linux-crypto; +Cc: herbert, davem, Maholi Tumanggor
When mpi_powm() is called with res->alloced < size and res->d aliases
base->d or exp->d, assign_rp is set to 1 and a new buffer is allocated
for rp. However the final write-back block unconditionally writes the
result into res->d (the original undersized buffer) instead of rp,
causing a heap out-of-bounds write and a subsequent use-after-free when
mpi_assign_limb_space() frees and re-assigns the corrupted buffer.
Fix by skipping the copy into res->d when assign_rp is set, keeping
the result in rp so that mpi_assign_limb_space() can correctly transfer
ownership.
Signed-off-by: Maholi Tumanggor <maholitumanggor@gmail.com>
---
lib/crypto/mpi/mpi-pow.c | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/lib/crypto/mpi/mpi-pow.c b/lib/crypto/mpi/mpi-pow.c
index 9e695a3bd..06038ac8f 100644
--- a/lib/crypto/mpi/mpi-pow.c
+++ b/lib/crypto/mpi/mpi-pow.c
@@ -187,14 +187,14 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
if (!tspace) {
tsize = 2 * rsize;
tspace =
- mpi_alloc_limb_space(tsize);
+ mpi_alloc_limb_space(tsize);
if (!tspace)
goto enomem;
} else if (tsize < (2 * rsize)) {
mpi_free_limb_space(tspace);
tsize = 2 * rsize;
tspace =
- mpi_alloc_limb_space(tsize);
+ mpi_alloc_limb_space(tsize);
if (!tspace)
goto enomem;
}
@@ -204,7 +204,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
xsize = 2 * rsize;
if (xsize > msize) {
mpihelp_divrem(xp + msize, 0, xp, xsize,
- mp, msize);
+ mp, msize);
xsize = msize;
}
@@ -216,21 +216,21 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
if (bsize < KARATSUBA_THRESHOLD) {
mpi_limb_t tmp;
if (mpihelp_mul
- (xp, rp, rsize, bp, bsize,
- &tmp) < 0)
+ (xp, rp, rsize, bp, bsize,
+ &tmp) < 0)
goto enomem;
} else {
if (mpihelp_mul_karatsuba_case
- (xp, rp, rsize, bp, bsize,
- &karactx) < 0)
+ (xp, rp, rsize, bp, bsize,
+ &karactx) < 0)
goto enomem;
}
xsize = rsize + bsize;
if (xsize > msize) {
mpihelp_divrem(xp + msize, 0,
- xp, xsize, mp,
- msize);
+ xp, xsize, mp,
+ msize);
xsize = msize;
}
@@ -256,14 +256,16 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
* might be, see above).
*/
if (mod_shift_cnt) {
- carry_limb =
- mpihelp_lshift(res->d, rp, rsize, mod_shift_cnt);
+ mpi_ptr_t dst = assign_rp ? rp : res->d;
+
+ carry_limb = mpihelp_lshift(dst, rp, rsize, mod_shift_cnt);
+ if (!assign_rp)
rp = res->d;
if (carry_limb) {
- rp[rsize] = carry_limb;
- rsize++;
+ rp[rsize] = carry_limb;
+ rsize++;
}
- } else {
+ } else if (!assign_rp) {
MPN_COPY(res->d, rp, rsize);
rp = res->d;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] lib/crypto/mpi: Fix heap OOB write in mpi_powm() when res aliases input
2026-11-02 6:42 [PATCH] lib/crypto/mpi: Fix heap OOB write in mpi_powm() when res aliases input Maholi Tumanggor
@ 2026-11-02 6:49 ` sashiko-bot
2026-11-02 9:25 ` [PATCH v2] " Maholi Tumanggor
1 sibling, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-11-02 6:49 UTC (permalink / raw)
To: Maholi Tumanggor, linux-crypto; +Cc: herbert, davem
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] lib/crypto/mpi: use-after-free and leak in mpi_powm() when assign_rp is set
--
commit 85051cb2fd0529447a03f7f3bbc383a2addcb07d
Author: Maholi Tumanggor <maholitumanggor@gmail.com>
lib/crypto/mpi: Fix heap OOB write in mpi_powm() when res aliases input
This commit avoids writing the exponentiation result into an undersized
res->d buffer in mpi_powm() when assign_rp is set due to res->d aliasing
an input operand.
> diff --git a/lib/crypto/mpi/mpi-pow.c b/lib/crypto/mpi/mpi-pow.c
> index 9e695a3bda3a0..06038ac8f92ac 100644
> --- a/lib/crypto/mpi/mpi-pow.c
> +++ b/lib/crypto/mpi/mpi-pow.c
[ ... ]
> @@ -256,14 +256,16 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
> * might be, see above).
> */
> if (mod_shift_cnt) {
> - carry_limb =
> - mpihelp_lshift(res->d, rp, rsize, mod_shift_cnt);
> + mpi_ptr_t dst = assign_rp ? rp : res->d;
> +
> + carry_limb = mpihelp_lshift(dst, rp, rsize, mod_shift_cnt);
> + if (!assign_rp)
> rp = res->d;
> if (carry_limb) {
> - rp[rsize] = carry_limb;
> - rsize++;
> + rp[rsize] = carry_limb;
> + rsize++;
> }
> - } else {
> + } else if (!assign_rp) {
> MPN_COPY(res->d, rp, rsize);
> rp = res->d;
> }
[Severity: Critical]
When assign_rp is set in lib/crypto/mpi/mpi-pow.c:mpi_powm() because
res->alloced < size and rp aliases bp, ep, or mp, a new limb buffer is
allocated directly into rp without saving a marker pointer:
if (res->alloced < size) {
if (rp == ep || rp == mp || rp == bp) {
rp = mpi_alloc_limb_space(size);
if (!rp)
goto enomem;
assign_rp = 1;
Later in the exponentiation loop, rp and xp are swapped after every
squaring step and after every multiplication step:
xp = xp_marker = mpi_alloc_limb_space(2 * (msize + 1));
...
for (;;) {
while (c) {
...
swap(rp, xp);
rsize = xsize;
if ((mpi_limb_signed_t) e < 0) {
...
swap(rp, xp);
rsize = xsize;
}
If the exponent causes an odd number of swap(rp, xp) operations (for
example when exp has an odd number of zero bits after the most significant
bit, such as exp = 2 or exp = 65537), the loop finishes with rp pointing
to xp_marker and the block-local xp pointing to the buffer allocated for
assign_rp.
With this change, when assign_rp is 1, rp is left pointing to xp_marker
while xp goes out of scope. At the end of mpi_powm():
if (assign_rp)
mpi_assign_limb_space(res, rp, size);
...
if (xp_marker)
mpi_free_limb_space(xp_marker);
Wouldn't mpi_assign_limb_space() assign xp_marker to res->d and
mpi_free_limb_space(xp_marker) immediately zero and free it, leaving
res->d pointing to freed memory while leaking the limb buffer originally
allocated for rp?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261102064225.2271-1-maholitumanggor@gmail.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2] lib/crypto/mpi: Fix heap OOB write in mpi_powm() when res aliases input
2026-11-02 6:42 [PATCH] lib/crypto/mpi: Fix heap OOB write in mpi_powm() when res aliases input Maholi Tumanggor
2026-11-02 6:49 ` sashiko-bot
@ 2026-11-02 9:25 ` Maholi Tumanggor
2026-11-02 13:03 ` sashiko-bot
2026-11-02 18:12 ` Eric Biggers
1 sibling, 2 replies; 5+ messages in thread
From: Maholi Tumanggor @ 2026-11-02 9:25 UTC (permalink / raw)
To: linux-crypto; +Cc: herbert, davem, Maholi Tumanggor
When mpi_powm() is called with res->alloced < size and res->d aliases
base->d or exp->d, assign_rp is set to 1 and a new buffer is allocated
for rp. However the final write-back block unconditionally writes the
result into res->d (the original undersized buffer) instead of rp,
causing a heap out-of-bounds write and a subsequent use-after-free when
mpi_assign_limb_space() frees and re-assigns the corrupted buffer.
The previous fix (v1) introduced a new issue: inside the exponentiation
loop rp and xp are swapped after each squaring/multiplication step, so
after the loop rp may point to xp_marker instead of the originally
allocated buffer. Fix by saving the allocation pointer in rp_alloc at
the time of allocation, then using rp_alloc as the write-back destination
so mpi_assign_limb_space() always receives the correct buffer regardless
of how many swaps occurred in the loop.
Confirmed via SLUB debug (slub_debug=FZPU) on kernel 6.8.0-147-generic
(Ubuntu 24.04): two BUG reports (Right Redzone overwritten and Freepointer
corrupt) are triggered by mpi_powm(base, base, exp, mod) with base->alloced
smaller than required, and are absent after this fix.
Signed-off-by: Maholi Tumanggor <maholitumanggor@gmail.com>
---
lib/crypto/mpi/mpi-pow.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/lib/crypto/mpi/mpi-pow.c b/lib/crypto/mpi/mpi-pow.c
index 9e695a3bd..f4df9fbcb 100644
--- a/lib/crypto/mpi/mpi-pow.c
+++ b/lib/crypto/mpi/mpi-pow.c
@@ -28,6 +28,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
mpi_ptr_t mp_marker = NULL, bp_marker = NULL, ep_marker = NULL;
struct karatsuba_ctx karactx = {};
mpi_ptr_t xp_marker = NULL;
+ mpi_ptr_t rp_alloc = NULL;
mpi_ptr_t tspace = NULL;
mpi_ptr_t rp, ep, mp, bp;
mpi_size_t esize, msize, bsize, rsize;
@@ -256,16 +257,23 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
* might be, see above).
*/
if (mod_shift_cnt) {
- carry_limb =
- mpihelp_lshift(res->d, rp, rsize, mod_shift_cnt);
- rp = res->d;
+ mpi_ptr_t dst = assign_rp ? rp_alloc : res->d;
+
+ carry_limb = mpihelp_lshift(dst, rp, rsize, mod_shift_cnt);
+ rp = dst;
if (carry_limb) {
rp[rsize] = carry_limb;
rsize++;
}
} else {
- MPN_COPY(res->d, rp, rsize);
- rp = res->d;
+ if (assign_rp) {
+ if (rp != rp_alloc)
+ MPN_COPY(rp_alloc, rp, rsize);
+ rp = rp_alloc;
+ } else {
+ MPN_COPY(res->d, rp, rsize);
+ rp = res->d;
+ }
}
if (rsize >= msize) {
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2] lib/crypto/mpi: Fix heap OOB write in mpi_powm() when res aliases input
2026-11-02 9:25 ` [PATCH v2] " Maholi Tumanggor
@ 2026-11-02 13:03 ` sashiko-bot
2026-11-02 18:12 ` Eric Biggers
1 sibling, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-11-02 13:03 UTC (permalink / raw)
To: Maholi Tumanggor, linux-crypto; +Cc: herbert, davem
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] lib/crypto/mpi: NULL dereference in mpi_powm() due to unassigned rp_alloc
--
commit eb877144fed936eb853d022502854e67c6b7e317
Author: Maholi Tumanggor <maholitumanggor@gmail.com>
lib/crypto/mpi: Fix heap OOB write in mpi_powm() when res aliases input
This commit attempts to fix an out-of-bounds write in mpi_powm() when res
aliases an input operand and requires reallocation by introducing rp_alloc
as the write-back destination buffer when assign_rp is set.
> diff --git a/lib/crypto/mpi/mpi-pow.c b/lib/crypto/mpi/mpi-pow.c
> index 9e695a3bda3a0..f4df9fbcbc2c4 100644
> --- a/lib/crypto/mpi/mpi-pow.c
> +++ b/lib/crypto/mpi/mpi-pow.c
> @@ -28,6 +28,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
> mpi_ptr_t mp_marker = NULL, bp_marker = NULL, ep_marker = NULL;
> struct karatsuba_ctx karactx = {};
> mpi_ptr_t xp_marker = NULL;
> + mpi_ptr_t rp_alloc = NULL;
> mpi_ptr_t tspace = NULL;
> mpi_ptr_t rp, ep, mp, bp;
> mpi_size_t esize, msize, bsize, rsize;
> @@ -256,16 +257,23 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
> * might be, see above).
> */
> if (mod_shift_cnt) {
> - carry_limb =
> - mpihelp_lshift(res->d, rp, rsize, mod_shift_cnt);
> - rp = res->d;
> + mpi_ptr_t dst = assign_rp ? rp_alloc : res->d;
> +
> + carry_limb = mpihelp_lshift(dst, rp, rsize, mod_shift_cnt);
> + rp = dst;
> if (carry_limb) {
> rp[rsize] = carry_limb;
> rsize++;
> }
> } else {
> - MPN_COPY(res->d, rp, rsize);
> - rp = res->d;
> + if (assign_rp) {
> + if (rp != rp_alloc)
> + MPN_COPY(rp_alloc, rp, rsize);
> + rp = rp_alloc;
> + } else {
> + MPN_COPY(res->d, rp, rsize);
> + rp = res->d;
> + }
> }
[Severity: Critical]
As reported by Sashiko on v1 [1], rp_alloc is initialized to NULL in
mpi_powm(), but is it ever assigned when the new limb buffer is allocated?
In lib/crypto/mpi/mpi-pow.c:mpi_powm(), when res->alloced < size and rp
aliases an input operand:
if (res->alloced < size) {
if (rp == ep || rp == mp || rp == bp) {
rp = mpi_alloc_limb_space(size);
if (!rp)
goto enomem;
assign_rp = 1;
}
rp_alloc is not updated here and remains NULL.
When execution reaches the write-back block with assign_rp set to 1, won't
mpihelp_lshift() (when mod_shift_cnt is non-zero) or MPN_COPY() (when
mod_shift_cnt is zero) dereference a NULL rp_alloc pointer, and overwrite
rp with NULL so the limb buffer allocated via mpi_alloc_limb_space() is
also leaked?
[1] https://lore.kernel.org/r/20261102064225.2271-1-maholitumanggor@gmail.com
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261102092550.2633-1-maholitumanggor@gmail.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] lib/crypto/mpi: Fix heap OOB write in mpi_powm() when res aliases input
2026-11-02 9:25 ` [PATCH v2] " Maholi Tumanggor
2026-11-02 13:03 ` sashiko-bot
@ 2026-11-02 18:12 ` Eric Biggers
1 sibling, 0 replies; 5+ messages in thread
From: Eric Biggers @ 2026-11-02 18:12 UTC (permalink / raw)
To: Maholi Tumanggor; +Cc: linux-crypto, herbert, davem
On Mon, Nov 02, 2026 at 09:25:50AM +0000, Maholi Tumanggor wrote:
> When mpi_powm() is called with res->alloced < size and res->d aliases
> base->d or exp->d, assign_rp is set to 1 and a new buffer is allocated
> for rp. However the final write-back block unconditionally writes the
> result into res->d (the original undersized buffer) instead of rp,
> causing a heap out-of-bounds write and a subsequent use-after-free when
> mpi_assign_limb_space() frees and re-assigns the corrupted buffer.
>
> The previous fix (v1) introduced a new issue: inside the exponentiation
> loop rp and xp are swapped after each squaring/multiplication step, so
> after the loop rp may point to xp_marker instead of the originally
> allocated buffer. Fix by saving the allocation pointer in rp_alloc at
> the time of allocation, then using rp_alloc as the write-back destination
> so mpi_assign_limb_space() always receives the correct buffer regardless
> of how many swaps occurred in the loop.
>
> Confirmed via SLUB debug (slub_debug=FZPU) on kernel 6.8.0-147-generic
> (Ubuntu 24.04): two BUG reports (Right Redzone overwritten and Freepointer
> corrupt) are triggered by mpi_powm(base, base, exp, mod) with base->alloced
> smaller than required, and are absent after this fix.
>
> Signed-off-by: Maholi Tumanggor <maholitumanggor@gmail.com>
Is this issue actually reachable from any existing kernel code, such as
RSA or DH? The commit message needs to mention this. If it's
reachable, explain how to reach it.
If this fixes a bug, there also needs to be a Fixes tag. Fixing a bug
in a previous, unapplied version of this same patch doesn't count.
And finally, please see the Sashiko review, which had a finding.
- Eric
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-02 18:12 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-02 6:42 [PATCH] lib/crypto/mpi: Fix heap OOB write in mpi_powm() when res aliases input Maholi Tumanggor
2026-11-02 6:49 ` sashiko-bot
2026-11-02 9:25 ` [PATCH v2] " Maholi Tumanggor
2026-11-02 13:03 ` sashiko-bot
2026-11-02 18:12 ` Eric Biggers
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox