Skip to content
/linux-syscalls

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

ArchitectureNuméroABIPoint d'entrée
x86 (i386)106i386sys_newstat
x64 (x86_64)4commonsys_newstat

Historique noyau

Introduit dans Linux 1.0.

  1. 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. 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.

  3. 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 EFAULT

strace 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.

Syscalls liés