In the Linux kernel, the following vulnerability has been resolved:
pstore/ram: fix buffer overflow in persistent_ram_save_old()
persistent_ram_save_old() can be called multiple times for the same persistent_ram_zone (e.g., via ramoops_pstore_read -> ramoops_get_next_prz for PSTORE_TYPE_DMESG records).
Currently, the function only allocates prz->old_log when it is NULL, but it unconditionally updates prz->old_log_size to the current buffer size and then performs memcpy_fromio() using this new size. If the buffer size has grown since the first allocation (which can happen across different kernel boot cycles), this leads to:
- A heap buffer overflow (OOB write) in the memcpy_fromio() calls
- A subsequent OOB read when ramoops_pstore_read() accesses the buffer
The KASAN splat would look similar to: BUG: KASAN: slab-out-of-bounds in ramoops_pstore_read+0x... Read of size N at addr ... by task ...
The conditions are likely extremely hard to hit:
- Crash with a ramoops write of less-than-record-max-size bytes.
- Reboot: ramoops registers, pstore_get_records(0) reads old crash,
- Crash handler registered, timer started (if pstore_update_ms >= 0)
- Oops happens (non-fatal, system continues)
- pstore_dump() writes oops via ramoops_pstore_write() size Y (>X)
- pstore_new_entry = 1, pstore_timer_kick() called
- System continues running (not a panic oops)
- Timer fires after pstore_update_ms milliseconds
- pstore_timefunc() → schedule_work() → pstore_dowork() → pstore_get_records(1)
- ramoops_get_next_prz() → persistent_ram_save_old()
- buffer_size() returns Y, but old_log is X bytes
- Y > X: memcpy_fromio() overflows heap
Requirements:
- a prior crash record exists that did not fill the record size
- pstore_update_ms >= 0 (disabled by default)
- Non-fatal oops (system survives)
Free and reallocate the buffer when the new size differs from the previously allocated size. This ensures old_log always has sufficient space for the data being copied.