Команда rm -fr /some/directory
обязана выполнять рекурсивные работы. Использование команды намного проще, чем писать собственный код для выполнения той же работы - он воплощает достоинство лень и использует повторное использование кода в масштабе программы. (Вы не можете использовать системный вызов rmdir()
в каталоге, если он уже не пуст.). Так что это не совсем необоснованно.
Одна проблема - безопасность: может ли кто-нибудь разместить альтернативу команде rm
системы на вашем пути? В Unix есть /bin
и /usr/bin
сначала на вашем пути, или другие каталоги на первом месте?
Если вы решили, что использование /bin/rm
(или /usr/bin/rm
) достаточно безопасно, что может быть лучшим выбором, чем неукрашенная rm
, но в целом, это не так уж плохо.
Другая проблема - это другой аспект безопасности - можете ли вы удалить и создать каталог? Можете ли вы написать в /some
или нет? И следует ли сохранить текущего владельца, группу, разрешения /some/directory
, если вы удалите и заново создадите его? После этих операций каталог будет принадлежать эффективному UID процесса; если будет принадлежать группе с эффективным GID процесса (если в каталоге /some
нет липкого бита, или если вы не находитесь на macOS); и разрешения будут иметь значение 0777
, измененное текущей установкой umask()
.
Если эти проблемы не важны или являются обходными, то удаление и воссоздание правдоподобно.
Расширение на вышеуказанные комментариях:
Когда вы упомянули system()
вызов в своем комментарии, я понятия не имел, что вы говорили.
Функция system()
выполняет строку, переданную в качестве аргумента с помощью командного интерпретатора. Когда вы пишете код, вы должны думать о том, как это может пойти не так, когда кто-то вредоносный пытается заставить вас запустить его.Когда вы пишете "rm -fr /some/directory"
, вы полагаетесь на оболочку, находя обычную команду rm
и работая правильно. Однако, если ваш PATH
имеет значение, такое как $HOME/bin:/bin:/usr/bin
(так что команды в вашем собственном приватном каталоге bin
используются в предпочтении к тем, которые предоставляются системой), то если пользователь может установить свой собственный скрипт как $HOME/bin/rm
, они могут выполнять произвольный код с вашими привилегиями, которые могут позволить им оставить способ проникнуть в вашу систему, а затем сохранить все привилегии, которые у вас есть. Они могут даже очистить (большинство) доказательства того, что когда-то был сценарий $HOME/bin/rm
.
Один из способов избежать такой проблемы является запрос "/bin/rm -fr /some/directory"
(если rm
не /usr/bin
, а не в /bin
, конечно). Это, возможно, безопаснее. Раньше были атаки, доступные через переменную окружения IFS
; они стерилизованы современными оболочками, которые не используют никакого унаследованного значения для IFS
.
Обратите внимание, что одна из проблем будет интерпретировать, была ли выполнена команда rm
. Опция -fr
означает, что она будет сообщать об успехе практически при любых обстоятельствах, но если каталог не исчезнет, ваш вызов mkdir("/some/directory", 0777)
завершится с ошибкой.
Что касается безопасности /some/directory
, то мое понимание того, что вы пытаетесь сказать, заключается в том, что может быть выбран неправильный каталог. Я просто не могу представить, как это произойдет.
Предполагая, что ты есть разрешение на изменение /some
каталога (вам это нужно, чтобы быть в состоянии удалить /some/directory
), и что вы могли бы изменить все подкаталоги старой версии /some/directory
, то вы можете начать off /some/directory
принадлежит victim
, группе witless
и с разрешением 775, тогда как после команды и системного вызова (обратите внимание, что system()
является функцией, а не системным вызовом, mkdir()
- системный вызов), каталог может принадлежать пользователь victor
, группа mischief
и с разрешением 0777. Это может быть менее идеальным. Если вы не хотите нарушать такие параметры разрешения, вы, вероятно, не захотите использовать технику удаления и воссоздания - или, что не так просто, как показывает этот пример. Тогда вам придется немного усложнить удаление содержимого каталога без изменения этих атрибутов. Вы можете отсканировать каталог (opendir()
, readdir()
, closedir()
и вызвать rm
на каждое имя - или наборы имен - для тщательной очистки без удаления самой директории. Это сложная гибридность. Это более сложно, чем просто удаление и воссоздание, но гораздо менее затруднительно, чем иметь дело с полным рекурсивным удалением по нескольким уровням.
Как я уже говорил, вам нужно решить, важны эти вопросы или нет. Важно, чтобы вы знали, что проблемы существуют, и что у вас есть (осознанное) решение о том, следует ли решать проблемы и как справляться с этими проблемами.
Помните, что если ваша программа может быть запущена с помощью root (administra tor), гораздо важнее быть осторожным - но это все равно имеет значение, даже если только обычные смертные пользователи будут запускать программу.
Я все еще немного запутался в вашем объяснении безопасности, когда дело доходит до путей к файлу, но ваш ответ вполне достаточен для того, что я спросил, поэтому я буду отмечать его как официальный ответ. – Larrimus
@ Larrimus: спасибо за прием. Какая часть «безопасности для путей к файлам» запутывает?Является ли это безопасностью 'system()' call и 'rm' или безопасностью'/some/directory', которую вы собираетесь удалить и воссоздать? Или оба...? –
Я полагаю, это и то, и другое. Когда вы упомянули 'system()' звонок в своем комментарии, я понятия не имел, о чем вы говорите. Что касается безопасности '/ some/directory', то мое понимание того, что вы пытаетесь сказать, заключается в том, что может быть выбран неправильный каталог. Я просто не могу представить, как это произойдет. – Larrimus