GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GHSA-MQH3-5X68-9V64

Vulnerability from github – Published: 2025-03-27 18:31 – Updated: 2026-01-22 21:33
VLAI
Details

In the Linux kernel, the following vulnerability has been resolved:

bpf: Fix pointer-leak due to insufficient speculative store bypass mitigation

To mitigate Spectre v4, 2039f26f3aca ("bpf: Fix leakage due to insufficient speculative store bypass mitigation") inserts lfence instructions after 1) initializing a stack slot and 2) spilling a pointer to the stack.

However, this does not cover cases where a stack slot is first initialized with a pointer (subject to sanitization) but then overwritten with a scalar (not subject to sanitization because the slot was already initialized). In this case, the second write may be subject to speculative store bypass (SSB) creating a speculative pointer-as-scalar type confusion. This allows the program to subsequently leak the numerical pointer value using, for example, a branch-based cache side channel.

To fix this, also sanitize scalars if they write a stack slot that previously contained a pointer. Assuming that pointer-spills are only generated by LLVM on register-pressure, the performance impact on most real-world BPF programs should be small.

The following unprivileged BPF bytecode drafts a minimal exploit and the mitigation:

[...] // r6 = 0 or 1 (skalar, unknown user input) // r7 = accessible ptr for side channel // r10 = frame pointer (fp), to be leaked // r9 = r10 # fp alias to encourage ssb (u64 )(r9 - 8) = r10 // fp[-8] = ptr, to be leaked // lfence added here because of pointer spill to stack. // // Ommitted: Dummy bpf_ringbuf_output() here to train alias predictor // for no r9-r10 dependency. // (u64 )(r10 - 8) = r6 // fp[-8] = scalar, overwrites ptr // 2039f26f3aca: no lfence added because stack slot was not STACK_INVALID, // store may be subject to SSB // // fix: also add an lfence when the slot contained a ptr // r8 = (u64 )(r9 - 8) // r8 = architecturally a scalar, speculatively a ptr // // leak ptr using branch-based cache side channel: r8 &= 1 // choose bit to leak if r8 == 0 goto SLOW // no mispredict // architecturally dead code if input r6 is 0, // only executes speculatively iff ptr bit is 1 r8 = (u64 )(r7 + 0) # encode bit in cache (0: slow, 1: fast) SLOW: [...]

After running this, the program can time the access to *(r7 + 0) to determine whether the chosen pointer bit was 0 or 1. Repeat this 64 times to recover the whole address on amd64.

In summary, sanitization can only be skipped if one scalar is overwritten with another scalar. Scalar-confusion due to speculative store bypass can not lead to invalid accesses because the pointer bounds deducted during verification are enforced using branchless logic. See 979d63d50c0c ("bpf: prevent out of bounds speculation on pointer arithmetic") for details.

Do not make the mitigation depend on !env->allow_{uninit_stack,ptr_leaks} because speculative leaks are likely unexpected if these were enabled. For example, leaking the address to a protected log file may be acceptable while disabling the mitigation might unintentionally leak the address into the cached-state of a map that is accessible to unprivileged processes.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-53024"
  ],
  "database_specific": {
    "cwe_ids": [],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-03-27T17:15:51Z",
    "severity": "HIGH"
  },
  "details": "In the Linux kernel, the following vulnerability has been resolved:\n\nbpf: Fix pointer-leak due to insufficient speculative store bypass mitigation\n\nTo mitigate Spectre v4, 2039f26f3aca (\"bpf: Fix leakage due to\ninsufficient speculative store bypass mitigation\") inserts lfence\ninstructions after 1) initializing a stack slot and 2) spilling a\npointer to the stack.\n\nHowever, this does not cover cases where a stack slot is first\ninitialized with a pointer (subject to sanitization) but then\noverwritten with a scalar (not subject to sanitization because\nthe slot was already initialized). In this case, the second write\nmay be subject to speculative store bypass (SSB) creating a\nspeculative pointer-as-scalar type confusion. This allows the\nprogram to subsequently leak the numerical pointer value using,\nfor example, a branch-based cache side channel.\n\nTo fix this, also sanitize scalars if they write a stack slot\nthat previously contained a pointer. Assuming that pointer-spills\nare only generated by LLVM on register-pressure, the performance\nimpact on most real-world BPF programs should be small.\n\nThe following unprivileged BPF bytecode drafts a minimal exploit\nand the mitigation:\n\n  [...]\n  // r6 = 0 or 1 (skalar, unknown user input)\n  // r7 = accessible ptr for side channel\n  // r10 = frame pointer (fp), to be leaked\n  //\n  r9 = r10 # fp alias to encourage ssb\n  *(u64 *)(r9 - 8) = r10 // fp[-8] = ptr, to be leaked\n  // lfence added here because of pointer spill to stack.\n  //\n  // Ommitted: Dummy bpf_ringbuf_output() here to train alias predictor\n  // for no r9-r10 dependency.\n  //\n  *(u64 *)(r10 - 8) = r6 // fp[-8] = scalar, overwrites ptr\n  // 2039f26f3aca: no lfence added because stack slot was not STACK_INVALID,\n  // store may be subject to SSB\n  //\n  // fix: also add an lfence when the slot contained a ptr\n  //\n  r8 = *(u64 *)(r9 - 8)\n  // r8 = architecturally a scalar, speculatively a ptr\n  //\n  // leak ptr using branch-based cache side channel:\n  r8 \u0026= 1 // choose bit to leak\n  if r8 == 0 goto SLOW // no mispredict\n  // architecturally dead code if input r6 is 0,\n  // only executes speculatively iff ptr bit is 1\n  r8 = *(u64 *)(r7 + 0) # encode bit in cache (0: slow, 1: fast)\nSLOW:\n  [...]\n\nAfter running this, the program can time the access to *(r7 + 0) to\ndetermine whether the chosen pointer bit was 0 or 1. Repeat this 64\ntimes to recover the whole address on amd64.\n\nIn summary, sanitization can only be skipped if one scalar is\noverwritten with another scalar. Scalar-confusion due to speculative\nstore bypass can not lead to invalid accesses because the pointer\nbounds deducted during verification are enforced using branchless\nlogic. See 979d63d50c0c (\"bpf: prevent out of bounds speculation on\npointer arithmetic\") for details.\n\nDo not make the mitigation depend on !env-\u003eallow_{uninit_stack,ptr_leaks}\nbecause speculative leaks are likely unexpected if these were enabled.\nFor example, leaking the address to a protected log file may be acceptable\nwhile disabling the mitigation might unintentionally leak the address\ninto the cached-state of a map that is accessible to unprivileged\nprocesses.",
  "id": "GHSA-mqh3-5x68-9v64",
  "modified": "2026-01-22T21:33:42Z",
  "published": "2025-03-27T18:31:28Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-53024"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/01bdcc73dbe7be3ad4d4ee9a59b71e42f461a528"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/81b3374944d201872cfcf82730a7860f8e7c31dd"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/aae109414a57ab4164218f36e2e4a17f027fcaaa"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/b0c89ef025562161242a7c19b213bd6b272e93df"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/da75dec7c6617bddad418159ffebcb133f008262"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/e4f4db47794c9f474b184ee1418f42e6a07412b6"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…