Systèmes de fichiers & Montages · Section 2
stat(2)
Récupère les métadonnées d'un fichier (taille, permissions, dates, propriétaire) par son chemin.
Signature
#include <sys/stat.h>
int stat(const char * pathname, struct stat * statbuf);- pathname
- Chemin du fichier à stater. Les liens symboliques sont suivis (lstat() pour les conserver).
- statbuf
- Tampon de sortie ; le noyau y écrit une struct stat (ou struct stat64 en ABI 32 bits).
Description
stat() remplit *statbuf avec les métadonnées du fichier en pathname : périphérique, inode, mode (type + bits de permission), nlink, uid, gid, rdev (fichiers spéciaux), taille, taille de bloc, blocs alloués, atime/mtime/ctime. L'appel n'ouvre PAS le fichier — il ne lit que l'inode — et déréférence les liens symboliques (utiliser lstat() pour stater le lien). Le code moderne préfère statx() ou newfstatat() parce que (a) ils évitent le cast time_t 32 bits qui cassait les stat() pré-2038 sur i386, (b) statx() permet de ne demander que les champs nécessaires (moins coûteux sur les systèmes de fichiers réseau), et (c) newfstatat()/statx() supportent des chemins relatifs à un dirfd pour la traversée sans course. Sur aarch64, stat() et lstat() ne sont pas exportés du tout — seuls newfstatat()/statx() existent, et la libc traduit.
Numéros par architecture
| Architecture | Numéro | ABI | Point d'entrée |
|---|---|---|---|
| x86 (i386) | 106 | i386 | sys_newstat |
| x64 (x86_64) | 4 | common | sys_newstat |
Historique noyau
Introduit dans Linux 1.0.
1.0
stat() est l'un des appels système originels (Linux 1.0). Le nom 'newstat'/'sys_newstat' reflète la séparation interne noyau entre le stat() initial (struct ancienne) et l'expansion post-1.4 en struct stat64 ; l'espace utilisateur moderne atteint toujours le nouveau layout via la glibc.
2.6.16
fstatat() (alias newfstatat()) a été ajouté avec la famille *at (2.6.16) pour permettre la résolution relative à un dirfd, éliminant les courses chdir() du stat() classique.
4.11
statx() (Linux 4.11) a ajouté un masque de requête pour ne demander que certains champs, retourne struct timespec64 pour tous les timestamps (compatible post-2038), et expose des informations spécifiques Linux (btime, drapeaux d'attributs, mount ID). L'interface moderne recommandée.
seccomp & conteneurs
Docker default profile
Autorisé
Podman default profile
Autorisé
La famille stat (stat, lstat, fstat, newfstatat, statx) est autorisée par tout profil par défaut. Tout programme en appelle constamment — ls, cp, chargeur dynamique, tout shell — donc les bloquer est impraticable. Le levier seccomp pour le confinement filesystem est à openat() et Landlock, pas à stat.
libseccomp
// Allow the stat family
for (int s : { SCMP_SYS(stat), SCMP_SYS(lstat), SCMP_SYS(fstat),
SCMP_SYS(newfstatat), SCMP_SYS(statx) })
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, s, 0);Exemple strace
$ strace -e stat,fstat,newfstatat,statx ls /etc/hostname
newfstatat(AT_FDCWD, "/etc/hostname", {st_mode=S_IFREG|0644, st_size=15, …}, 0) = 0
statx(0, NULL, AT_STATX_SYNC_AS_STAT, STATX_ALL, NULL) = -1 EFAULTstrace moderne affiche newfstatat() pour ce que l'utilisateur appelle stat() (la glibc réécrit). Utiliser -e trace=stat pour couvrir toute la famille symboliquement. -y résout dirfd en chemin. Les ~100 premiers stat() d'un programme sont le chargeur dynamique parcourant le PATH — sans intérêt ; l'activité applicative commence après.
Sécurité & observabilité
stat() seul est en lecture et rarement intéressant à superviser — trop bruyant, faible impact. Exceptions : stat() sur /etc/shadow, /root/.ssh/, ou /proc/<pid>/mem depuis un non-root est un fort signal de reconnaissance (l'attaquant vérifie s'il pourra ouvrir plus tard). Pour la sécurité conteneur, comparer l'inode et le mount de /proc/self/exe aux valeurs attendues détecte les rootkits de substitution — la donnée vient d'un stat(). Le tracepoint eBPF sys_enter_newfstatat capture tout stat moderne ; à coupler au hook LSM file_open pour une décision plus fidèle.
Erreurs
- EACCES
- Permission de recherche refusée sur un composant de pathname (pas sur le fichier — stat() ne nécessite que la permission de traversée).
- EBADF
- —
- EFAULT
- —
- ELOOP
- Trop de boucles de liens symboliques.
- ENAMETOOLONG
- pathname plus long que PATH_MAX.
- ENOENT
- Un composant de pathname n'existe pas, ou pathname est vide.
- ENOMEM
- —
- ENOTDIR
- Un composant non final de pathname n'est pas un répertoire.
- EOVERFLOW
- Un champ dépasse la plage de la struct stat de cette ABI (par ex. fichier > 2 GiB en build 32 bits non-LFS). statx() évite ce piège.