Skip to main content

Module sandbox

Module sandbox 

Source
Expand description

Confinement d’un ring (Temps 3f) — sous-module air-sys-syscall::io_uring::sandbox. Matérialise la décision de soundness S3 : un ring qui ne peut émettre que les opérations explicitement mises en liste blanche, imposé par le kernel.

Référence normative : docs/specs/layer-0/io-uring-3f-sandbox.md.

§Pourquoi

io_uring exécute des opérations (read, openat2, connect…) qui ne passent pas par l’interface syscall classique : un filtre seccomp qui bloque le syscall openat2 n’empêche pas un IORING_OP_OPENAT2 soumis via le ring — voie de contournement historique des bacs à sable. La réponse : restreindre le ring lui-même. Les restrictions io_uring complètent seccomp/Landlock (family-security), en défense en profondeur ; elles ne les remplacent pas. C’est la brique io_uring du modèle de capabilities d’Air (ADR-001 AirCom, ADR-010 entitlements signés) — la couche 0 fournit le mécanisme, la politique vit en couche 5.

§Le flux en trois temps (imposé kernel, reflété par l’API)

  1. Créer désactivé : IoUringBuilder::restrict crée le ring IORING_SETUP_R_DISABLED et applique la liste blanche (REGISTER_RESTRICTIONS) — possible uniquement tant qu’il est désactivé.
  2. Activer : IoUring::enable (REGISTER_ENABLE_RINGS).
  3. Immuable ensuite : après enable, les restrictions ne peuvent plus être assouplies (imposé kernel) ; toute soumission avant enable est refusée.

Default-deny : dès qu’un opcode est mis en liste blanche, le kernel refuse tout le reste (-EACCES).

use air_sys_syscall::io_uring::{IoUringOpcode, RegisterOp, RestrictionSet, SqeFlagSet};

// Un service AirCom « réseau seul » : le ring ne pourra jamais émettre
// openat2, unlinkat, etc. — garanti kernel.
let policy = RestrictionSet::new()
    .allow_op(IoUringOpcode::Socket)
    .allow_op(IoUringOpcode::Connect)
    .allow_op(IoUringOpcode::Send)
    .allow_op(IoUringOpcode::Recv)
    .allow_op(IoUringOpcode::Close)
    .allow_register(RegisterOp::ProvidedBuffers)
    .require_sqe_flags(SqeFlagSet::new().fixed_file());
assert_eq!(policy.as_slice().len(), 7);
// let mut ring = IoUringBuilder::new(entries).restrict(policy.as_slice()).build()?;
// ring.enable()?;  // à partir d'ici, tout opcode hors liste échoue.

Structs§

RestrictionSet
Liste blanche de ce qu’un ring confiné pourra faire (décision S3). Default-deny : ce qui n’est pas explicitement autorisé est refusé par le kernel. Construite par combinateurs, puis passée à IoUringBuilder::restrict via as_slice.
SqeFlagSet
Ensemble de drapeaux IOSQE_* pour les restrictions de drapeaux SQE (RestrictionSet::allow_sqe_flags / RestrictionSet::require_sqe_flags). Default = aucun drapeau. Builder chaînable. Partage la représentation des drapeaux avec SubmitOptions.

Enums§

RegisterOp
Register opcode qu’un ring confiné peut être autorisé à effectuer (RESTRICTION_REGISTER_OP). Newtype typé plutôt qu’un u8 magique (ADR-021 conv. 3 : chaque opération est une variante nommée). #[non_exhaustive] : de futurs kernels peuvent en ajouter.