All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] crypto: algif_skcipher - fix AIO IV race in stable trees
@ 2026-07-16  2:58 Muhammet Kaan KILINÇ
  2026-07-16  2:58 ` [PATCH v3 1/2] crypto: algif_skcipher - force synchronous processing Muhammet Kaan KILINÇ
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Muhammet Kaan KILINÇ @ 2026-07-16  2:58 UTC (permalink / raw)
  To: stable, gregkh, sashal
  Cc: linux-crypto, herbert, ebiggers, Muhammet Kaan KILINÇ

The AF_ALG skcipher AIO path passes the socket-wide ctx->iv as a raw
pointer into the async request. After io_submit() the socket lock is
dropped and the request is processed by a worker, which dereferences
ctx->iv only later. A concurrent sendmsg(ALG_SET_IV) on the same socket
can overwrite ctx->iv inside this window, so the in-flight request runs
under an attacker-controlled IV. For CTR and other stream modes this is
IV/keystream reuse and lets an unprivileged user recover the plaintext
of a concurrent operation.

Both patches fix this the same way: force the operation synchronous, so
ctx->iv is only ever dereferenced under the socket lock held by
recvmsg(). They are split only because the surrounding code differs
between trees, not because the approach differs.

v2 used a per-request IV snapshot for the async path instead. Sasha
Levin pointed out that this is wrong, and it is: for ciphers with
statesize == 0 - which includes cbc and ctr - skcipher_prepare_alg()
installs skcipher_noimport()/skcipher_noexport(), so ctx->state carries
nothing and the MSG_MORE inter-chunk IV chaining is carried solely by
the in-place req->iv writeback. A snapshot redirects that writeback into
per-request memory that af_alg_free_resources() releases on completion,
so AIO + MSG_MORE with cbc/ctr silently produces wrong output. Writing
the IV back from the completion callback instead is not possible either:
that would require lock_sock() there, but the callback can run in
softirq/atomic context, so it must not sleep. Forcing the operation
synchronous avoids both problems and leaves the req->iv writeback
landing in ctx->iv as before.

Mainline removed the AIO socket path entirely in commit fcc77d33a34c
("net: Remove support for AIO on sockets"), which is what closes this
race upstream: the sync/async split no longer exists there, so mainline
is not affected. That removal landed after 7.1, so 7.1.y is still
affected along with every older supported tree. That commit is a
tree-wide removal across net/ and does not apply to these trees as-is,
so this is sent under option 3 of
stable-kernel-rules.rst: a change equivalent to one already mainlined,
adjusted for the older series. The equivalence is in the end state for
this file - algif_skcipher never processes an AIO request
asynchronously - and the deviation is that these patches touch only
crypto/algif_skcipher.c rather than removing AIO socket support across
the tree, which would be far too invasive for stable. io_submit() now
completes synchronously, which is valid for the AIO interface; AF_ALG
async is rarely used in practice.

The patches are not tagged as a port of that commit, because they share
no code with it: the equivalence is functional, not textual. It is
also checkable: after patch 1, _skcipher_recvmsg() matches mainline's
crypto/algif_skcipher.c as it stands today - no msg_iocb branch, no
algif_skcipher_done(), a single crypto_wait_req() - down to the same
now-dead -EIOCBQUEUED check left in place in skcipher_recvmsg().

All seven currently supported stable trees still carry the async branch
and are affected. Please apply, in two variants because the surrounding
code differs:

  - patch 1 to 7.1.y, 6.18.y and 6.12.y, which have ctx->state, cflags
    and algif_skcipher_export().
  - patch 2 to 6.6.y, 6.1.y, 5.15.y and 5.10.y, which have none of
    those.

Each patch applies cleanly to every tree listed for it, as of 7.1.3,
6.18.38, 6.12.95, 6.6.144, 6.1.177, 5.15.211 and 5.10.260.

This is distinct from CVE-2026-31677 (a skcipher receive-accounting
fix); it is an IV-handling race, not a receive-space guardrail.

Reported to security@kernel.org on 2026-06-07 (follow-up 2026-06-19, no
response). As the mainline removal is independent of that report and is
not backportable, I am sending the stable fix here.

Verified on 6.19.14. That tree is no longer supported, but
crypto/algif_skcipher.c is byte-identical there and on 7.1.y, 6.18.y
and 6.12.y, so this exercises exactly the code patch 1 targets. Same
tests across three kernels:

                          MSG_MORE chained     AIO IV race over 200000
                          output correct?      ops: times the attacker
                                               IV was injected
  unpatched               yes                  2857 (victim plaintext
                                               recovered on all of them)
  v2 snapshot             NO, silently wrong   0
  this patch, force-sync  yes                  0

  - MSG_MORE chaining: two 16 byte chunks over separate io_submit()
    calls must equal the single-shot 32 byte reference. Checked for
    ctr(aes), cbc(aes) and the cryptd() variants of both, which
    exercise deferred completion. The v2 snapshot fails all of them
    (first chunk correct, second chunk encrypted under the stale IV);
    unpatched and this patch both pass, byte-identical output.
  - Race: a concurrent sendmsg(ALG_SET_IV) hammer against 200000 AIO
    encrypt ops recovers the victim plaintext on the unpatched kernel
    and injects nothing on the patched one.

This supersedes v1 and v2:
  https://lore.kernel.org/linux-crypto/20260705220112.2522-1-muhammetkaankilinc@gmail.com
  https://lore.kernel.org/linux-crypto/20260712022618.1665-1-muhammetkaankilinc@gmail.com

Changes in v3: both patches now force the operation synchronous. The v2
snapshot approach in patch 1 is dropped entirely, along with the framing
that it mirrors commit 5aa58c3a572b ("crypto: algif_aead - snapshot IV
for async AEAD requests"). That comparison was wrong: aead has no
inter-request IV chaining, skcipher does. Thanks to Sasha Levin for
catching this.

A working PoC is available to maintainers on request; it will be
published after the fix is picked up by the stable trees.

Muhammet Kaan KILINÇ (2):
  crypto: algif_skcipher - force synchronous processing
  crypto: algif_skcipher - force synchronous processing on trees without
    ctx->state

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-07-17  1:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16  2:58 [PATCH v3 0/2] crypto: algif_skcipher - fix AIO IV race in stable trees Muhammet Kaan KILINÇ
2026-07-16  2:58 ` [PATCH v3 1/2] crypto: algif_skcipher - force synchronous processing Muhammet Kaan KILINÇ
2026-07-16  2:58 ` [PATCH v3 2/2] crypto: algif_skcipher - force synchronous processing on trees without ctx->state Muhammet Kaan KILINÇ
2026-07-17  1:37 ` [PATCH v3 0/2] crypto: algif_skcipher - fix AIO IV race in stable trees Sasha Levin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.