CVE: CVE-2024-26989
Published: 2024-05-01
Description: In the Linux kernel, the following vulnerability has been resolved:

arm64: hibernate: Fix level3 translation fault in swsusp_save()

On arm64 machines, swsusp_save() faults if it attempts to access
MEMBLOCK_NOMAP memory ranges. This can be reproduced in QEMU using UEFI
when booting with rodata=off debug_pagealloc=off and CONFIG_KFENCE=n:

  Unable to handle kernel paging request at virtual address ffffff[PII_REDACTED]
  Mem abort info:
    ESR = 0x[PII_REDACTED]000007
    EC = 0x25: DABT (current EL), IL = 32 bits
    SET = 0, FnV = 0
    EA = 0, S1PTW = 0
    FSC = 0x07: level 3 translation fault
  Data abort info:
    ISV = 0, ISS = 0x00000007, ISS2 = 0x00000000
    CM = 0, WnR = 0, TnD = 0, TagAccess = 0
    GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
  swapper pgtable: 4k pages, 39-bit VAs, pgdp=00000000eeb0b000
  [ffffff[PII_REDACTED]] pgd=180000217fff9803, p4d=180000217fff9803, pud=180000217fff9803, pmd=180000217fff8803, pte=[PII_REDACTED]
  Internal error: Oops: [PII_REDACTED] [#1] SMP
  Internal error: Oops: [PII_REDACTED] [#1] SMP
  Modules linked in: xt_multiport ipt_REJECT nf_reject_ipv4 xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 libcrc32c iptable_filter bpfilter rfkill at803x snd_hda_codec_hdmi snd_hda_intel snd_intel_dspcfg dwmac_generic stmmac_platform snd_hda_codec stmmac joydev pcs_xpcs snd_hda_core phylink ppdev lp parport ramoops reed_solomon ip_tables x_tables nls_iso8859_1 vfat multipath linear amdgpu amdxcp drm_exec gpu_sched drm_buddy hid_generic usbhid hid radeon video drm_suballoc_helper drm_ttm_helper ttm i2c_algo_bit drm_display_helper cec drm_kms_helper drm
  CPU: 0 PID: 3663 Comm: systemd-sleep Not tainted 6.6.2+ #76
  Source Version: 4e22ed63a0a48e7a7cff9b98b7806d8d4add7dc0
  Hardware name: Greatwall GW-XXXXXX-XXX/GW-XXXXXX-XXX, BIOS KunLun BIOS V4.0 01/19/2021
  pstate: 600003c5 (nZCv DAIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
  pc : swsusp_save+0x280/0x538
  lr : swsusp_save+0x280/0x538
  sp : ffffffa034a3fa40
  x29: ffffffa034a3fa40 x28: ffffff[PII_REDACTED] x27: [PII_REDACTED]
  x26: ffffff[PII_REDACTED] x25: ffffffc08113e248 x24: [PII_REDACTED]
  x23: [PII_REDACTED] x22: ffffffc08113e280 x21:[PII_REDACTED]0c69f2
  x20: ffffff[PII_REDACTED] x19: ffffffc081ae2500 x18: [PII_REDACTED]
  x17: [PII_REDACTED] x16: [PII_REDACTED] x15: [PII_REDACTED]
  x14:[PII_REDACTED]000b69 x13: ffffff9f89088530 x12: 00000000ffffffea
  x11: 00000000ffff7fff x10: 00000000ffff7fff x9 : ffffffc08193f0d0
  x8 :[PII_REDACTED]0bffe8 x7 : c0000000ffff7fff x6 : [PII_REDACTED]
  x5 : ffffffa0fff09dc8 x4 : [PII_REDACTED] x3 : [PII_REDACTED]
  x2 : [PII_REDACTED] x1 : [PII_REDACTED] x0 :[PII_REDACTED]00004e
  Call trace:
   swsusp_save+0x280/0x538
   swsusp_arch_suspend+0x148/0x190
   hibernation_snapshot+0x240/0x39c
   hibernate+0xc4/0x378
   state_store+0xf0/0x10c
   kobj_attr_store+0x14/0x24

The reason is swsusp_save() -> copy_data_pages() -> page_is_saveable()
-> kernel_page_present() assuming that a page is always present when
can_set_direct_map() is false (all of rodata_full,
debug_pagealloc_enabled() and arm64_kfence_can_set_direct_map() false),
irrespective of the MEMBLOCK_NOMAP ranges. Such MEMBLOCK_NOMAP regions
should not be saved during hibernation.

This problem was introduced by changes to the pfn_valid() logic in
commit a7d9f306ba70 ("arm64: drop pfn_valid_within() and simplify
pfn_valid()").

Similar to other architectures, drop the !can_set_direct_map() check in
kernel_page_present() so that page_is_savable() skips such pages.

[catalin.marinas@arm.com: rework commit message]
CVSS Score: 7.8 (HIGH)
References: https://git.kernel.org/stable/c/022b19ebc31cce369c407617041a3db810db23b3; https://git.kernel.org/stable/c/31f815cb436082e72d34ed2e8a182140a73ebdf4; https://git.kernel.org/stable/c/50449ca66cc5a8cbc64749cf4b9f3d3fc5f4b457