vulnerability sistemas seccion race operativos ejemplo critica condicion concurrencia carrera linux find timestamp

linux - sistemas - race condition vulnerability



Condiciones de carrera de marca de tiempo de creación de archivo de Linux (4)

¿Por qué no crear un directorio temporal en el que ejecutar las pruebas? Utilice un nombre basado en la marca de tiempo en el directorio para ayudar a realizar un seguimiento de los resultados que ocurrieron cuando, y simplemente elimine el directorio completo cuando haya terminado.

Estoy tratando de hacer lo que creo que es algo simple en Linux. Tengo un script bash que ejecuta varios programas de prueba, y quiero determinar qué archivos en el directorio actual fueron creados por los programas de prueba. Así que estoy haciendo algo como esto:

touch timestamp-file run the test find -newer timestamp-file -type f > list-of-files rm -f timestamp-file

Resulta que la granularidad de find -newer es pobre, por lo que lo que normalmente ocurre es que algunos archivos que fueron generados por el programa de prueba aparecen como OLDER que el archivo de marca de tiempo. Entonces intenté esto:

ls -tr1 | sed ''1,/timestamp-file/d''

para generar la misma lista. Esto generalmente funciona, pero no siempre. Todavía termino con la situación en la que los archivos generados por la prueba aparecen como más antiguos que el archivo de marca de tiempo.

¡Gracias!

PD. Puedo lograr esto de otra manera tomando dos instantáneas del directorio, una antes de que se ejecute el programa de prueba y luego una después, y las comparé. Cualquier archivo en la segunda lista que no esté en la primera debe haber sido creado por el programa de prueba (no me preocupan los trabajos en segundo plano ni otros usuarios que escriban en el directorio). Pero este método no es lo que quiero porque si un archivo de salida no se eliminó antes de ejecutar la prueba (se supone que debe ser, pero en algunos casos puede que no lo sea), este método dirá que no fue creado por el programa de prueba porque estaba en el directorio antes de ejecutar el programa de prueba.


En realidad, puede utilizar el tacto para forzar las marcas de tiempo de todos los archivos actuales en el directorio hasta ahora, como por ejemplo:

touch -t 200801010000.00 *

Si hace esto antes de ejecutar su prueba, debería haber una diferencia más que suficiente en el tiempo para " find -newer " para recogerla. Si la granularidad fue de dos minutos, puede establecer todos los archivos actuales hace diez minutos, el archivo de marca de tiempo hace 5 minutos y luego ejecutar la prueba.

Entonces tu script se convierte en:

touch -t (current time - 10 minutes) * touch -t (current time - 5 minutes) timestamp-file run the test find -newer timestamp-file -type f > list-of-files rm -f timestamp-file

Suponiendo que tiene una instalación decente de Perl, puede hacer lo siguiente para obtener hace 5 minutos (o use -600 por 10 minutos) en el formato correcto para " date -t ":

use Date::Manip; print UnixDate(DateCalc(ParseDateString("now"),"-300"),"%Y%m%d%H%M.%S") . "/n";

Si, por alguna razón, no tiene permitido cambiar las marcas de tiempo, use:

sleep 300 touch timestamp-file sleep 300 run the test find -newer timestamp-file -type f > list-of-files rm -f timestamp-file

que tiene el mismo efecto, pero le da diez minutos para tomar un café (o su veneno de elección si no es un bebedor de café).


Si considera cómo se implementa find(1) , quedará claro por qué esto a veces puede no funcionar como espera. Aquí hay una pista:

$ touch timestamp ; touch newer ; find . -newer timestamp $ rm timestamp newer $ touch timestamp ; sleep 1 ; touch newer ; find . -newer timestamp . ./newer $

find(1) obtiene los valores de mtime / ctime / atime del archivo utilizando el stat(2) llamada del sistema stat(2) . Estos son los elementos de struct stat de <sys/stat.h> (Linux):

time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change */

En Linux (y en general los units) time_t es un número entero que representa "segundos desde el comienzo de 1970". Por lo tanto, la granualidad más fina que puede comprender el -newer es solo un segundo.


Tome los nombres de archivo de todos los archivos antes de la ejecución, pero incluya sus marcas de tiempo:

find -printf ''%p %T@/n'' | sort > file1

Si no tiene disponible esa opción de búsqueda, puede usar la estadística para ese trabajo también:

find -print0 | xargs -0 stat -c "%n %Y" | sort > file1

Y después de ejecutar para file2 . Entonces usa

comm -1 -3 file1 file2

Y le mostrará las líneas exclusivas de file2 , que deben ser archivos nuevos si no me equivoco. Si existieron antes, su tiempo de modificación habrá cambiado, lo que se cuida con el %T@ thingy (imprimiendo el número de segundos desde 1970):

[js@HOST2 cpp]$ find -printf ''%p %T@/n'' | sort > file1 [js@HOST2 cpp]$ echo foo>bar [js@HOST2 cpp]$ echo foo>baz [js@HOST2 cpp]$ find -printf ''%p %T@/n'' | sort > file2 [js@HOST2 cpp]$ comm -1 -3 file1 file2 . 1230947309.0000000000 ./bar 1230947308.0000000000 ./baz 1230947309.0000000000 ./file2 1230947315.0000000000 [js@HOST2 cpp]$ find -printf ''%p %T@/n'' | sort > file1 [js@HOST2 cpp]$ echo lol>bar [js@HOST2 cpp]$ find -printf ''%p %T@/n'' | sort > file2 [js@HOST2 cpp]$ comm -1 -3 file1 file2 ./bar 1230947359.0000000000 ./file2 1230947362.0000000000 [js@HOST2 cpp]$`