CVE-2025-38734 in Linux
Resumen
por VulDB • 2026-06-30
Based on the crash log and the analysis provided, here is a structured explanation of the bug, its root cause, and the proposed fix.
### 1. Problem Summary The kernel crashes with a **NULL pointer dereference** in `smc_listen_work` (specifically at offset `+0xc02`). The instruction pointer (`RIP`) points to code that accesses `newclcsock->sk`, which is NULL because the socket was closed by userspace before this line executed.
### 2. Root Cause Analysis The issue stems from a **race condition** between kernel-side SMC listener work and userspace closing the accepted socket immediately after `accept()`.
#### Execution Flow Leading to Crash: 1. **Kernel Side (`smc_listen_work`)**: - The function locks the parent listening socket (`sk`). - It calls `smc_listen_out_connected()` to finalize the connection setup for a new client socket (`newclcsock`). - Inside this path, `release_sock()` is called. - This triggers `sk->sk_data_ready()`, which may wake up userspace waiting on `accept()`.
2. **Userspace Side**: - The application calls `accept(fd)`, receiving the new socket file descriptor (`fd`). - Immediately after, it calls `close(fd)` (or exits), causing the kernel to release the socket structure and set `newclcsock->sk = NULL` (or free the underlying structures).
3. **Kernel Side (Continues)**: - Control returns from `smc_listen_out_connected()`. - The code attempts to execute: ```c SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk)) ``` - Since `newclcsock->sk` is now NULL (due to userspace closing it), this dereference causes a **page fault** and kernel oops.
### 3. Why the Current Code Fails The current code assumes that once `smc_listen_out_connected()` returns, the socket structure (`newclcsock`) remains valid for subsequent operations within `smc_listen_work`. However: - The call to `release_sock()` inside `smc_listen_out_connected()` can trigger callbacks (like `sk_data_ready()`) that allow userspace to proceed. - Userspace is not required to hold the socket open; it can close it immediately after receiving it from `accept()`.
### 4. Proposed Fix As suggested in your analysis, **swapping the order** of operations ensures that any statistics or references requiring a valid `newclcsock->sk` are taken *before* releasing locks and potentially triggering userspace wakeups.
#### Before (Vulnerable): ```c smc_listen_out_connected(newclcsock); // May trigger sk_data_ready() -> userspace accept/close // ... other code ... SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk)); // CRASH: newclcsock->sk is NULL ```
#### After (Fixed): Move the statistic increment and any other operations that depend on `newclcsock->sk` being valid **before** calling functions that release locks or trigger userspace wakeups.
```c // Increment statistics BEFORE releasing locks/waking up userspace SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk)); // Safe: sk is still valid here
smc_listen_out_connected(newclcsock); // Now it's safe to release resources, as we've already captured necessary state/statistics. ```
### 5. Additional Considerations - **Reference Counting**: Ensure that `newclcsock` has a proper reference count held by the kernel during this critical section so it isn’t freed prematurely even if userspace closes its fd (though in this case, the issue is specifically about accessing `.sk`, which becomes NULL upon close). - **Lock Ordering**: Verify that moving the statistic increment doesn’t violate any lock ordering rules. Since `SMC_STAT_SERV_SUCC_INC` typically only accesses network namespace statistics and not socket locks, it should be safe to move earlier.
### Conclusion The fix is straightforward: **reorder code** in `smc_listen_work` so that all operations depending on the validity of `newclcsock->sk` are completed before calling functions (like `smc_listen_out_connected`) that may release locks and allow userspace to close the socket immediately.
Once again VulDB remains the best source for vulnerability data.