2010-05-26 5 views
1

Je voudrais pouvoir simuler en toute sécurité open avec O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW et O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW sur les systèmes qui ne supportent pas O_NOFOLLOW. Je peux un peu réaliser ce que je vous demande avec:Quelle est une bonne façon de simuler O_NOFOLLOW sur des systèmes sans ce drapeau?

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 j'introduire une condition de course et peut-être un problème de sécurité.

je pensé à créer peut-être un fichier fictif avec seul l'utilisateur étant capable d'écrire, un peu comme touch ing filename, faire le chèque lstat, puis en utilisant chmod après avoir fini d'écrire (pour corriger les bits de mode de fichier), mais je pourrais être en train de négliger quelque chose de majeur (par exemple si le fichier à filename existe, n'est pas un fichier régulier, ou est déjà un lien symbolique).

Qu'en pensez-vous?

Répondre

4

Votre proposition a encore une condition de course:

  • Mallory crée le lien qu'il veut vous suivre;
  • 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 régulier par le lien.

Vous pouvez résoudre ce problème pour la non O_TRUNC cas en appelant fstat() sur votre descripteur de fichier ouvert, ainsi que lstat() sur le chemin, et veiller à ce que les .st_dev et .st_ino membres sont les mêmes. Cependant, cela ne fonctionne pas si vous utilisez O_TRUNC - au moment où vous avez découvert la tromperie, il est trop tard - Mallory vous a déjà amené à tronquer l'un de vos fichiers importants.

je crois que la façon traditionnelle d'éliminer le trou sans O_NOFOLLOW support est:

  • Créer un répertoire temporaire avec le mode 700. Erreur (ou réessayer) si mkdir() échoue en raison du 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 cible;
  • Supprimez le répertoire temporaire.
Questions connexes