2015-12-02 1 views
1

Je me demande si quelqu'un pourrait m'aider avec cela, je suis essayer de comprendre comment gérer un moment de vérification, problème de temps d'utilisation et de laisser tomber les privilèges quand ils ne sont pas nécessaires , dans le cas par exemple c'est un lien symbolique vers le fichier qui pourrait être changé pour dire le fichier shadow. En supposant que la fonction ci-dessous est appelée pendant que le processus appelant s'exécute avec des privilèges élevés.Mettre à jour un fichier en toute sécurité de liens symboliques - C

int 
updatefile(char *file) 
{ 
    int fd; 

    if (access(file, R_OK|W_OK)) { 
    perror("access()"); 
    return (-1); 
    } 

    fd = open(file, O_RDWR); 

    /* 
    * file is written to here. 
    */ 

    printf("Updated %s on...\n", file); 
    system("date"); 

    /* 
    * elevated privileges are required here... 
    */ 

    return (0); 
} 

Répondre

3

En supposant que votre fonction access vérifie le type de fichier et détermine si l'utilisateur dispose des privilèges appropriés pour manipuler le fichier, vous êtes préoccupé par une erreur de TOCTTOU potentiel entre l'appel à access et l'appel à open.

La façon typique d'éviter ce serait:

int updatefile(char *file) 
{ 
    int fd = -1; 

    if(-1 != (fd = open(file, R_OK | W_OK))) 
    { 
     struct stat buf; 

     if(0 == fstat(fd, &buf)) 
     { 
      /* perform any necessary check on the here */ 
      /* do what ever else you need to do */ 

      /* write to the file here */ 

      /* gain elevated permissions here */ 
      /* do privileged task */ 
      /* drop back to normal permissions here */ 

      close(fd); 
     } 
     else 
     { 
      /* handle error stating the file */ 
     } 
    } 
    else 
    { 
     /* handle error for not opening file */ 
    } 
} 

La raison pour que cela fonctionne, est que nous remettons à faire des contrôles au dossier qu'après nous avoir une « poignée » au fichier. Nous pouvons dire si l'utilisateur n'a pas les permissions pour ouvrir le fichier par la valeur errno dans le bloc externe else;

Si nous sommes en mesure d'obtenir un "handle" du fichier, nous pouvons faire ce que nous voulons. Parce que nous maintenons le "handle" à partir du moment où nous ouvrons le fichier, jusqu'à quand nous effectuons nos contrôles et enfin lorsque nous utilisons le fichier; un malveillant ne serait pas en mesure de modifier le système de fichiers entre vérification et utilisation.

Hope this helps T.

+0

Le schéma de comparaison inverse est inélégant et obsolète. – chqrlie

+0

@chqrlie c'est le schéma que j'ai toujours vu comme un moyen d'éviter TOCTTOU. soin de partager un schéma plus élégant et moderne? – thurizas

+0

Activer plus d'avertissements du compilateur. 'gcc -Wall -W -Werror' ou' clang -Weverything -Werror' empêche cela et bien d'autres erreurs et fautes de frappe. La chose de comparaison inverse réduit la lisibilité à mon humble avis. – chqrlie