Rapport de tests — findings

Issues découvertes par la suite anti-régression (test/anti-regression-suite). Chaque finding est référencé par un test qui le documente/pinne.

F1 — Build kernel cassé par le nightly non épinglé (bloquant) — ✅ RÉSOLU

Épinglé sur nightly-2026-08-20 (dernier bon vérifié : bisect 08-20 OK / 08-23 cassé, cause PR rust-lang/rust#160302 mergé le 23/08 à 21:33 UTC, commit fb6531d550e0). Le code exige en outre Step::forward/backward_overflowing (PR #155114, 09/07/2026) ⇒ fenêtre compatible [2026-07-10 .. 2026-08-22]. Correctif associé : [profile.dev] opt-level = 0 → 1 car O0 déclenche une ICE LLVM distincte (#158532) sur les intrinsèques AVX2. Builds debug, release, selftest et gate hôte tous vérifiés verts. framebuffer/x86/avx2.rs utilise #[target_feature(enable = "avx2")]. Sur rustc 1.100.0-nightly, activer sse/avx sur une cible soft-float (x86_64-unknown-none) est une erreur dure (lint x86_softfloat_sse). cargo make kernel échoue sur toutes les branches. Options :

  1. (recommandé, immédiat) Épingler l'outilchain : channel = "nightly-2026-06-xx" dans rust-toolchain.toml — dernière version connue fonctionnelle ;
  2. (long terme) Adapter avx2.rs : runtime detection + assembly inline ou wrapper compilé sans soft-float constraint.

F2 — VfsTimestamp::to_filetime déborde — ⏳ à faire

(secs + WINDOWS_EPOCH_OFFSET) as u64 * 10_000_000 sans arithmetic checkée : panic debug / wrap release au-delà de ~an 60000. Entrée contrôlée par le disque ou le réseau (chemins stat) ⇒ à traiter comme entrée hostile. Fix proposé : checked_mul → FsError::ArithmeticOverflow.

F3 — FsCapabilities::xfs()/btrfs() : valeurs PiB au lieu de EiB — ✅ RÉSOLU

XFS = 8 EiB réels ; btrfs clampé à u64::MAX (16 EiB = 2^64). Tests mis à jour. Commentaires « 8 EiB »/« 16 EiB », chaînes littérales à 5 facteurs 1024 ⇒ valeurs réelles 8 PiB / 16 PiB (16 EiB ne tient même pas dans u64). Décider : corriger les commentaires ou l'arithmétique.

F4 — parse_ipv6_literal sur-accepte le :: — ⏳ à durcir (RFC 4291)

RFC 4291 interdit :: quand 8 groupes explicites sont déjà présents ; le parseur accepte 1:2:3:4:5:6:7:8::. Sans danger immédiat (sortie bien formée) mais à durcir pour la conformité.

F5 — OpenReply n'implémente pas KnownLayout — ✅ RÉSOLU

KnownLayout dérivé via zerocopy (déjà dépendance) sur toute la surface de payloads repr(C) + InlineBlobHeader. Test de regression roundtrip decode_fixed ajouté pour chaque struct fixe.

F6 — ENOTSUP = 52 n'est pas la valeur Linux — ✅ RÉSOLU

Renommé 52 → 95 (= Linux x86_64) : constante ABI, selftest kernel, tests golden, entrée changelog ABI.

F7 — Test unitaire préexistant cassé depuis longtemps

strate-fs-abstraction/tests/unit_tests.rs importait fs_abstraction (ancien nom de crate) : aucun test de cette crate ne tournait depuis le renommage. Corrigé — preuve que l'absence de CI de test laisse pourrir la couverture silencieusement.

F8 — Constantes POSIX fausses dans strat9_syscall::flag — ✅ RÉSOLU

Trouvé lors de la passe 2 par la table dorée Linux :

  • O_NOFOLLOW = 0o100000 → en réalité O_CLOEXEC sur Linux ; corrigé à 0o400000 ;
  • O_NOCTTY = 0o400000 → en réalité O_NOFOLLOW sur Linux (!) ; corrigé à 0o000400, détecté par le test doré lui-même après le premier fix ;
  • O_DSYNC = 0o02000000 → O_CLOEXEC aussi ; corrigé à 0o10000. La traduction posix_oflags_to_strat9 (crate abi) utilisait ses propres copies correctes — mais tout composant consommant ces constantes directement cassait. Leçon : les tables dorées attrapent ce que la relecture manuelle rate.

F9 — Test inline lockfree_ring::full_ring faux depuis sa création — ✅ CORRIGÉ

Découvert dès la première exécution réelle des tests inline du kernel (jamais possibles avant le harnais L2) : LockFreeRing::new(4, 64) crée 4 slots (next_power_of_two), donc 4 writes réussissent — le test attendait Full au 4ᵉ. Le test était off-by-one ; corrigé dans le bloc #[cfg(test)].

F10 — Port I/O out 0xe9 dans les primitives de sync — ✅ CONTOURNÉ

emit_trace_e9 (spinlock.rs) et d'autres traces diagnostiques émettent sur le port série E9 via asm!("out 0xe9") : instruction ring-0, SIGSEGV garanti en userspace. Compilé hors du binaire de test uniquement sous le cfg kernel_l2_host (posé par workspace/kernel-l2-tests/.cargo/config.toml) ; production inchangée.

F11 — La mailbox d'événements N1 est LIFO — ⚠️ épinglé, à arbitrer

notify_scheduler/poll_scheduler_events s'appuient sur IntrusiveMailbox (stack documentée « order is reversed on reception ») : les événements arrivent en ordre INVERSE d'émission. Sans gravité pour des événements indépendants, mais toute logique future dépendant de l'ordre causal (SchedTick avant Wakeup…) héritera de cette inversion. Épinglé AS IMPLEMENTED.

F12 — get_initfs_file_bytes ne retrouve pas les fichiers enregistrés avec préfixe — ⚠️ à vérifier au runtime

Le boot enregistre les modules Limine avec leur chemin complet (/initfs/fs-ext4, cf. log « Registered /initfs/fs-ext4 »), mais le lookup strip /initfs/ avant recherche : clé stockée /initfs/fs-ext4, clé cherchée fs-ext4 → raté. Conséquence possible : exec d'initfs via ce chemin cassé. Épinglé dans kernel_vfs_scheme.rs ; à confirmer sur le runtime QEMU.

F13 — Écrire dans un pipe à lecture fermée boucle à l'infini — ✅ CORRIGÉ

Trouvé par le harnais L2 (le test pendait indéfiniment) : Pipe::write évalue la condition « read end closed → EPIPE » via wait_until, mais le bras Err(_) => {} du match avalait l'erreur et relançait la boucle — spin 100% CPU infini au lieu de retourner EPIPE. Violation directe du contrat POSIX (SIGPIPE/EPIPE). Fix : propagation de l'erreur fatale (Err(e) => return Err(e)), seul Again reste transitoire. Impact production réel : tout processus écrivant dans un pipe dont le lecteur est mort (shell pipelines, IPC interne) se figeait.

F14 — Limine v8.7 panique sur les kernels fraîchement construits — 🔍 investigation ouverte

Constaté en tentant la validation L3/L4 : Limine PANIC: elf: No higher half PHDRs exist au chargement de boot():/boot/kernel.elf, sur NOTRE kernel selftest ET sur le kernel release reconstruit le 25/08 15:02. Pourtant readelf -l montre 4 PT_LOAD en higher-half (0xffffffff8000_0000+), entry point compris, ET_EXEC non-relocatable — le check elf64_get_ranges de Limine v8.7.0 (common/lib/elf.c:646) devrait compter 4 ranges. Éléments discriminants :

  • les binaires Limine sont identiques (md5) dans les deux worktrees (clone v8.x-binary @ aad3edd, jan 2025) ;
  • l'ISO construite ce matin depuis le VIEUX kernel (mai) bootait ;
  • le kernel a donc changé, pas Limine → propriété ELF subtile en cause (memsz ~2 Go de .bss par segment ? ordre/alignement des PHDRs ?). ⚠️ CONTEXTE : le flux de boot est en migration (bootloader perso BIOS workspace/bootloader + create-image.sh, commits UEFI sur d'autres branches). À arbitrer : réparer la chaîne Limine (utile pour les selftests L3/L4 automatisés) ou basculer le harnais QEMU sur le bootloader perso. En attendant, la porte CI L0/L1/L2 (364 tests) ne dépend pas du boot QEMU.

Couverture ajoutée (L2 — code kernel réel sur hôte)

SuiteTestsPérimètre
inline kernel récupérés13lockfree_ring (8), mailbox (3), boot/toml (3*)
kernel-l2-tests/tests/buddy_allocator.rs6buddy réel sur mémoire hôte: alignement par ordre, épuisement→OOM propre, zéro après purpose-alloc, stress 2000 ops avec payload tags, tolérance double-free
kernel-l2-tests/tests/kernel_sync_namespace.rs10FixedQueue FIFO/wraparound/overflow, SpinLock réel, namespace bind/unbind/resolve longest-prefix
kernel-l2-tests/tests/kernel_channels.rs9canal MPMC typé (multi-producteurs, disconnect lifecycle), SyncChan registre + drain-first après destroy
kernel-l2-tests/tests/kernel_n1_semaphores.rs6+2 inlineévénements N1 (ordre LIFO épinglé), sémaphores POSIX (comptage, destroy, registre)

| kernel-l2-tests/tests/kernel_vfs_scheme.rs | 7 | finalize_pseudo_stat, registre KernelScheme (/initfs), routeur global de schemes, F12 |

| kernel-l2-tests/tests/kernel_vfs_fd.rs | 13 | OpenFile (offset partagé POSIX, permissions, EOF), FileDescriptorTable (réuse plus bas fd, dup F_DUPFD, cloexec), Nice saturé + AtomicNice |

| kernel-l2-tests/tests/kernel_pipes.rs | 9 | pipes kernel: FIFO, wraparound 4096, EOF/EPIPE lifecycle (F13), registre PipeScheme |

Total porte CI : 364 tests verts.

Reste candidat L2 : classes d'ordonnancement complètes (nécessitent une fake AddressSpace), fake userslice pour handlers read/write d'IpcScheme.

Total porte CI : 327 tests verts.

Reste candidat L2 (documenté) : vfs/scheme.rs + routeur — bloqué par memory/userslice.rs qui valide les pointeurs userspace contre les tables de pages x86 réelles ; nécessitera une fake de validation de région.

* comptage approximatif des modules inclus. Harnais : crate ombre workspace/kernel-l2-tests — modules kernel inclus verbatim via #[path], fakes fonctionnels pour IRQ/percpu/silo/HHDM.

SuiteTestsPérimètre
abi/tests/abi_stability.rs10golden syscalls (169), layouts, magics
abi/tests/errno_abi.rs4valeurs Linux, convention de détection
abi/tests/flags_translation.rs8POSIX↔Strat9 exhaustif (1536 combos)
abi/tests/ip_parsing.rs9IPv4/IPv6 edge cases
abi/tests/ipc_codec_roundtrip.rs16codec bornes/roundtrip/endian
abi/tests/ipc_payload_wire.rs12wire format schemes VFS
fs-abstraction/tests/safe_math_edge_cases.rs23arith safe exhaustive
fs-abstraction/tests/types_conformance.rs13+1mode bits, FILETIME, caps
abi/tests/ipc_handshake.rs8handshake IPC wire + validation réservés
abi/tests/data_types.rs9SiloMode, DirentHeader, PCI, tailles structs
syscall/tests/error_and_flags.rs8Error↔errno roundtrip, demux RAX, flags Linux
syscall/tests/dirent_wire.rs10getdents packed parsing, SchemeV2, SigAbi
intel-ethernet/tests/descriptors.rs10layouts SDM 16B, anneaux Rx/Tx
driver-net-proto/tests/wire_protocol.rs3opcodes + headers IPC réseau
alloc-freelist/tests/allocator.rs6GlobalAlloc: alignement, réuse, OOM propre

Porte CI : cargo make ci-tests — 162+ tests hôte verts (stage GitLab test).

Porte CI : cargo make ci-tests (stage GitLab test, job test-host).

Prochaines étapes proposées (L2/L3/L4)

  1. L2 kernel-hôte : extraire la logique pure IPC/mémoire en modules testables hôte.
  2. L3 : généraliser le pattern selftest (PASS/FAIL série grep-able) à tous les sous-systèmes kernel.
  3. L4 : harnais QEMU automatisé (boot ISO + grep série + timeout) en job GitLab.