Skip to main content

clone3

Function clone3 

Source
pub unsafe fn clone3(args: &CloneArgs) -> Result<CloneResult, Errno>
Expand description

Crée un nouveau processus via le syscall clone3(2).

Cf. docs/specs/layer-0/family-process.md section clone3. La fonction retourne deux fois en cas de succès : une fois côté parent (avec le PID enfant, et un PidFd si [CloneFlags::PIDFD] était positionné), une fois côté enfant (avec [CloneResult::Child]). Le match sur le résultat est le seul moyen sûr de discriminer.

§Périmètre

clone3 est dédié à la création de processus style fork ; la création de thread passe par clone_thread (modèle de retour distinct, cf. sa doc et la note d’implémentation au-dessus de clone_thread) :

  • args.flags peut contenir tous les bits hors [CloneFlags::VM] / [CloneFlags::THREAD] / [CloneFlags::SIGHAND] : ces drapeaux de création de thread sont refusés ici avec [Errno::EINVAL] (leur retour CloneResult::Child serait unsound sur une pile neuve — voir clone_thread).
  • args.stack doit être None (refusé sinon avec [Errno::EINVAL] ; une pile dédiée n’a de sens que pour un thread → clone_thread).
  • args.exit_signal est typiquement Some(Signal::SIGCHLD).

§Safety

clone3 peut créer un thread partageant la mémoire avec le parent (CLONE_VM), situation que Rust ne peut pas vérifier. L’appelant doit donc garantir, selon le scénario :

  • Fork classique (sans CLONE_VM) — aucune précondition particulière sur la mémoire. L’enfant possède une copie CoW de l’espace d’adressage du parent ; tous les invariants Rust restent valables des deux côtés.

  • Création de thread (CLONE_VM | CLONE_THREAD | CLONE_SIGHAND) — non géré par clone3 ; l’appel échoue avec [Errno::EINVAL]. Utiliser clone_thread, qui exécute le thread via un trampoline assembleur (pas de retour Rust sur pile neuve) et expose le join par CLONE_CHILD_CLEARTID.

  • Namespaces (CLONE_NEWUSER, CLONE_NEWNS, CLONE_NEWPID, …) — l’appelant doit posséder les capabilities nécessaires (typiquement CAP_SYS_ADMIN) ; à défaut, le syscall retourne [Errno::EPERM]. Sur Ubuntu 24.04, les user namespaces non privilégiés sont restreints par AppArmor (kernel.apparmor_restrict_unprivileged_userns=1) et l’appel échoue avec [Errno::EPERM] même côté unprivileged.

  • « Retourne deux fois » — après succès, le syscall est exécuté côté parent et côté enfant ; les deux retours apparaissent ici comme Ok(_) distincts. L’enfant doit terminer son travail (typiquement par std::process::exit ou un futur exit_group wrapper) ; revenir « plus loin » dans le code appelant produit généralement un comportement surprenant pour l’utilisateur.

§Errors

  • [Errno::EINVAL] : combinaison de flags refusée par cette PR (création de thread) ou par le kernel (configuration invalide).
  • [Errno::EPERM] : capabilities insuffisantes (NEWUSER refusé, AppArmor, …).
  • EAGAIN (constante non encore définie dans le stub partiel Errno) : limites système atteintes (nombre de processus).
  • ENOMEM (idem) : mémoire kernel insuffisante.
  • EUSERS (idem) : trop de namespaces utilisateurs créés.
  • ENOSYS (idem) : kernel antérieur à 5.3 (clone3 indisponible).

Les constantes nommées en prose ci-dessus seront promues en pub const au fil des PRs qui les rencontrent réellement (cf. note « stub partiel » en tête du module errno).