Ну чо, расчехляем strace и погнали ковыряться в кишках. Сегодня будем проводить эксперимент над утилитой mktemp, которая входит в состав пакета coreutils.
mktemp создаёт временный файл (по умолчанию) или директорию и возвращает имя созданного файла. Я ее использую для хранения промежуточных данных, когда нужно создать какую-то рандомную папку или файл и положить туда какой-нибудь мусор.
Задача - понять что произойдет если временный файл или папка уже существует. Будет ли mktemp создавать папку или файл с другим именем и сколько раз она это будет делать.
Для начала надо узнать с помощью какого системного вызова создается файл, запускаем:
strace -Yyf mktemp
Y = выводим команды с привязкой к PIDs y = выводим пути привязанные к дескрипторам файла f = мониторим форки процессов
Можно и без ключей запускать, я просто так привык. После запуска получаем длинную портянку. Мне интересна лишь концовка, а именно:
openat(AT_FDCWD</root>, "/tmp/tmp.V0051oIfmC", O_RDWR|O_CREAT|O_EXCL, 0600) = 3</tmp/tmp.V0051oIfmC>
Ага, отловили openat. Идем сюда читать список ошибок, которые возвращает openat.
Меня интересует:
EEXIST pathname already exists and O_CREAT and O_EXCL were used.
Если были заданы флаги O_CREAT и O_EXCL и файл существует, то возвращается ошибка EEXIST.
Дополнительно нужно выяснить с какого по счету системного вызова будем перехватывать и возвращать ошибку. Суть в том, что при запуске mktemp есть несколько вызовов openat. Их делает динамический загрузчик. Если их перехватить, то программа просто не запустится. Также нужно избавиться от нескольких вызовов openat которые совершает система языковых переводов. Для этого нужно установить значения переменной LC_ALL в POSIX.
Выводим все openat которые делает утилита:
LC_ALL=POSIX strace -Yyfe openat mktemp
У меня получилось 4 строки:
openat(AT_FDCWD</root>, "/etc/ld.so.cache")
openat(AT_FDCWD</root>, "/lib/x86_64-linux)
openat(AT_FDCWD</root>, "/dev/urandom")\
openat(AT_FDCWD</root>, "/tmp/tmp.eyg53MQ1c2")
Вызов создающий временный файл у меня по счету 4-й. Выпускаем кракена:
LC_ALL=POSIX strace -YCyfe inject=openat:error=EEXIST:when=4+ mktemp
Вот это поворот! Ждем какое-то время и наблюдаем, как на экране бежит какая-то дичь.
Вот это поворот
Шутки за 300.
Короче дождались пока оно там просрется и выведет табличку с результатами. Смотрим в колонку errors для системного вызова в openat и видим число 238328.
Вот собственно столько раз утилита mktemp будет пытаться создать файл с новым именем, после того как системный вызов будет возвращать ошибку, означающую что файл существует. Получается количество попыток 62**3 = 238328.
На этом собственно все, немного сложновато, но очень интересно. Потыкай сам и всё станет еще более прозрачным. Давай пять, увидимся!








Комментарии
Виджет комментариев загружается с серверов Telegram и может использовать cookies. Разрешите внешние сервисы, чтобы открыть обсуждение.