Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR-111 — air-log (AirLogManager) : sink de logs opérationnels (couche 1), journald natif sans C, anti-injection, distinct d’AirCom

Statut : Accepté (2026-07-26, décision BDFL). RFC de direction (ADR-015). S’appuie sur ADR-077 (managers de domaine couche 1), ADR-001 (AirCom = bus IPC événementiel), ADR-088 (sans libc C), ADR-029 (nommage), ADR-019 (modèle d’erreurs), ADR-089 (SecurityManager).

Catégorie : Architecture couche 1 (nouveau manager de domaine). Vague 1 #4 du triage des écarts OpenSSH.

Contexte

OpenSSH journalise vers syslog/journald ses événements opérationnels (connexions, échecs d’auth, erreurs). air-sshd ne publie aujourd’hui que sur AirCom — le bus IPC événementiel programmatique d’Air ([ADR-001]), consommé par des programmes. Or un administrateur attend un journal opérationnel consultable par les outils standard (journalctl) : c’est une surface distincte d’AirCom (destinataire humain/ops vs consommateur logiciel), et elle manque.

Deux exigences la rendent délicate : (1) rester sans libc C ([ADR-088]) alors que la voie naturelle serait libsystemd (C) ; (2) on journalise des données contrôlées par l’attaquant (nom d’utilisateur, commentaire de clé, IP) — vecteur classique d’injection de logs.

Directive BDFL (2026-07-26). « Je vois un manager de log… distinct d’AirCom. » Détail tranché en discussion : journald natif d’abord + fallback ; pont AirCom opt-in ; API typée ; anti-injection obligatoire ; envoi drop-safe ; abstraction de sink.

Décision

1. air-log est un manager de domaine couche 1, distinct d’AirCom

Une crate air-log exposant un AirLogManager ([ADR-077]) : le sink de logs opérationnels (destinés à l’admin / journalctl), séparé d’AirCom ([ADR-001], bus événementiel programmatique). no_std + alloc, erreurs AirError ([ADR-019]), au-dessus d’air-socket (couche 1) — jamais la couche 0 en direct. Pont opt-in : un consommateur peut demander de mirrorer certains événements AirCom vers le log (ex. AuthFailed → warning), mais les deux surfaces restent indépendantes.

2. journald natif, écrit par nous (sans C) + fallback résilient

Le sink par défaut parle le protocole journald natif — socket datagram /run/systemd/journal/socket, champs structurés CLÉ=valeur (cadrage longueur-préfixé pour les valeurs multi-lignes) — implémenté par nous (pas de libsystemd C, cohérent [ADR-088]). Si journald est absent (systemd non présent), fallback résilient (stderr / fichier). Le protocole natif est simple et documenté ; l’écrire nous coûte peu et évite une dépendance C.

3. Anti-injection de logs — obligatoire

On journalise des données d’attaquant ⇒ toute valeur est neutralisée (retours à la ligne / caractères de contrôle échappés ou rejetés) avant émission. Le cadrage binaire longueur-préfixé de journald protège par construction (une valeur ne peut pas « sortir » de son champ) — argument supplémentaire pour journald natif plutôt que syslog texte. Fuzz de l’encodeur (valeurs arbitraires → trame journald bien formée).

4. API typée + envoi drop-safe

API typée : niveaux (emergency … debug) + champs structurés (user, peer, method, session_id…), pas des chaînes libres. Émission datagram fire-and-forget, drop-safe sous flood : un pic de logs ne doit jamais bloquer le réacteur d’un démon (air-sshd sous DoS) — on jette plutôt que de bloquer, avec compteur de pertes.

5. Abstraction de sink

Le sink est abstrait (trait) : journald / fichier / futur journal Air natif (cf. air-launchd v2) — pour ne pas se lier à systemd. Le manager choisit le sink à la construction ; le code appelant ne dépend que de l’API typée.

Conséquences

Positives.

  • Journal opérationnel standard (journalctl) pour les démons Air, distinct du bus programmatique AirCom — chaque surface pour son public.
  • Sans C : protocole journald natif, pas de libsystemd ; tient sur *-linux-air.
  • Anti-injection par construction (cadrage journald) — classe de vulnérabilités fermée.
  • Drop-safe : la journalisation ne devient pas un vecteur de DoS.
  • Découplé de systemd (abstraction de sink) : portable vers un journal Air futur.

Négatives / coûts assumés.

  • Protocole journald à maintenir (écrit maison) : suivre l’évolution du format natif ; coût faible (format stable), fuzz + tests de conformité.
  • Nouvelle crate couche 1 aux exigences (coverage, fuzz encodeur, AirError).
  • Pont AirCom à concevoir avec soin (opt-in, pas de double-comptage / boucle).

Mise en œuvre (référence, hors décision). Incréments : (a) crate air-log couche 1 (API typée + encodeur journald natif + fallback) ; (b) fuzz de l’encodeur + anti-injection ; (c) sink abstrait ; (d) câblage air-sshd/air-ssh + pont AirCom opt-in. Non engagés par cet ADR.

Alternatives rejetées

Aucune alternative n’a été consignée lors de l’instruction.