Pregunta

Me gustaría ser capaz de forma segura open simular con O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW y O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW en sistemas que no O_NOFOLLOW apoyo. algo que puedo lograr lo que estoy pidiendo con:

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);

pero entonces introducir una condición de carrera y, posiblemente, un problema de seguridad.

pensé tal vez crear un archivo ficticio con sólo el usuario pueda escribir, algo así como touching filename, haciendo la comprobación lstat, y luego usando chmod después de que termino de escribir (para corregir los bits de modo de archivo), pero podría ser pasando por alto algo importante (por ejemplo, si el archivo en filename existe, no es un archivo normal, o es un enlace simbólico).

¿Qué opinas?

¿Fue útil?

Solución

Su propuesta aún tiene una condición de carrera:

  • Mallory crea el enlace que quiere que siga;
  • open() el enlace con O_CREAT;
  • Mallory reemplaza el vínculo con un archivo normal;
  • Usted hace su prueba lstat(), que pasa (no un enlace);
  • Mallory reemplaza el archivo regular con el enlace de nuevo.

Se puede solucionar este problema para el caso no O_TRUNC llamando fstat() en su descriptor de fichero abierto, así como lstat() en el camino, y la garantía de que los miembros .st_dev y .st_ino son los mismos.

Sin embargo, esto no funciona si está utilizando O_TRUNC - en el momento en que haya descubierto el engaño, ya es demasiado tarde -. Mallory ya le ha inducido a truncar una de sus archivos importantes

Creo que la manera tradicional para eliminar el agujero sin apoyo O_NOFOLLOW es:

  • Crear un directorio temporal con 700 modo. De error (o reintento) si mkdir() falla debido a directorio existente;
  • Crea tu nuevo archivo en el directorio temporal;
  • Uso rename() atómicamente para mover el archivo temporal al nombre de destino;
  • Eliminar el directorio temporal.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top