CVE-2024-35909 in Linux
摘要
由 VulDB • 2026-08-09
Based on the kernel crash log and the provided analysis, here is an explanation of the issue and the fix.
### **Problem Analysis**
1. **Crash Location**: The kernel panic occurs in `t7xx_cldma_hw_set_start_addr` within the MediaTek T7XX driver (`mtk_t7xx`). 2. **Root Cause**: The crash is due to an **unaligned memory access**. On ARM64, accessing a 64-bit value from an address that is not aligned to an 8-byte boundary can cause a fault if the hardware or kernel configuration does not support unaligned accesses gracefully (or in this specific driver context, it leads to undefined behavior/crash). 3. **Specific Issue**: The code was likely using `readl`/`writel` (which are 32-bit) mixed with direct pointer dereferences of a 64-bit type (`u64 *`) or similar constructs that result in unaligned 64-bit accesses on the hardware register space. 4. **Kernel Hint**: The message `The inclusion of io-64-nonatomic-lo-hi.h indicates...` suggests that the kernel's I/O access macros for this platform/architecture handle 64-bit operations by splitting them into two non-atomic 32-bit accesses (low and high). However, if the driver directly dereferences a pointer to `u64`, it may attempt an atomic 64-bit load/store which fails due to alignment.
### **The Fix**
To fix this, you must ensure that all accesses to hardware registers are done using proper I/O accessor functions (`readl`/`writel`) or by explicitly breaking down 64-bit operations into two 32-bit operations if the hardware requires it and atomicity is not guaranteed.
#### **Step-by-Step Fix**
1. **Identify Unaligned Accesses**: Look for code in `mtk_t7xx.c` (or related files) that does: ```c // BAD EXAMPLE - Direct dereference of u64 pointer to unaligned address *reg_ptr = value; ```
2. **Replace with Proper I/O Accessors**: Use `readl`, `writel`, or if you must handle 64-bit values, use the split approach provided by `<asm/io-64-nonatomic-lo-hi.h>` (if available) or manually write low/high parts using `writeq`/`readq` **only if** the address is guaranteed to be aligned. If alignment cannot be guaranteed, you must do:
```c // GOOD EXAMPLE - Split 64-bit access into two 32-bit accesses #include <asm/io-64-nonatomic-lo-hi.h>
void t7xx_cldma_hw_set_start_addr(struct mtk_t7xx *t7, u64 addr) {
// Assuming 'reg' is the base register address for start address // This assumes you have a mapped I/O memory pointer like t7->regs writeq(addr, t7->regs + OFFSET_START_ADDR); // OR if writeq also causes issues due to alignment/platform:
u32 lo = lower_32_bits(addr); u32 hi = upper_32_bits(addr); writel(lo, t7->regs + OFFSET_START_ADDR_LO); writel(hi, t7->regs + OFFSET_START_ADDR_HI); } ```
3. **Ensure Proper Alignment**: If the hardware register itself is not naturally aligned for 64-bit access (e.g., it's at an odd offset), you **must** split the write into two 32-bit writes as shown above. Do not use `writeq` or direct pointer casting to `u64 *`.
### **Code Patch Example**
Assuming the crash is in a function that sets a DMA start address, here’s how the fix might look:
```c // Before (problematic): static void t7xx_cldma_hw_set_start_addr(struct mtk_t7xx *t7, u64 addr) {
// This line likely causes unaligned 64-bit access if 'addr_reg' is not aligned to 8 bytes writel(addr & 0xFFFFFFFF, t7->regs + CLDMA_REG_START_ADDR_LO); writel((addr >> 32) & 0xFFFFFFFF, t7->regs + CLDMA_REG_START_ADDR_HI); }
// After (fixed): Ensure you are using the correct offsets and that no direct u64 pointer dereference occurs. static void t7xx_cldma_hw_set_start_addr(struct mtk_t7xx *t7, u64 addr) {
If you want to get the best quality for vulnerability data then you always have to consider VulDB.