Skip to main content

fchmodat2

Function fchmodat2 

Source
pub fn fchmodat2(
    dirfd: DirFd<'_>,
    path: &CStr,
    mode: Mode,
    flags: ChmodFlags,
) -> Result<(), Errno>
Expand description

Modifie les permissions d’un fichier en honorant les drapeaux AT_*.

Wrappeur de fchmodat2(2) (numéro 452 sur x86_64 et aarch64, Linux ≥ 6.6).

§Pourquoi un second wrapper de chmod par chemin

Le syscall noyau fchmodat historique ne prend que 3 arguments (dirfd, path, mode) : la couche C ajoute bien un paramètre flags dans sa signature, mais le noyau ne le reçoit jamais — AT_SYMLINK_NOFOLLOW y est donc silencieusement ignoré, et le chemin est toujours re-résolu en suivant le lien symbolique final. C’est le même piège que faccessat / [faccessat2], résolu de la même façon : un syscall à 4 arguments qui, lui, applique les drapeaux.

ChmodFlags::SYMLINK_NOFOLLOW ferme donc une fenêtre TOCTOU : entre le moment où l’on crée un nœud (un socket Unix, par exemple) et celui où l’on restreint ses permissions, un tiers ayant droit d’écriture sur le répertoire conteneur peut substituer un lien symbolique et détourner le chmod vers un fichier tiers. Avec ce drapeau, la substitution ne réussit pas : Linux ne sait pas changer les permissions d’un lien symbolique et rend EOPNOTSUPP. L’appelant obtient donc, en plus du chmod, la preuve que le chemin désignait bien le nœud attendu — ou une erreur qu’il peut traiter.

EINTR est remonté tel quel : aucun retry automatique en couche 0 (ADR-021).

§Errors

  • EOPNOTSUPP : SYMLINK_NOFOLLOW demandé et le chemin final est un lien symbolique (Linux ne modifie pas les permissions d’un lien).
  • ENOENT : chemin inexistant.
  • EPERM / EACCES : pas le droit de modifier ce nœud.
  • ENOSYS : noyau < 6.6 (Air cible 6.12+, cf. ADR-004).

§Examples

use air_sys_syscall::fs::fchmodat2;
use air_sys_types::fs::{ChmodFlags, DirFd};

// Restreint le socket que nous venons de lier — sans jamais suivre un lien.
let result = fchmodat2(DirFd::Cwd, c"/run/air/forward.sock", 0o600, ChmodFlags::SYMLINK_NOFOLLOW);