Есть команда оболочки unix ( udevadm info -q path -n /dev/ttyUSB2
), которую я хочу вызвать из программы на Си. Возможно, с неделей борьбы, я мог бы реализовать ее сам, но я не хочу этого делать.
Является ли для меня общепринятой практикой просто звонить popen("my_command", "r");
или это вызовет неприемлемые проблемы с безопасностью и перенаправит проблемы совместимости? Мне кажется неправильным делать что-то подобное, но я не могу понять, почему это будет плохо.
udevadm
исполняемый файл в тот же каталог, что и ваша программа, и использовать его для повышения привилегий? Я не знаю много о безопасности Unix, но будет ли запускаться ваша программаsetuid root
?PATH
, то нет - его нужно запускать./udevadm
. Windows IIRC будет запускать исполняемые файлы в одном каталоге.Ответы:
Это не особенно плохо, но есть некоторые оговорки.
LANG
и т. Д.?;rm -rf /
(например) (обратите внимание, что некоторые API-интерфейсы позволят вам указать аргументы более безопасно, чем просто предоставить их в командной строке)Я в целом рад выполнению двоичных файлов, когда я нахожусь в известной среде, которую я могу предсказать, когда двоичный вывод легко анализировать (если требуется - вам может просто понадобиться код выхода), и мне не нужно это делать тоже довольно часто.
Как вы заметили, другая проблема заключается в том, сколько работы нужно, чтобы воспроизвести то, что делает двоичный файл? Использует ли он библиотеку, которую вы также можете использовать?
источник
Forking a binary results in a lot more load and requires more resources than executing library calls (generally speaking).
Если бы это было на Windows, я бы согласился. Тем не менее, OP определяет Unix, где разветвление является достаточно низкой стоимостью, поэтому трудно сказать, хуже ли динамическая загрузка библиотеки, чем разветвление.exec
чем отfork
. Загрузка разделов, ссылки в общих объектах, запуск кода инициализации для каждого. А затем необходимо преобразовать все данные в текст для анализа на другой стороне, как для входных, так и для выходных данных.udevadm info -q path -n /dev/ttyUSB2
в любом случае не будет работать на Windows, так что все разветвленные дискуссии немного теоретичны.Нужно быть очень осторожным, чтобы защититься от уязвимостей инъекций, как только вы представили потенциальный вектор Сейчас это находится в центре вашего внимания, но позже вам может понадобиться возможность выбрать
ttyUSB0-3
, затем этот список будет использоваться в других местах, поэтому он будет учтен в соответствии с принципом единой ответственности, тогда у клиента будет требование поставить произвольное устройство в списке, и разработчик, делающий это изменение, не будет знать, что список в конечном итоге будет использоваться небезопасным способом.Другими словами, код, как будто самый небрежный из известных вам разработчиков делает небезопасные изменения в, казалось бы, не связанной части кода.
Во-вторых, выходные данные инструментов CLI обычно не считаются стабильными интерфейсами, если документация специально не помечает их как таковые. Вы можете рассчитывать на них для сценария, который вы запускаете, который вы можете устранить самостоятельно, но не для чего-то, что вы развертываете для клиента.
В-третьих, если вам нужен простой способ извлечь ценность из вашего программного обеспечения, скорее всего, кто-то еще этого захочет. Ищите библиотеку, которая уже делает то, что вы хотите.
libudev
был уже установлен в моей системе:В этой библиотеке есть другие полезные функции. Полагаю, если вам это понадобится, некоторые из связанных функций также могут пригодиться.
источник
ttyUSB2
и используетеsprintf(buf, "udevadm info -q path -n /dev/%s", argv[1])
. Теперь это выглядит довольно безопасно, но что, еслиargv[1]
есть"nul || echo OOPS"
?В вашем конкретном случае, где вы хотите вызвать
udevadm
, я подозреваю, что вы можетеudev
использовать библиотеку и сделать соответствующие вызовы функций в качестве альтернативы?Например, вы можете посмотреть, что делает udevadm при вызове в режиме «информация»: https://github.com/gentoo/eudev/blob/master/src/udev/udevadm-info.c и сделать эквивалентные вызовы. что касается тех, кто делает udevadm.
Это позволило бы избежать многих недостатков, перечисленных в отличном ответе Брайана Агнью - например, не полагаться на двоичный файл, существующий на определенном пути, избегая затрат на разветвление и т. Д.
источник
Ваш вопрос, казалось, требовал лесного ответа, а ответы здесь кажутся древовидными, поэтому я решил дать вам лесной ответ.
Это очень редко, как пишутся программы на Си. Это всегда, как пишутся сценарии оболочки, а иногда и как программы на Python, Perl или Ruby.
Люди обычно пишут на C для простого использования системных библиотек и прямого низкоуровневого доступа к системным вызовам ОС, а также для скорости. А C - сложный язык для написания, поэтому, если людям не нужны эти вещи, они не используют C. Кроме того, ожидается, что программы на C обычно зависят только от общих библиотек и файлов конфигурации.
Выделение подпроцесса не особенно быстрое и не требует детального и контролируемого доступа к низкоуровневым системным средствам, а также представляет собой неожиданную зависимость от внешнего исполняемого файла, поэтому его редко можно увидеть в C программах.
Есть некоторые дополнительные проблемы. Вопросы безопасности и мобильности, о которых упоминают люди, полностью действительны. Конечно, они одинаково действительны для сценариев оболочки, но люди ожидают такого рода проблем в сценариях оболочки. Но от программ на C обычно не ожидается такой класс безопасности, что делает его более опасным.
Но, на мой взгляд, самые большие проблемы связаны с тем, как
popen
будет взаимодействовать с остальной частью вашей программы.popen
должен создать дочерний процесс, прочитать его выходные данные и получить статус выхода. Между тем, stderr этого процесса будет подключен к тому же stderr, что и ваша программа, что может привести к сбивающему с толку выводу, а его stdin будет таким же, как ваша программа, что может вызвать другие интересные проблемы. Вы можете решить эту проблему, включив</dev/null 2>/dev/null
вpopen
нее передаваемую строку, поскольку она интерпретируется оболочкой.И
popen
создает дочерний процесс. Если вы что-то делаете с процессами обработки сигналов или разветвления самостоятельно, вы можете получить странныеSIGCHLD
сигналы. Ваши призывыwait
могут странным образом взаимодействоватьpopen
и, возможно, создавать странные условия гонки.Проблемы безопасности и переносимости, конечно, есть. Как и для сценариев оболочки или всего, что запускает другие исполняемые файлы в системе. И вы должны быть осторожны, чтобы люди, использующие вашу программу, не могли получить метасимволы оболочки в строку, в которую вы передаете,
popen
потому что эта строка передается непосредственно сsh
помощьюsh -c <string from popen as a single argument>
.Но я не думаю, что по этой причине странно видеть использование программы на Си
popen
. Причина в том, что это странно, потому что C, как правило, язык низкого уровня, аpopen
не низкого уровня. И потому что использованиеpopen
накладывает конструктивные ограничения на вашу программу, потому что она будет странным образом взаимодействовать со стандартным вводом и выводом вашей программы и затруднит управление вашим собственным процессом или обработкой сигналов. А поскольку программы на Си, как правило, не должны зависеть от внешних исполняемых файлов.источник
Ваша программа может быть взломана и т. Д. Одним из способов защитить себя от этого вида деятельности является создание копии вашего текущего окружения машины и запуск вашей программы с использованием системы, называемой chroot.
С точки зрения вашей программы, она выполняется в обычном окружении, с точки зрения безопасности, если кто-то нарушает вашу программу, он имеет доступ только к тем элементам, которые вы указали при создании копии.
Такая настройка называется chroot jail, более подробно см. Chroot jail .
Обычно он используется для настройки общедоступных серверов и т. Д.
источник