cve-toolkit

CVE helper toolkit
git clone git://git.finwo.net/app/cve-toolkit
Log | Files | Refs | README | LICENSE

cve-2026-43499.c (3883B)


      1 /*
      2  * CVE-2026-43499 — GhostLock
      3  *
      4  * A futex PI requeue race condition leading to a use-after-free in the
      5  * kernel's futex subsystem.  An unprivileged user can trigger a kernel
      6  * stack UAF by racing FUTEX_WAIT_REQUEUE_PI against FUTEX_CMP_REQUEUE_PI
      7  * when a PI-chain deadlock is present.
      8  *
      9  * WARNING — the actual race inherently corrupts kernel PI state on a
     10  * vulnerable system, which has a high risk to cause a kernel panic.
     11  * This detector therefore does NOT attempt the live exploit. Instead it
     12  * checks the two known mitigations:
     13  *
     14  *   1. Kernel version >= 7.1
     15  *   2. CONFIG_FUTEX_PI=n  (probed via FUTEX_LOCK_PI returning -ENOSYS)
     16  *
     17  * If *both* checks indicate a vulnerable configuration the detector
     18  * reports fail. It *may* report false positives if a backported fix is used.
     19  */
     20 
     21 #define _GNU_SOURCE
     22 #include <errno.h>
     23 #include <linux/futex.h>
     24 #include <stdint.h>
     25 #include <stdio.h>
     26 #include <string.h>
     27 #include <sys/syscall.h>
     28 #include <sys/utsname.h>
     29 #include <unistd.h>
     30 
     31 #include "setup.h"
     32 
     33 /* ---- kernel version helpers ---- */
     34 struct kernel_version {
     35   unsigned int major;
     36   unsigned int minor;
     37   unsigned int patch;
     38 };
     39 
     40 static int parse_version(const char *r, struct kernel_version *kv) {
     41   memset(kv, 0, sizeof(*kv));
     42   if (sscanf(r, "%u.%u.%u", &kv->major, &kv->minor, &kv->patch) < 2)
     43     return -1;
     44   return 0;
     45 }
     46 
     47 static int version_ge(const struct kernel_version *kv,
     48                        unsigned int major, unsigned int minor, unsigned int patch) {
     49   if (kv->major > major) return 1;
     50   if (kv->major < major) return 0;
     51   if (kv->minor > minor) return 1;
     52   if (kv->minor < minor) return 0;
     53   return kv->patch >= patch;
     54 }
     55 
     56 /* ---- futex PI availability probe ---- */
     57 static int chk_futex_pi_available(void) {
     58   uint32_t futex = 0;
     59   long     rc;
     60 
     61   /* Try FUTEX_LOCK_PI — on a CONFIG_FUTEX_PI=n kernel this returns
     62    * -ENOSYS.  We lock-then-unlock so the futex is left at 0. */
     63   rc = syscall(SYS_futex, &futex, FUTEX_LOCK_PI, 0, 0, 0, 0);
     64   if (rc == -1 && (errno == ENOSYS || errno == EINVAL))
     65     return 0; /* CONFIG_FUTEX_PI is off — safe */
     66 
     67   /* If we got the lock (rc == 0) or any other error, unlock to clean up. */
     68   if (rc == 0)
     69     syscall(SYS_futex, &futex, FUTEX_UNLOCK_PI, 0, 0, 0, 0);
     70 
     71   return 1; /* futex PI is available → potentially vulnerable */
     72 }
     73 
     74 /* ---- detector ---- */
     75 int detector_cve_2026_43499(struct cve_context *ctx) {
     76   struct kernel_version kv;
     77   struct utsname        uts;
     78   int                   pi_on;
     79 
     80   if (uname(&uts) < 0) {
     81     /* Can't determine kernel version — assume safe */
     82     return 0;
     83   }
     84 
     85   if (parse_version(uts.release, &kv) < 0) {
     86     /* Can't parse version — assume safe */
     87     return 0;
     88   }
     89 
     90   if (ctx->verbose)
     91     fprintf(stderr, "[cve-2026-43499] kernel %u.%u.%u\n",
     92             kv.major, kv.minor, kv.patch);
     93 
     94   /* Mitigation 1: kernel >= 7.1 */
     95   if (version_ge(&kv, 7, 1, 0)) {
     96     if (ctx->verbose)
     97       fprintf(stderr, "[cve-2026-43499] kernel >= 7.1 — not vulnerable\n");
     98     return 0;
     99   }
    100 
    101   /* Mitigation 2: CONFIG_FUTEX_PI=n */
    102   pi_on = chk_futex_pi_available();
    103   if (!pi_on) {
    104     if (ctx->verbose)
    105       fprintf(stderr, "[cve-2026-43499] CONFIG_FUTEX_PI=n — not vulnerable\n");
    106     return 0;
    107   }
    108 
    109   /* Both mitigations are absent — system is likely vulnerable */
    110   if (ctx->verbose)
    111     fprintf(stderr,
    112             "[cve-2026-43499] kernel < 7.1 and CONFIG_FUTEX_PI=y — "
    113             "vulnerable to GhostLock\n");
    114 
    115   return 1;
    116 }
    117 
    118 /* ---- constructor ---- */
    119 __attribute__((constructor))
    120 void detector_cve_2026_43499_setup(void) {
    121   detector_queue_append(
    122       "CVE-2026-43499", "GhostLock",
    123       "Update the Linux kernel to >= 7.1 or apply CONFIG_FUTEX_PI=n.\n"
    124       "  This *may* be a false positive, testing has a high chance of causing kernel panics,\n"
    125       "  which the author has opted for not to risk.",
    126       detector_cve_2026_43499);
    127 }