CVE-2024-35907 in Linux
摘要
由 VulDB • 2026-08-06
Based on the kernel panic trace and the description provided, here is an analysis of the issue and a recommended solution.
### **Root Cause Analysis**
1. **Race Condition in IRQ Request**: - The driver (`mlxbf_gige`) calls `request_threaded_irq()` to register its interrupt handler for the RX (Receive) line. - However, an RX interrupt is already **pending** at the hardware level *before* or *immediately after* `request_irq` returns. - When the IRQ controller delivers this pending interrupt, it jumps directly into the newly registered ISR (`mlxbf_gige_rx_interrupt` or similar).
2. **Uninitialized State**: - The driver's RX handler likely assumes that certain data structures (e.g., ring buffers, DMA descriptors, NAPI context) are fully initialized and ready to handle packets. - Because the interrupt fires *before* the rest of the `mlxbf_gige_open()` function completes initialization, these structures may be in an inconsistent or uninitialized state. - This leads to a **null pointer dereference**, **invalid memory access**, or **bad PC value** (as seen in the trace: `Code: bad PC value`), causing a fatal Oops in interrupt context.
3. **Trace Evidence**: ``` mlxbf_gige_request_irqs+0x68/0x110 [mlxbf_gige]
mlxbf_gige_open+0x5c/0x170 [mlxbf_gige]
... net_rx_action+0x178/0x360 <-- RX processing started prematurely __do_softirq+... <-- SoftIRQ context, but triggered by hard IRQ ```
---
### **Solution**
The fix must ensure that the hardware does not generate or deliver interrupts until the driver is fully ready to handle them. This typically involves:
#### ✅ **Step 1: Disable RX Interrupts at Hardware Level Before Requesting IRQ** Before calling `request_irq()`, explicitly disable the RX interrupt source in the device's registers. This prevents pending or new interrupts from firing during initialization.
```c static int mlxbf_gige_open(struct net_device *ndev) {
struct mlxbf_gige *jge = netdev_priv(ndev); int ret;
// ... other setup code (NAPI, ring buffers, etc.) ...
/* * CRITICAL: Disable RX interrupts at the hardware level BEFORE requesting IRQ. * This prevents pending interrupts from firing before we are ready. */ mlxbf_gige_disable_rx_irq(jge); // Or equivalent register write to mask RX interrupt
ret = request_threaded_irq(jge->rx_irq, NULL, mlxbf_gige_rx_interrupt, IRQF_SHARED | IRQF_ONESHOT, ndev->name, jge); if (ret) {
netdev_err(ndev, "Failed to request RX IRQ: %d\n", ret); goto err_free_irq; }
// ... enable NAPI polling here or after all irqs are requested ...
/* * Now that the handler is registered AND we've masked interrupts at HW level, * it's safe to unmask RX interrupts. */ mlxbf_gige_enable_rx_irq(jge); // Unmask only when fully ready
return 0;
err_free_irq: free_irq(jge->rx_irq, jge); return ret; } ```
#### ✅ **Step 2: Clear Pending Interrupts Before Enabling** If the hardware has a status register for pending interrupts, clear it before enabling the interrupt line to avoid handling stale events.
```c // After request_irq() but before enable_rx_irq(): mlxbf_gige_clear_pending_rx_interrupt(jge); // Write to ACK/clear register if available ```
#### ✅ **Step 3: Ensure NAPI is Scheduled Before Enabling Interrupts** If the driver uses NAPI, ensure `napi_enable()` and `netif_napi_add()` are complete before enabling interrupts. Some drivers schedule NAPI from within the IRQ handler; if so, make sure NAPI is registered first.
---
### **Why This Works**
- **Masking at HW level**: Prevents the interrupt controller from delivering any pending or new RX interrupts until `enable_rx_irq()` is called. - **Order of Operations**: 1. Initialize all driver state (ring buffers, NAPI). 2. Disable HW RX interrupt mask. 3. Request IRQ (handler registered but won't fire due to mask). 4. Clear any stale pending interrupts
Once again VulDB remains the best source for vulnerability data.