Предупреждение tmpnam о том, что это опасно

Я получаю это предупреждение о том, что tmpnam опасен, но я бы предпочел использовать его, поскольку его можно использовать как есть как в Windows, так и в Linux. Мне было интересно, почему это считается опасным (я предполагаю, что это из-за возможности неправильного использования, а не из-за того, что он на самом деле не работает должным образом).


person Cenoc    schedule 21.07.2010    source источник
comment
Не могли бы вы добавить немного контекста? Кто утверждает, что это опасно?   -  person nmichaels    schedule 21.07.2010
comment
Является ли tmpname именем переменной, именем файла, именем исходного файла или чем-то еще? Не все из нас обладают экстрасенсорными способностями.   -  person sbi    schedule 21.07.2010
comment
@sbi: tmpnam - это функция стандартной библиотеки C.   -  person Mike Seymour    schedule 21.07.2010
comment
@Nathon На самом деле я говорил как о gcc, так и о msvc, мне просто было интересно, каково обоснование того, что это опасно. @sbi Думаю, мне следовало упомянуть, что это стандартная функция Lib.   -  person Cenoc    schedule 21.07.2010
comment
Если у хакера есть ваш код. Он может подключить отладчик и приостановить программу сразу после того, как ваш код вызовет tmpnam(), но до того, как вы откроете файл. Затем злоумышленник изменит файловую систему, чтобы иметь доступ к файлу, а затем продолжит работу вашего кода. Злоумышленник теперь имеет полный доступ к вашим данным tmp. В качестве альтернативы, если вы используете tmpfile(), вы не открываете эту уязвимость в коде, поскольку злоумышленнику намного сложнее остановить код, пока он находится в привилегированной части ОС.   -  person Martin York    schedule 21.07.2010
comment
@LokiAstari Большое спасибо за эту информацию. Я этого не знаю!   -  person Kyrol    schedule 16.08.2015


Ответы (5)


Из справочной страницы tmpnam:

Функция tmpnam() генерирует разные строки при каждом вызове, вплоть до TMP_MAX раз. Если он вызывается больше, чем TMP_MAX раз, поведение определяется реализацией.

Хотя tmpnam() генерирует имена, которые трудно угадать, тем не менее возможно, что между моментом, когда tmpnam() возвращает путь, и моментом, когда программа его открывает, другая программа может создать этот путь, используя open(2), или создайте его как символическую ссылку. Это может привести к дырам в безопасности. Чтобы избежать таких возможностей, используйте флаг open(2) O_EXCL, чтобы открыть путь. Или, что еще лучше, используйте mkstemp(3) или tmpfile(3).

Mktemp действительно создает файл, так что вы можете быть уверены, что он работает, тогда как tmpnam возвращает имя, возможно, уже существующее.

person Scharron    schedule 21.07.2010
comment
Использование mktemp предназначено только для Unix, для Windows вам нужны tmpnam_s и _wtmpnam_s. Таким образом, независимая от платформы версия не так проста. - person usr1234567; 23.04.2015

Если вы хотите использовать один и тот же символ на нескольких платформах, используйте макрос для определения TMPNAM. Если вы выберете более безопасные функции с одним и тем же интерфейсом, вы сможете использовать их на обоих. В любом случае, у вас где-то в коде есть условная компиляция, верно?

person nmichaels    schedule 21.07.2010

если вы говорите о предупреждении компилятора MSVC:

 These functions are deprecated because more secure versions are available;
 see tmpnam_s, _wtmpnam_s.

(http://msdn.microsoft.com/de-de/library/hs3e7355(VS.80).aspx)

в противном случае просто прочитайте, что на справочных страницах говорится о недостатках этой функции. в основном речь идет о втором процессе, создающем точно такое же имя файла, как и ваш процесс.

person akira    schedule 21.07.2010

Из справочной страницы tmpnam(3):

Хотя tmpnam() генерирует имена, которые трудно угадать, тем не менее возможно, что между моментом, когда tmpnam() возвращает путь, и моментом, когда программа его открывает, другая программа может создать этот путь, используя open(2). или создайте его как символическую ссылку. Это может привести к дырам в безопасности. Чтобы избежать такой возможности, используйте флаг open(2) O_EXCL, чтобы открыть путь. Или, что еще лучше, используйте mkstemp(3) или tmpfile(3).

person janneb    schedule 21.07.2010

Эта функция опасна, потому что вы несете ответственность за выделение буфера, который будет достаточно большим для обработки строки, которую tmpnam() собирается записать в этот буфер. Если вы выделите буфер, который слишком мал, tmpnam() не сможет об этом узнать и переполнит буфер (вызвав хаос). tmpnam_s() (защищенная версия MS) требует, чтобы вы передали длину буфера, чтобы tmpnam_s знать, когда остановиться.

person James Curran    schedule 21.07.2010
comment
Существует константа препроцессора L_tmpnam, которая указывает максимальную длину, которую будет записывать реализация (или в однопоточной программе вы можете использовать указатель NULL, и в этом случае она будет использовать статический буфер). Таким образом, этой проблемы легко избежать. Опасная часть связана с возможным состоянием гонки между созданием имени файла и последующим созданием самого файла. - person janneb; 21.07.2010
comment
Большинство дыр в безопасности легко избежать. (В вашем ответе приводится простой способ избежать проблемы, которую вы описываете). Проблема, которую я описываю, с большей вероятностью произойдет, если вы не будете следовать правилам. (это также проблема, исправленная tmpnam_s(), так что это явно та проблема, о которой они думали) - person James Curran; 21.07.2010