Quel est un bon moyen de simuler O_NOFOLLOW sur des systèmes sans cet indicateur?

Je voudrais pouvoir simuler open avec O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW et O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW sur les systèmes qui ne prennent pas en charge O_NOFOLLOW . Je peux un peu réaliser ce que je demande avec:

 struct stat lst; if (lstat(filename, &lst) != -1 && S_ISLNK(lst.st_mode)) { errno = ELOOP; return -1; } mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, mode); 

mais alors je présente une condition de concurrence critique et éventuellement un problème de sécurité.

Je pensais peut-être créer un fichier factice avec seulement l’utilisateur capable d’écrire, un peu comme touch le filename , faire la vérification lstat , puis utiliser chmod après avoir fini d’écrire (pour corriger les bits de mode de fichier), mais je pourrais le faire. ignorer quelque chose de majeur (par exemple, si le fichier au filename du filename existe, n’est pas un fichier normal ou est déjà un lien symbolique).

Qu’est-ce que tu penses?

Votre proposition a toujours une condition de concurrence:

  • Mallory crée le lien qu’il veut que vous suiviez;
  • Vous open() le lien avec O_CREAT ;
  • Mallory remplace le lien par un fichier normal;
  • Vous faites votre test lstat() , qui passe (pas un lien);
  • Mallory remplace à nouveau le fichier normal par le lien.

Vous pouvez résoudre ce problème pour le cas non- O_TRUNC en appelant fstat() sur le descripteur de fichier ouvert et lstat() sur le chemin, et en veillant à ce que les membres .st_dev et .st_ino soient identiques.

Cependant, cela ne fonctionne pas si vous utilisez O_TRUNC – au moment où vous avez découvert la supercherie, il est trop tard – Mallory vous a déjà incité à tronquer l’un de vos fichiers importants.

Je pense que la méthode traditionnelle pour éliminer le trou sans le support O_NOFOLLOW est la suivante:

  • Créez un répertoire temporaire avec le mode 700 . Erreur (ou nouvelle tentative) si mkdir() échoue en raison d’un répertoire existant;
  • Créez votre nouveau fichier dans le répertoire temporaire;
  • Utilisez rename() pour déplacer de manière atomique le fichier temporaire vers le nom de la cible.
  • Supprimer le répertoire temporaire.