CVE-2025-38734 in Linux
Sumário
de VulDB • 10/06/2026
Based on the crash log and the analysis provided, here is the explanation of the bug and the proposed fix.
### Problem Analysis
The kernel panic occurs in `smc_listen_work` due to a **Use-After-Free (UAF)** or **NULL Pointer Dereference** on `newclcsock->sk`.
1. **Root Cause**: * The function `smc_listen_out_connected()` is called. * Inside this function, `release_sock()` is called, which triggers `sk->sk_data_ready()`. * If the user-space application immediately calls `accept()` and then `close()` on the new socket, the socket's reference count may drop to zero, and the socket structure (`sk`) is freed or set to `NULL`. * After `smc_listen_out_connected()` returns, the code attempts to access `newclcsock->sk` for statistics (`SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk))`). * Since `newclcsock->sk` is now `NULL`, dereferencing it causes a page fault (CR2: `0x30` indicates an invalid address, likely due to offset from NULL).
2. **Race Condition**: The race is between the kernel's socket cleanup (triggered by `close()`) and the kernel's SMC listener work item. The critical section is not properly protected against the socket being freed during the `release_sock()` call inside `smc_listen_out_connected()`.
### Proposed Fix
As suggested in the description, the simplest and most effective fix is to **move the statistics update (`SMC_STAT_SERV_SUCC_INC`) before the call to `smc_listen_out_connected()`**.
This ensures that the statistics are updated while `newclcsock->sk` is still valid and guaranteed to be non-NULL.
### Code Patch
Here is the likely location in the kernel source (e.g., `net/smc/smc_listen.c`) and the fix:
```c // Before the fix (problematic code): static void smc_listen_work(struct work_struct *work) {
struct smc_listen_conn *conn = container_of(work, struct smc_listen_conn, work); struct sock *sk = conn->listen_sk; struct smc_sock *smc = smc_sk(sk); struct sock *newclcsock; // ... other variables ...
// ... setup code ...
lock_sock(sk); // ... some checks ...
// BUG: smc_listen_out_connected() may trigger socket free via sk_data_ready() // and user-space close() can race here, making newclcsock->sk NULL later. ret = smc_listen_out_connected(conn, newclcsock); // This line crashes if newclcsock->sk is NULL SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk));
release_sock(sk); // ... }
// After the fix: static void smc_listen_work(struct work_struct *work) {
struct smc_listen_conn *conn = container_of(work, struct smc_listen_conn, work); struct sock *sk = conn->listen_sk; struct smc_sock *smc = smc_sk(sk); struct sock *newclcsock; // ... other variables ...
// ... setup code ...
lock_sock(sk); // ... some checks ...
// FIX: Update statistics BEFORE calling smc_listen_out_connected() // This ensures newclcsock->sk is still valid. SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk));
// Now it's safe to call, even if it triggers socket cleanup ret = smc_listen_out_connected(conn, newclcsock);
release_sock(sk); // ... } ```
### Why This Fix Works
1. **Guaranteed Validity**: At the point where `SMC_STAT_SERV_SUCC_INC` is called, `newclcsock` has just been created and is still referenced by the kernel. The `sk` pointer is guaranteed to be non-NULL. 2. **No Race Condition**: The statistics update is a simple atomic operation (or uses local variables) and does not depend on the state of the socket after `smc_listen_out_connected()` returns. 3. **Minimal Change**: Swapping the order of these two operations is safe because the statistics update does not depend on the outcome of `smc_listen_out_connected()` (other than the fact that it succeeded, which is implied by the code flow).
### Additional Considerations
* **Reference Counting**: Ensure that `newclcsock` has a proper reference count before
If you want to get best quality of vulnerability data, you may have to visit VulDB.