FKIE_CVE-2026-12631

Vulnerability from fkie_nvd - Published: 2026-08-18 21:16 - Updated: 2026-10-22 22:10
Summary
The Zephyr kernel validates the k_thread_join() and k_thread_abort() system calls (declared __syscall in include/zephyr/kernel.h) through thread_obj_validate() in kernel/thread.c. Its default switch branch is the access-denied path, taken when k_object_validate() returns -EPERM (the calling user thread was never granted access to the target thread object) or -EBADF (the supplied pointer is not a registered kernel object of the right type). That branch invoked K_OOPS(K_SYSCALL_VERIFY_MSG(ret, "access denied")), but K_SYSCALL_VERIFY_MSG treats a true expression as success; the non-zero error code ret therefore read as "verified OK", the kernel oops was never raised, and control fell through to CODE_UNREACHABLE. Because k_thread_join() and k_thread_abort() are system calls, an unprivileged user-mode thread (under CONFIG_USERSPACE) can reach this denial path directly by calling either syscall on a thread object it does not own. Instead of the offending thread being cleanly terminated, execution reaches __builtin_unreachable() while running in supervisor mode inside the syscall handler. On Clang builds CODE_UNREACHABLE emits an illegal-instruction trap, so a user thread can deterministically crash the kernel — a locally triggerable denial of service that escapes the userspace sandbox. On GCC builds the path is undefined behavior: the compiler may drop the return-value handling for thread_obj_validate(), so it can return an undefined bool; if that is false, the caller proceeds into the real k_thread_join()/k_thread_abort() implementation for a thread the user was never authorized to access, an access-control bypass. The fix changes the verification expression to ret == 0, so a denied (non-zero) result now correctly raises K_OOPS and terminates the offending caller.
Impacted products
Vendor Product Version

{
  "affected": [
    {
      "affectedData": [
        {
          "collectionURL": "https://github.com/zephyrproject-rtos/zephyr",
          "defaultStatus": "unaffected",
          "packageName": "zephyr",
          "product": "zephyr",
          "programFiles": [
            "kernel/thread.c"
          ],
          "vendor": "zephyrproject",
          "versions": [
            {
              "lessThan": "4.4.2",
              "status": "affected",
              "version": "2.3.0",
              "versionType": "semver"
            }
          ]
        }
      ],
      "source": "vulnerabilities@zephyrproject.org"
    }
  ],
  "cveTags": [],
  "descriptions": [
    {
      "lang": "en",
      "value": "The Zephyr kernel validates the k_thread_join() and k_thread_abort() system calls (declared __syscall in include/zephyr/kernel.h) through thread_obj_validate() in kernel/thread.c. Its default switch branch is the access-denied path, taken when k_object_validate() returns -EPERM (the calling user thread was never granted access to the target thread object) or -EBADF (the supplied pointer is not a registered kernel object of the right type). That branch invoked K_OOPS(K_SYSCALL_VERIFY_MSG(ret, \"access denied\")), but K_SYSCALL_VERIFY_MSG treats a true expression as success; the non-zero error code ret therefore read as \"verified OK\", the kernel oops was never raised, and control fell through to CODE_UNREACHABLE.\n\nBecause k_thread_join() and k_thread_abort() are system calls, an unprivileged user-mode thread (under CONFIG_USERSPACE) can reach this denial path directly by calling either syscall on a thread object it does not own. Instead of the offending thread being cleanly terminated, execution reaches __builtin_unreachable() while running in supervisor mode inside the syscall handler.\n\nOn Clang builds CODE_UNREACHABLE emits an illegal-instruction trap, so a user thread can deterministically crash the kernel \u2014 a locally triggerable denial of service that escapes the userspace sandbox. On GCC builds the path is undefined behavior: the compiler may drop the return-value handling for thread_obj_validate(), so it can return an undefined bool; if that is false, the caller proceeds into the real k_thread_join()/k_thread_abort() implementation for a thread the user was never authorized to access, an access-control bypass.\n\nThe fix changes the verification expression to ret == 0, so a denied (non-zero) result now correctly raises K_OOPS and terminates the offending caller."
    },
    {
      "lang": "es",
      "value": "El kernel Zephyr valida las llamadas al sistema k_thread_join() y k_thread_abort() (declaradas __syscall en include/zephyr/kernel.h) a trav\u00e9s de thread_obj_validate() en kernel/thread.c. Su rama switch predeterminada es la ruta de acceso denegado, tomada cuando k_object_validate() devuelve -EPERM (el hilo de usuario llamante nunca tuvo acceso concedido al objeto de hilo objetivo) o -EBADF (el puntero suministrado no es un objeto kernel registrado del tipo correcto). Esa rama invoc\u00f3 K_OOPS(K_SYSCALL_VERIFY_MSG(ret, \u2019access denied\u2019)), pero K_SYSCALL_VERIFY_MSG trata una expresi\u00f3n verdadera como \u00e9xito; el c\u00f3digo de error no nulo ret, por lo tanto, se ley\u00f3 como \u2019verified OK\u2019, el oops del kernel nunca se gener\u00f3, y el control pas\u00f3 a CODE_UNREACHABLE.\n\nDebido a que k_thread_join() y k_thread_abort() son llamadas al sistema, un hilo en modo usuario sin privilegios (bajo CONFIG_USERSPACE) puede alcanzar esta ruta de denegaci\u00f3n directamente llamando a cualquiera de las syscall en un objeto de hilo que no posee. En lugar de que el hilo infractor sea terminado limpiamente, la ejecuci\u00f3n alcanza __builtin_unreachable() mientras se ejecuta en modo supervisor dentro del gestor de syscall.\n\nEn compilaciones de Clang, CODE_UNREACHABLE emite una trampa de instrucci\u00f3n ilegal, por lo que un hilo de usuario puede bloquear el kernel de forma determinista - una denegaci\u00f3n de servicio activable localmente que escapa al sandbox del espacio de usuario. En compilaciones de GCC, la ruta es un comportamiento indefinido: el compilador puede omitir el manejo del valor de retorno para thread_obj_validate(), por lo que puede devolver un booleano indefinido; si eso es falso, el llamante procede a la implementaci\u00f3n real de k_thread_join()/k_thread_abort() para un hilo al que el usuario nunca fue autorizado a acceder, una omisi\u00f3n de control de acceso.\n\nLa soluci\u00f3n cambia la expresi\u00f3n de verificaci\u00f3n a ret == 0, por lo que un resultado denegado (no nulo) ahora genera correctamente K_OOPS y termina al llamante infractor."
    }
  ],
  "id": "CVE-2026-12631",
  "lastModified": "2026-10-22T22:10:00.250",
  "metrics": {
    "cvssMetricV31": [
      {
        "cvssData": {
          "attackComplexity": "LOW",
          "attackVector": "LOCAL",
          "availabilityImpact": "HIGH",
          "baseScore": 6.5,
          "baseSeverity": "MEDIUM",
          "confidentialityImpact": "NONE",
          "integrityImpact": "NONE",
          "privilegesRequired": "LOW",
          "scope": "CHANGED",
          "userInteraction": "NONE",
          "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H",
          "version": "3.1"
        },
        "exploitabilityScore": 2.0,
        "impactScore": 4.0,
        "source": "vulnerabilities@zephyrproject.org",
        "type": "Secondary"
      }
    ],
    "ssvcV203": [
      {
        "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
        "ssvcData": {
          "id": "CVE-2026-12631",
          "options": [
            {
              "exploitation": "none"
            },
            {
              "automatable": "no"
            },
            {
              "technicalImpact": "partial"
            }
          ],
          "role": "CISA Coordinator",
          "timestamp": "2026-08-19T13:17:32.022813Z",
          "version": "2.0.3"
        }
      }
    ]
  },
  "published": "2026-08-18T21:16:33.647",
  "references": [
    {
      "source": "vulnerabilities@zephyrproject.org",
      "url": "https://github.com/zephyrproject-rtos/zephyr/commit/bd1828652dfc217ba9f3a2221a7499cd8914ed9c"
    },
    {
      "source": "vulnerabilities@zephyrproject.org",
      "url": "https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-crfw-75jw-hjm3"
    }
  ],
  "sourceIdentifier": "vulnerabilities@zephyrproject.org",
  "vulnStatus": "Awaiting Analysis",
  "weaknesses": [
    {
      "description": [
        {
          "lang": "en",
          "value": "CWE-862"
        }
      ],
      "source": "vulnerabilities@zephyrproject.org",
      "type": "Secondary"
    }
  ]
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.

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.
Vulnerability timeline

Sightings and recorded dates, grouped by day · UTC

JSON
Events included in the timeline

Loading timeline…


    Loading…

    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.