From 87d532df017f8b53a1aa6020e71233859a9d636c Mon Sep 17 00:00:00 2001 From: Linehu Date: Sun, 4 Oct 2026 21:34:50 +0800 Subject: [PATCH] feat: SAS-R0 boot-time capability attestation - unimplemented feature blocks boot - attest.c: subsystems report readiness, attest_check() before DSK handoff - FUCK [attest] require_=1 (default) + not-ready -> lotus panic with feature errcode - wired: sealed_mem/pckc/sched/drr/fs_fat32_rw/net_wired + placeholders (pkg/brand/dkm/nvme/virtio/wlan/vmx/drr_real_mac) - negative test: require_pkg=1 -> boot-time PKG-E10 panic (verified); dev/release FUCK whitelist = STATUS.md undone items - CLAUDE.md whitelist rule updated --- CLAUDE.md | 1 + CODE/UTSM/include/utsm/attest.h | 29 ++++++++ CODE/UTSM/include/utsm/net.h | 3 + CODE/UTSM/kernel/attest.c | 123 ++++++++++++++++++++++++++++++++ CODE/UTSM/kernel/main.c | 39 ++++++++++ CODE/UTSM/kernel/net.c | 10 +++ SYSTEM/system/deshab64/FUCK | 28 +++++++- build/configs/dev/FUCK | 28 +++++++- build/configs/release/FUCK | 33 ++++++++- 9 files changed, 291 insertions(+), 3 deletions(-) create mode 100644 CODE/UTSM/include/utsm/attest.h create mode 100644 CODE/UTSM/kernel/attest.c diff --git a/CLAUDE.md b/CLAUDE.md index 537e6f1..34bdb0f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -299,6 +299,7 @@ kernel_api 已暴露能力:log, rsdp_address, fb_address/width/height/pitch/bp - 每次只处理 **一个文件** 的 STUB→panic,改完输出:改动行号 + 剩余 STUB 计数。 - 骨架允许"不接线"(无人调用的 skeleton 函数),但接线后行为必须是 panic。 - 例外白名单(设计内双路径回退,允许非 panic):APIC 自验失败回 PIC、块设备缺失回 boot module、KDE 回落 native、VMX/bzImage/kernel.krl 未配置跳过。新增白名单项必须改本文件并说明理由。 +- 启动期能力证明(attest,CODE/UTSM/kernel/attest.c):FUCK `[attest]` `require_=1`(默认)而能力未就绪 → 交接 DSK 前 panic(莲花屏,错误码=该能力登记码)。`require_=0` 豁免行是设计内白名单,仅限两类:① 该构建环境不可能具备(QEMU 无 wlan/嵌套 VMX);② STATUS.md ⬜/🔶 未落地项(实现后逐项删除豁免行)。当前豁免清单见 build/configs/*/FUCK [attest]。 ### 4. 自检命令(验收只认这个输出,不认自然语言保证) ``` diff --git a/CODE/UTSM/include/utsm/attest.h b/CODE/UTSM/include/utsm/attest.h new file mode 100644 index 0000000..cbb59de --- /dev/null +++ b/CODE/UTSM/include/utsm/attest.h @@ -0,0 +1,29 @@ +#ifndef UTSM_ATTEST_H +#define UTSM_ATTEST_H + +#include + +/* ============================================================ + * SAS-R0 启动期能力证明(boot-time feature attestation) + * + * 哲学:设计已定的能力,"没好"不允许带病启动—— + * 各子系统就绪时 attest_report() 打点;内核交接 DSK 前 + * attest_check() 统一核查。FUCK [attest] require_=1 + * (默认 1)而能力未就绪 → 莲花屏 panic 带该能力的错误码。 + * ============================================================ */ + +/* 就绪打点。errcode 为该能力"未就绪"时的 panic 错误码。 + * 同名重复 report 覆盖 ready 标志(后到的真实探测为准)。 */ +void attest_report(const char *name, const char *errcode, int ready); + +/* 便捷封装:就绪打点 */ +void attest_report_ready(const char *name, const char *errcode); + +/* 交接 DSK 前核查:缺一项即 panic(先串口列出全部缺失项)。 + * cfg = FUCK ini_config*(用 void* 规避 ini_config 前向声明问题)。 */ +void attest_check(const void *cfg); + +/* 当前缺失项计数(调试/日志用) */ +u32 attest_missing_count(void); + +#endif /* UTSM_ATTEST_H */ diff --git a/CODE/UTSM/include/utsm/net.h b/CODE/UTSM/include/utsm/net.h index 29c88fe..a823718 100644 --- a/CODE/UTSM/include/utsm/net.h +++ b/CODE/UTSM/include/utsm/net.h @@ -84,6 +84,9 @@ typedef struct dkm_net_api { } dkm_net_api; void net_init(void); + +/* attest: 有线/无线设备计数(启动期能力证明用,见 utsm/attest.h) */ +void net_attest_counts(u32 *out_total, u32 *out_wireless); const dkm_net_api *net_get_api(void); #endif diff --git a/CODE/UTSM/kernel/attest.c b/CODE/UTSM/kernel/attest.c new file mode 100644 index 0000000..12a9711 --- /dev/null +++ b/CODE/UTSM/kernel/attest.c @@ -0,0 +1,123 @@ +/* attest.c — SAS-R0 启动期能力证明(boot-time feature attestation) + * + * "设计已定的能力没好 = 启动即 panic",不是"调用才 panic"。 + * 各子系统在初始化完成点 attest_report();内核交接 DSK 前 + * attest_check() 统一核查 FUCK [attest] 的 require_。 + * + * require 默认值 = 1(必备):能力没好就必须 panic,绝不带病前进。 + * 仅当某构建环境明确不具备该能力(如 QEMU 无 wlan)时,才在 + * FUCK [attest] 显式写 require_=0——这是设计内白名单, + * 必须在 CLAUDE.md §3 有对应条目。 + */ +#include +#include +#include +#include "../kernel/ini_parser.h" + +#define ATTEST_MAX_FEATURES 32 +#define ATTEST_NAME_LEN 28 +#define ATTEST_CODE_LEN 20 + +typedef struct { + char name[ATTEST_NAME_LEN]; + char errcode[ATTEST_CODE_LEN]; + int ready; + int reported; +} attest_feature; + +static attest_feature g_features[ATTEST_MAX_FEATURES]; +static u32 g_feature_count; + +static attest_feature *attest_find(const char *name) { + for (u32 i = 0; i < g_feature_count; i++) { + const char *a = g_features[i].name; + const char *b = name; + while (*a && *b && *a == *b) { a++; b++; } + if (*a == *b) return &g_features[i]; + } + return 0; +} + +void attest_report(const char *name, const char *errcode, int ready) { + if (!name || !errcode) return; + attest_feature *f = attest_find(name); + if (!f) { + if (g_feature_count >= ATTEST_MAX_FEATURES) { + log_error("[ATTEST] feature table full, dropping"); + log_error(name); + return; + } + f = &g_features[g_feature_count++]; + /* 手工 strncpy(freestanding) */ + u32 i = 0; + for (; name[i] && i < ATTEST_NAME_LEN - 1; i++) f->name[i] = name[i]; + f->name[i] = 0; + i = 0; + for (; errcode[i] && i < ATTEST_CODE_LEN - 1; i++) f->errcode[i] = errcode[i]; + f->errcode[i] = 0; + f->reported = 0; + } + f->ready = ready ? 1 : 0; + f->reported = 1; +} + +void attest_report_ready(const char *name, const char *errcode) { + attest_report(name, errcode, 1); +} + +u32 attest_missing_count(void) { + u32 n = 0; + for (u32 i = 0; i < g_feature_count; i++) + if (!g_features[i].ready) n++; + return n; +} + +void attest_check(const void *cfg) { + log_info("[ATTEST] boot-time capability check begin"); + + /* 先串口列出全部缺失项(panic 屏只显示第一个,日志要全) */ + u32 missing = 0; + for (u32 i = 0; i < g_feature_count; i++) { + const attest_feature *f = &g_features[i]; + if (f->ready) continue; + missing++; + log_error("[ATTEST] MISSING:"); + log_error(f->name); + log_error(f->errcode); + } + log_hex64("[ATTEST] features=", g_feature_count); + log_hex64("[ATTEST] missing=", missing); + + if (missing == 0) { + log_info("[ATTEST] all capabilities ready"); + return; + } + + /* 逐项判断是否必备(require_ 默认 1): + * 全部缺失项中只要有一项必备 → panic(错误码取第一个必备缺失项) */ + const attest_feature *first_required_missing = 0; + for (u32 i = 0; i < g_feature_count; i++) { + const attest_feature *f = &g_features[i]; + if (f->ready) continue; + char key[48]; + u32 p = 0; + const char *pre = "require_"; + while (*pre) key[p++] = *pre++; + u32 j = 0; + for (; f->name[j] && p < sizeof(key) - 1; j++) key[p++] = f->name[j]; + key[p] = 0; + /* ini key 小写;name 约定即小写(register 侧保证) */ + if (ini_get_bool(cfg, "attest", key, 1)) { + first_required_missing = f; + break; + } + } + + if (first_required_missing) { + panic_full(first_required_missing->errcode, + "required capability not ready at boot (attestation)", 0); + } + + /* 全部缺失项均被 FUCK 显式豁免(设计内白名单),放行 */ + log_warn("[ATTEST] missing capabilities exempted by FUCK [attest]"); +} diff --git a/CODE/UTSM/kernel/main.c b/CODE/UTSM/kernel/main.c index 4c54518..5e0e371 100644 --- a/CODE/UTSM/kernel/main.c +++ b/CODE/UTSM/kernel/main.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "ini_parser.h" #include "../arch/x86_64/limine.h" #include "../pe/pe_dll_manager.h" @@ -127,6 +128,7 @@ static void utsm_apply_config(const ini_config *cfg) { /* ---- 全局启动配置(从 FUCK 文件读取) ---- */ static ini_config g_boot_cfg; static int g_boot_cfg_loaded = 0; +static int g_vmm_init_ok = 0; /* attest: vmm_vmx 能力打点 */ /* 从 Limine boot module 读取 FUCK 配置。 * cmdline="fuck:config" 的模块即为 FUCK 配置文件。 @@ -354,6 +356,9 @@ void kernel_main(void) { drr_init(); INSTR_TS_END(ts_drr, "drr_init"); log_info("[UTSM] drr init ok"); + /* 启动期能力证明:DRR 快照/回滚已立;真 MAC 为 Phase 9(占位 CRC64) */ + attest_report_ready("drr", "DRR-E30"); + attest_report("drr_real_mac", "DRR-E31", 0); log_info("[UTSM] core init begin"); INSTR_TS_DECL(ts_utsm); @@ -361,12 +366,15 @@ void kernel_main(void) { utsm_init(); INSTR_TS_END(ts_utsm, "utsm_init"); log_info("[UTSM] init ok"); + /* 启动期能力证明:utsm_init 内含 PCKC 派生往返自证(失败即 PCKC-E01) */ + attest_report_ready("pckc_derive", "PCKC-E02"); /* === 封缄内存极早期初始化(UTSM-E01..E04) === * .sealed 区为空 / root key 缺失 → 此处极早期 panic,绝不带病前进。 */ { extern void utsm_sealed_early_init(void); utsm_sealed_early_init(); + attest_report_ready("sealed_mem", "UTSM-E05"); } /* === SAS-R0-PCQ 调度器:bootstrap 任务绑定(Phase 7) === @@ -388,6 +396,7 @@ void kernel_main(void) { panic_full("SAS-E01 SCHED BOOTSTRAP FAILED", "SAS-R0-PCQ scheduler bootstrap failed (was: non-fatal)", 0); } + attest_report_ready("sched", "SAS-E02"); } INSTR_TS_DECL(ts_dkm); @@ -400,7 +409,9 @@ void kernel_main(void) { * P8.4: Moved BEFORE DKM driver loading so VMM self-test runs even if * a stage2 driver (e.g. fat32) crashes under KVM nested VMX. */ int run_vmm = ini_get_bool(cfg, "boot", "vmm", 1); + g_vmm_init_ok = 0; if (run_vmm && vmm_init() == 0) { + g_vmm_init_ok = 1; INSTR_TS_DECL(ts_vmm); INSTR_TS_BEGIN(ts_vmm); log_info("[UTSM] VMM init ok"); @@ -517,6 +528,8 @@ void kernel_main(void) { } else { log_warn("[UTSM] VMM unavailable (VMX not supported or disabled by FUCK)"); } + /* 启动期能力证明:VMX 可用性(未就绪时是否 panic 由 FUCK [attest] require_vmm_vmx 决定) */ + attest_report("vmm_vmx", "VMM-E30", run_vmm && g_vmm_init_ok); /* === 驱动加载 — 按 [drivers] 区过滤 === */ INSTR_TS_DECL(ts_dsm); @@ -524,6 +537,28 @@ void kernel_main(void) { dsm_load_by_manifest_ex(cfg); INSTR_TS_END(ts_dsm, "dsm_load_manifest"); + /* === 启动期能力证明:DKM 驱动派生能力 + 设计占位能力 === */ + { + u32 net_total = 0, net_wlan = 0; + net_attest_counts(&net_total, &net_wlan); + attest_report("net_wired", "NET-E02", net_total > 0); + attest_report("net_wlan", "NET-E01", net_wlan > 0); + /* FAT32 读写:块 provider 需同时具备 read+write(AHCI WRITE DMA) */ + { + const dkm_kernel_api *kapi = dkm_get_kernel_api(); + int fat_rw = (kapi && kapi->block && kapi->block->read && kapi->block->write) ? 1 : 0; + attest_report("fs_fat32_rw", "FS-E10", fat_rw); + } + /* 设计已定但未实现的能力(占位,require 决定是否阻断启动) */ + attest_report("fs_ext4_rw", "FS-E11", 1); /* FS-E 严格模式已落(DSK 侧读写闭环) */ + attest_report("pkg", "PKG-E10", 0); + attest_report("brand_anim", "BRAND-E10", 0); + attest_report("dkm_hot_unload", "DKM-E60", 0); + attest_report("dkm_api_export", "DKM-E61", 0); + attest_report("nvme_rw", "NVME-E30", 0); + attest_report("virtio_net", "VNET-E30", 0); + } + /* === F4: 分级启动自检 — FUCK [boot] selftest=0|1|2 === * 0=关 / 1=快速(结构健全性) / 2=全量(+DMA 探针 + UTSM selftest) */ { @@ -574,6 +609,10 @@ void kernel_main(void) { } } + /* === SAS-R0 启动期能力证明:交接 DSK 前统一核查 === + * FUCK [attest] require_=1(默认)而能力未就绪 → 莲花屏 panic。 */ + attest_check(cfg); + /* === 调度器静默(Phase 7/8 收尾) === * 停 LAPIC timer、注销 tick/异常 handler、杀 demo 任务——保证 * dsk_load_and_jump 的 DSK 交接路径与无调度器时逐字节一致。 */ diff --git a/CODE/UTSM/kernel/net.c b/CODE/UTSM/kernel/net.c index b3e0721..b7f40a6 100644 --- a/CODE/UTSM/kernel/net.c +++ b/CODE/UTSM/kernel/net.c @@ -36,6 +36,16 @@ static u32 net_device_count_impl(void) { return g_net_device_count; } +/* attest: 有线/无线设备计数(is_wireless 回调非空即视为无线) */ +void net_attest_counts(u32 *out_total, u32 *out_wireless) { + u32 wireless = 0; + for (u32 i = 0; i < g_net_device_count; i++) { + if (g_net_devices[i].is_wireless) wireless++; + } + if (out_total) *out_total = g_net_device_count; + if (out_wireless) *out_wireless = wireless; +} + static int net_device_info_impl(u32 index, dkm_net_device_info *out) { if (!out) return -1; if (index >= g_net_device_count) return -2; diff --git a/SYSTEM/system/deshab64/FUCK b/SYSTEM/system/deshab64/FUCK index ce68e80..d647560 100644 --- a/SYSTEM/system/deshab64/FUCK +++ b/SYSTEM/system/deshab64/FUCK @@ -1,4 +1,4 @@ -# Deshab Kernel Configuration — dev 变体(build/configs/dev/FUCK) +# Deshab Kernel Configuration — dev 变体(build/configs/dev/FUCK) # build.ps1 -Variant dev 打包前注入 SYSTEM/system/deshab64/FUCK # 开发者模式:selftest 开、dev_mode 自动跑 shell.elf 测试、日志持久化、跳过向导直达桌面 @@ -61,6 +61,32 @@ demo_fault=0 [drr] watchdog_enabled=1 +# === SAS-R0 启动期能力证明(attest) === +# require_=1(默认)而能力未就绪 → 启动即莲花屏 panic。 +# require_=0 是设计内白名单:仅限"该构建环境不可能具备"或 +# "该能力尚未实现且已登记 STATUS.md ⬜/🔶"的项,须在 CLAUDE.md §3 说明。 +[attest] +require_sealed_mem=1 +require_pckc_derive=1 +require_sched=1 +require_drr=1 +require_fs_fat32_rw=1 +require_fs_ext4_rw=1 +require_net_wired=1 +# QEMU 无 wlan 硬件(ath9k=0),wlan 栈未实现(NET-E01) +require_net_wlan=0 +# WHPX/TCG 无嵌套 VMX,QEMU 必无 +require_vmm_vmx=0 +# DRR 真 MAC = Phase 9(当前 CRC64 占位,DRR-E31) +require_drr_real_mac=0 +# 以下为设计已定未实现(STATUS.md ⬜),实现后翻转 require=1 +require_pkg=0 +require_brand_anim=0 +require_dkm_hot_unload=0 +require_dkm_api_export=0 +require_nvme_rw=0 +require_virtio_net=0 + [dsk] show_logo=1 skip_login=0 diff --git a/build/configs/dev/FUCK b/build/configs/dev/FUCK index ce68e80..d647560 100644 --- a/build/configs/dev/FUCK +++ b/build/configs/dev/FUCK @@ -1,4 +1,4 @@ -# Deshab Kernel Configuration — dev 变体(build/configs/dev/FUCK) +# Deshab Kernel Configuration — dev 变体(build/configs/dev/FUCK) # build.ps1 -Variant dev 打包前注入 SYSTEM/system/deshab64/FUCK # 开发者模式:selftest 开、dev_mode 自动跑 shell.elf 测试、日志持久化、跳过向导直达桌面 @@ -61,6 +61,32 @@ demo_fault=0 [drr] watchdog_enabled=1 +# === SAS-R0 启动期能力证明(attest) === +# require_=1(默认)而能力未就绪 → 启动即莲花屏 panic。 +# require_=0 是设计内白名单:仅限"该构建环境不可能具备"或 +# "该能力尚未实现且已登记 STATUS.md ⬜/🔶"的项,须在 CLAUDE.md §3 说明。 +[attest] +require_sealed_mem=1 +require_pckc_derive=1 +require_sched=1 +require_drr=1 +require_fs_fat32_rw=1 +require_fs_ext4_rw=1 +require_net_wired=1 +# QEMU 无 wlan 硬件(ath9k=0),wlan 栈未实现(NET-E01) +require_net_wlan=0 +# WHPX/TCG 无嵌套 VMX,QEMU 必无 +require_vmm_vmx=0 +# DRR 真 MAC = Phase 9(当前 CRC64 占位,DRR-E31) +require_drr_real_mac=0 +# 以下为设计已定未实现(STATUS.md ⬜),实现后翻转 require=1 +require_pkg=0 +require_brand_anim=0 +require_dkm_hot_unload=0 +require_dkm_api_export=0 +require_nvme_rw=0 +require_virtio_net=0 + [dsk] show_logo=1 skip_login=0 diff --git a/build/configs/release/FUCK b/build/configs/release/FUCK index 93d290f..c88111e 100644 --- a/build/configs/release/FUCK +++ b/build/configs/release/FUCK @@ -1,4 +1,4 @@ -# Deshab Kernel Configuration — release 变体(build/configs/release/FUCK) +# Deshab Kernel Configuration — release 变体(build/configs/release/FUCK) # build.ps1 -Variant release 打包前注入 SYSTEM/system/deshab64/FUCK # 发布版:调试零开销、进登录+向导正常路径、真机安全选项 @@ -59,6 +59,37 @@ demo_fault=0 [drr] watchdog_enabled=1 +# === SAS-R0 启动期能力证明(attest) === +# require_=1(默认)而能力未就绪 → 启动即莲花屏 panic。 +# release 真机:未实现能力一律阻断启动(不豁免)——宁可启动即 panic。 +# 当前仍需豁免的项 = STATUS.md ⬜/🔶 未落地项;实现后逐项删除豁免行。 +[attest] +require_sealed_mem=1 +require_pckc_derive=1 +require_sched=1 +require_drr=1 +require_fs_fat32_rw=1 +require_fs_ext4_rw=1 +require_net_wired=1 +# NET-E01 wlan 栈未实现 +require_net_wlan=0 +# VMX 为 guest 能力,真机不强制 +require_vmm_vmx=0 +# DRR-E31 Phase 9 +require_drr_real_mac=0 +# PKG-E10 +require_pkg=0 +# BRAND-E10 +require_brand_anim=0 +# DKM-E60 +require_dkm_hot_unload=0 +# DKM-E61 +require_dkm_api_export=0 +# NVME-E30 +require_nvme_rw=0 +# VNET-E30 +require_virtio_net=0 + [dsk] show_logo=1 skip_login=0