Files
SKELETONKEY/core/registry.c
T
leviathan 8243817f7e test harness: kernel_range unit tests + coverage report + register_all helper
Three coupled improvements to the test harness:

1. New tests/test_kernel_range.c — 32 pure unit tests covering
   kernel_range_is_patched(), skeletonkey_host_kernel_at_least(),
   and skeletonkey_host_kernel_in_range(). These are the central
   comparison primitives every module routes through; a regression
   in any of them silently mis-classifies entire CVE families. Tests
   cover exact boundary, one-below, mainline-only, multi-LTS,
   between-branch, and NULL-safety cases. Builds and runs
   cross-platform (no Linux syscalls).

2. tests/test_detect.c additions:
   - mk_host(base, major, minor, patch, release) builder so new
     fingerprint-based tests don't duplicate 14-line struct literals
     to override one (major, minor, patch) triple.
   - Post-run coverage report that iterates the runtime registry and
     warns about modules without at least one direct test row. Output
     is informational (no CI fail) so coverage grows incrementally.
   - 7 new boundary tests for the kernel_patched_from entries added
     by tools/refresh-kernel-ranges.py (commit 8de46e2):
       - af_unix_gc 6.4.12 → VULNERABLE / 6.4.13 → OK
       - vmwgfx 5.10.127 → OK
       - nft_set_uaf 5.10.179 → OK / 6.1.27 → OK
       - nft_payload 5.10.162 → OK
       - nf_tables 5.10.209 → OK

3. core/registry_all.c — extracts the 27-line 'call every
   skeletonkey_register_<family>()' enumeration from skeletonkey.c
   into a shared helper. skeletonkey.c main() now calls
   skeletonkey_register_all_modules() once; the detect-test main()
   does the same. Kept in its own translation unit so registry.c
   stays standalone for the lean kernel_range unit-test binary
   (which links core/ only, no modules).

Makefile: builds two test binaries now —
  skeletonkey-test     — detect() integration tests (full corpus)
  skeletonkey-test-kr  — kernel_range unit tests (core/ only)
'make test' runs both.

Verification:
  - macOS: 32/32 kernel_range tests pass; detect tests skipped
    (non-Linux platform, stubbed bodies).
  - Linux (docker gcc:latest): 32/32 kernel_range + 51/51 detect.
    Coverage report identifies 2 modules without direct tests
    (copy_fail, entrybleed) out of 31 registered.

Test counts: 44 -> 83 (+39).
2026-05-23 01:09:30 -04:00

66 lines
1.7 KiB
C

/*
* SKELETONKEY — module registry implementation
*
* Simple flat array. Resized in chunks of 16. We never expect more
* than a few dozen modules, so this is fine.
*
* The canonical "register every family" enumeration lives in
* registry_all.c — kept separate so this file links into the
* standalone kernel_range unit-test binary without pulling in every
* module's symbol.
*/
#include "registry.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define REGISTRY_CHUNK 16
static const struct skeletonkey_module **g_modules = NULL;
static size_t g_count = 0;
static size_t g_cap = 0;
void skeletonkey_register(const struct skeletonkey_module *m)
{
if (m == NULL || m->name == NULL) {
fprintf(stderr, "[!] skeletonkey_register: NULL module or unnamed module\n");
return;
}
if (g_count == g_cap) {
size_t new_cap = g_cap + REGISTRY_CHUNK;
const struct skeletonkey_module **n =
realloc((void *)g_modules, new_cap * sizeof(*g_modules));
if (n == NULL) {
fprintf(stderr, "[!] skeletonkey_register: OOM\n");
return;
}
g_modules = n;
g_cap = new_cap;
}
g_modules[g_count++] = m;
}
size_t skeletonkey_module_count(void)
{
return g_count;
}
const struct skeletonkey_module *skeletonkey_module_at(size_t i)
{
if (i >= g_count) return NULL;
return g_modules[i];
}
const struct skeletonkey_module *skeletonkey_module_find(const char *name)
{
if (name == NULL) return NULL;
for (size_t i = 0; i < g_count; i++) {
if (strcmp(g_modules[i]->name, name) == 0)
return g_modules[i];
}
return NULL;
}