Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
342 changes: 342 additions & 0 deletions pocs/linux/kernelctf/CVE-2024-26583_lts/docs/exploit.md

Large diffs are not rendered by default.

Empty file.
49 changes: 49 additions & 0 deletions pocs/linux/kernelctf/CVE-2024-26583_lts/docs/vulnerability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
## Requirements to trigger the vulnerability

- Kernel configuration: CONFIG_TLS and one of [CONFIG_CRYPTO_PCRYPT, CONFIG_CRYPTO_CRYPTD]
- User namespaces required: no

## Commit which introduced the vulnerability

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0cada33241d9de205522e3858b18e506ca5cce2c

## Commit which fixed the vulnerability

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=aec7961916f3f9e88766e2688992da6980f11b8d

## Affected kernel versions

Introduced in 4.20. Fixed in 6.1.78, 5.15.159 and other stable trees.

## Affected component, subsystem

net/tls

## Description

TLS decryption works by calling recvmsg() on a TLS configured socket.
This will retrieve an encrypted message from the network stack and perform decryption.
AEAD decryption work is submitted to the crypto subsystem in tls_do_decryption(), setting tls_decrypt_done() as a callback and calling crypto_aead_decrypt().

If decryption is done asynchronously, crypto_aead_decrypt() returns immediately with EINPROGRESS value instead of waiting.
Execution then returns to tls_sw_recvmsg() which waits for the async crypto operations to be done using a completion mechanism.

When decryption is finished, the crypto subsystem calls tls_decrypt_done() callback function, which calls complete() allowing tls_sw_recvmsg() to exit. When recvmsg() returns, the socket is no longer locked and it is now possible to close it, which causes all associated objects to be freed.

Relevant tls_decrypt_done() code:

```
...
spin_lock_bh(&ctx->decrypt_compl_lock);
if (!atomic_dec_return(&ctx->decrypt_pending))
[1] complete(&ctx->async_wait.completion);
[2] spin_unlock_bh(&ctx->decrypt_compl_lock);
}

```

The bug is a race condition - calling complete at [1] allows the socket to be closed, which causes the ctx object to be freed, but ctx is later used as an argument to spin_unlock_bh()

If an attacker manages to close the socket and reallocate freed ctx with controlled data between points [1] and [2], he can manipulate memory using spin_unlock_bh().

This is a very limited write primitive, as it only allows changing an 8 bit integer value of 1 to 0 at a fixed position in memory (spinlock is basically a 32 bit unsigned integer with the least significant byte used for the actual lock value).
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
INCLUDES =
LIBS = -pthread -ldl
CFLAGS = -fomit-frame-pointer -static -fcf-protection=none

exploit: exploit.c kernelver_6.1.74.h
gcc -o $@ exploit.c $(INCLUDES) $(CFLAGS) $(LIBS)

prerequisites:
sudo apt-get install libkeyutils-dev
Binary file not shown.
Loading
Loading