CVE-2026-46253
Beschrijving NL
In de Linux kernel is de volgende kwetsbaarheid verholpen:
pstore/ram: fix buffer overflow in persistent_ram_save_old()
persistent_ram_save_old() kan meerdere keren worden aangeroepen voor hetzelfde
persistent_ram_zone (bijv. via ramoops_pstore_read -> ramoops_get_next_prz
voor PSTORE_type_dmesg-records). Momenteel wijst de functie alleen prz- >old_log toe als deze NULL is,
maar het werkt onvoorwaardelijk prz->old_log_size bij naar de huidige buffer
grootte en voert vervolgens memcpy_fromio() uit met deze nieuwe grootte. Als de
buffergrootte is gegroeid sinds de eerste toewijzing (wat kan gebeuren
over verschillende kernel bootcycli heen), leidt dit tot:
1. Een heap buffer overflow (OOB write) in de memcpy_fromio() calls
2. Een volgende OOB gelezen wanneer ramoops_pstore_read() toegang krijgt tot de buffer
het gebruik van de onjuiste (grotere) oude_log_size
De KASAN-spat zou er ongeveer zo uitzien:
BUG: KASAN: slab-out-of-bounds in ramoops_pstore_read+0x... Lees van maat N op adres ... per taak ... De omstandigheden zijn waarschijnlijk extreem moeilijk te raken:
0. Crash met een ramoops schrijven van minder-dan-record-max-size bytes. 1. Opnieuw opstarten: ramoops registers, pstore_get_records(0) leest oude crash,
wijst old_log toe met maat X
2. Crashhandler geregistreerd, timer gestart (als pstore_update_ms >= 0)
3. Oeps gebeurt (niet fataal, systeem gaat door)
4. pstore_dump() schrijft oops via ramoops_pstore_write() maat Y (>X)
5. pstore_new_entry = 1, pstore_timer_kick() gebeld
6. Het systeem blijft draaien (geen paniek oeps)
7. Timer brandt na pstore_update_ms milliseconden
8. pstore_timefunc() → schedule_work() → pstore_dowork() → pstore_get_records(1)
9. ramoops_get_next_prz() → persistent_ram_save_old()
10. buffer_size() geeft Y terug, maar old_log is X bytes
11. Y > X: memcpy_fromio() overflows heap
Vereisten:
- er bestaat een eerdere crashrecord die de recordgrootte niet heeft ingevuld
(bijna onmogelijk omdat de crashhandler zoveel schrijft als het
kan mogelijk in het record passen, begrensd door maximale recordgrootte en
de kmsg-buffer bijna altijd groter is dan de maximale recordgrootte)
- pstore_update_ms >= 0 (standaard uitgeschakeld)
- Niet-fatale oeps (systeem overleeft)
Maak de buffer vrij en wijs deze opnieuw toe wanneer de nieuwe grootte afwijkt van de
pr eviously allocated size. Dit zorgt ervoor dat oud_log altijd voldoende
ruimte voor de gegevens die worden gekopieerd.
Origineel (Engels) tonen
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:
1. A heap buffer overflow (OOB write) in the memcpy_fromio() calls
2. A subsequent OOB read when ramoops_pstore_read() accesses the buffer
using the incorrect (larger) old_log_size
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:
0. Crash with a ramoops write of less-than-record-max-size bytes.
1. Reboot: ramoops registers, pstore_get_records(0) reads old crash,
allocates old_log with size X
2. Crash handler registered, timer started (if pstore_update_ms >= 0)
3. Oops happens (non-fatal, system continues)
4. pstore_dump() writes oops via ramoops_pstore_write() size Y (>X)
5. pstore_new_entry = 1, pstore_timer_kick() called
6. System continues running (not a panic oops)
7. Timer fires after pstore_update_ms milliseconds
8. pstore_timefunc() → schedule_work() → pstore_dowork() → pstore_get_records(1)
9. ramoops_get_next_prz() → persistent_ram_save_old()
10. buffer_size() returns Y, but old_log is X bytes
11. Y > X: memcpy_fromio() overflows heap
Requirements:
- a prior crash record exists that did not fill the record size
(almost impossible since the crash handler writes as much as it
can possibly fit into the record, capped by max record size and
the kmsg buffer almost always exceeds the max 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.