- Quiero anexar datos a un archivo en/tmp.
- Si el archivo no existe quiero crearlo
- No me importa si alguien más posee el archivo. La información no es secreta
- No quiero que alguien pueda competir-condicionar esto para escribir en otro lado, o en otro archivo.
¿Cuál es la mejor manera de hacerlo?¿Cómo debo protegerme contra los ataques de enlaces duros?
Aquí está mi pensamiento:
fd = open("/tmp/some-benchmark-data.txt", O_APPEND | O_CREAT | O_NOFOLLOW | O_WRONLY, 0644);
fstat(fd, &st);
if (st.st_nlink != 1) {
HARD LINK ATTACK!
}
problema con esto: Alguien puede vincular el archivo a un archivo de corta duración de la mina, de manera que /tmp/some-benchmark-data.txt es lo mismo que/tmp/tmpfileXXXXXX que otro script mío está usando (y se abrió correctamente usando O_EXCL y todo eso). Mis datos de referencia se anexan a este archivo/tmp/tmpfileXXXXXX, mientras todavía se usa.
Si mi otra secuencia de comandos pasó a abrir su archivo temporal, entonces elimínelo, luego úselo; entonces el contenido de ese archivo se corrompería con mis datos de referencia. Esta otra secuencia de comandos tendría que eliminar su archivo entre open() y fstat() del código anterior.
Así, en otras palabras:
This script Dr.Evil My other script or program
open(fn2, O_EXCL | O_CREAT | O_RDWR)
link(fn1,fn2)
open(fn1, ...)
unlink(fn2)
fstat(..)=>link is 1
write(...)
close(...)
write(...)
seek(0, ...)
read(...) => (maybe) WRONG DATA!
Y por lo tanto, la solución anterior no funciona. Posiblemente haya otros ataques.
¿Cuál es el camino correcto? Además de no usar un directorio de escritura mundial.
Editar: Con el fin de proteger contra el resultado de que el usuario del mal crea el archivo con su/su propiedad y los permisos, o simplemente permisos incorrectos (por dura que une su archivo y luego retirar el original, o un enlace duro una archivo efímero tuyo) Puedo verificar los bits de propiedad y permiso después de la verificación nlink.
No habría problemas de seguridad, pero también evitaría sorpresas. El peor caso es que obtengo algunos de mis propios datos (de otro archivo) al principio del archivo copiados de algún otro archivo mío.
Editar 2: creo que es casi imposible proteger contra alguien difíciles de vincular el nombre de un archivo que está abierto, borrado y luego se usa. Ejemplos de esto son los empaquetadores EXE, que a veces incluso ejecutan el archivo eliminado a través de/proc/pid/fd-num. Compita con esto provocaría un error en la ejecución del programa empaquetado. Probablemente, lsof podría encontrar si alguien más tiene abierto el inodo, pero parece ser más problemático de lo que vale.
Es solo un ataque antes de que se cree el archivo. Si soy un usuario estándar, puedo crear un enlace a cualquier archivo (incluso si no puedo escribir en ese archivo) en cualquier directorio en el que pueda escribir. Eso significa que puedo crear un archivo llamado '/ tmp/foo' que es un enlace duro de '/ etc/passwd'. Ahora cuando su programa escribe en '/ tmp/foo', realmente está escribiendo en'/etc/passwd'. Él quiere evitar esto asegurándose de que el suyo sea el primer enlace al inodo que creó. – Gabe
@gabe: a la derecha. Por eso reviso st_nlink. Puede crear un nuevo enlace a los archivos de otras personas, pero no puede eliminarlos (disminuya el número de enlaces). – Thomas
Buen punto, Thomas. Si mi comentario se ve raro es porque estaba respondiendo a otro comentario que se ha eliminado desde entonces. – Gabe