Как стать автором
Обновить

Комментарии 35

Хмм, идея интересная, были мысли сделать библиотеку на подобии такой.
Посмотрите мой топик про .NET компилятор. Так в принципе можно и не только эти языки сделать.
Также видел проект, рисующий графики функций, который компилит их «в уме».
Реализация подобного рода скриптования может быть опасной, поскольку из скриптов афайк может быть доступ к внутренним методам и данным приложения.
Об этом как раз сказано в заключении. Там же есть и решение — правильно настраивать уровни видимости — то, что к чему нельзя подпускать делаем internal. Правда защита такого плана обходится при помощи рефлексии. Сейчас как раз ищу способы защиты от такого.
Никак в управляемом коде. Тем более, не забывайте, что в код можно написать
Exec(«format»,«C:/ /F /R»); или что то в этом роде.
Хотя от такого можно защитить дописывая какой нибудь Namespace к функциям, но тогда придется копаться с переопределениями.
Кстати, можно еще права у кода поотбирать)
Скрипт можно запустить из отдельного домена с минимальным набором разрешений.
Можно. Но это .NET 4.0. Что накладывает некоторые ограничения.
Прошу прощения, AppDomain есть в любой версии .NET. То ли MSDN проглючило, то ли меня…
Скрипт нужно запускать в отдельном домене. Не только разрешения, но и стабильность выполнения.
Стабильность в каком смысле? Это ведь управляемый код.
Управляемый код, тем не менее, вполне может сожрать память, впасть в бесконечный цикл и предоставить прочие прелести программистских ошибок.

Отдельный апп-домен вы в любой момент можете выгрузить, даже если живущий в нем тред завис.
Не в любой момент, насколько я знаю. Если тред завис на выполнении неуправляемого кода или исполнении finally блока, домен выгрузить не удастся.

Код в другом AppDomain тоже может сожрать память. Хотя, если это контролировать, можно попробовать успеть его выгрузить.
«Если тред завис на выполнении неуправляемого кода или исполнении finally блока, домен выгрузить не удастся.»
А если завис ваш собственный тред, вы не можете его выгрузить никогда. И это большая разница.

Плюс Рихтер пишет (CLR via C#, 3rd Edition, глава Writing Robust Host Applications), что в четвертом фреймворке можно сделать escalation policy, который приведет к тому, что если домен нельзя положить «по правилам», его убьют без правил. И это еще один аргумент за отдельные домены.

«Код в другом AppDomain тоже может сожрать память.»
Тем не менее, контроля за ним у вас намного больше.
Согласен.
По поводу безопасности — могу дать несколько советов которые возможно вам помогут

1. Во первых класс «плагина» должен реализовывать ранее продуманный интерфейс. И этот класс должен предусматривать некий «менеджер» который будет отвечать за доступ к важным данным и функциям основного приложения.

2. Доступ к файлику с паролями стоит ограничить. Как минимум приложение может его просто блокировать в начале работы и разблокировать после выгрузки «плагинов» (вариант грубый но простой)

3. Если есть критические данные в базе — то не давать доступа к connection string а опять же работать через менеджер которые дает возможность реализовать безопасный доступ к данным и контролировать операции из основного приложения.

4. Ну и еще есть вариант подписи плагинов — то есть прежде чем плагин выпустить в свободное плавание — его исходный код изучает специалист и проверяет на потенциально опасный код. Такая система например с приложения в App Store от Apple. (Хотя опять же зависит от конкретной ситуации — подходит такой вариант, или нет)
1. Во первых класс «плагина» должен реализовывать ранее продуманный интерфейс. И этот класс должен предусматривать некий «менеджер» который будет отвечать за доступ к важным данным и функциям основного приложения.


2. Доступ к файлику с паролями стоит ограничить. Как минимум приложение может его просто блокировать в начале работы и разблокировать после выгрузки «плагинов» (вариант грубый но простой)


Предыдущий комент почему-то самопроизвольно отправился…

1. Во первых класс «плагина» должен реализовывать ранее продуманный интерфейс. И этот класс должен предусматривать некий «менеджер» который будет отвечать за доступ к важным данным и функциям основного приложения.

Как раз такого подхода я и хочу добиться. Здесь проблема в том, что надо запретить в коде сточки вида System.IO.FileStream file = new System.IO.FileStream(«путь_до_важного_файла_с_паролями»);

2. Доступ к файлику с паролями стоит ограничить. Как минимум приложение может его просто блокировать в начале работы и разблокировать после выгрузки «плагинов» (вариант грубый но простой)

В статье я имел в виду файлы паролей не только самого приложения. Например — файл %APPDATA%/Opera/Opera/wand.dat. Не очень хорошо будет если такой файл попадёт не в те руки.

4. Ну и еще есть вариант подписи плагинов — то есть прежде чем плагин выпустить в свободное плавание — его исходный код изучает специалист и проверяет на потенциально опасный код. Такая система например с приложения в App Store от Apple. (Хотя опять же зависит от конкретной ситуации — подходит такой вариант, или нет)

К сожалению в моём случае не подходит.
«Как раз такого подхода я и хочу добиться. Здесь проблема в том, что надо запретить в коде сточки вида System.IO.FileStream file = new System.IO.FileStream(«путь_до_важного_файла_с_паролями»);»
Ну так отнять у выполняемого кода FilePermission, и все.
Внезапно в топик врывается кодогенерация через System.Linq.Expressions и DLR, который для реализации скриптов и придумали (см. IronPython, IronRuby и прочее).

Сразу, чтобы отмести обвинения в .net 4-only, DLR изначально был реализован в виде отдельной библиотеки — dlr.codeplex.com/
В Mono работает.

А System.CodeDom.Compiler изначально был нужен для кодогенерации именно в компиляторах.

Давайте все-таки использовать инструменты по назначению.
В целом верно. Сам зашел в этот пост чтобы проверить, предложено ли это очевидное (для меня) решение.
А что вы можете добавить по ограничению прав такого скрипта?
В документации предлагается запускать скрипты из отдельного аппдомена, как было уже предложено выше.
Кроме того, почти все классы из System.CodeDom.Compiler недоступны в Silverlight, например.
Спасибо за ещё одно направление в котором нужно подумать. До этого так нормально и не знал для чего предназначен DLR. Сейчас посмотрел его поверхностно — позже посмотрю поподробнее. Однако мне кажется что любой подход имеет право на существование — в качестве плюсов к моему методу могу сказать что у меня уже сразу используется готовый язык. В случае DLR же, если я правильно понял, надо ещё описать синтаксис языка, и что во что компилируется.
Да, во времена, когда еще существовал Managed DirectX, Майкрософт предлагал подход аналогичный вашему для скриптования игрушек.
У моно есть же специальное безопасное решение для создания песочниц с поддержкой CoreCLR и прочего. Они на его основе безопасность в мунлайте делали.
Хм. Интересно. А где можно поподробнее посмотреть как это можно использовать у себя? А то на сайте mono нашёл только два страничке посвященные песочнице Mono.
Если я правильно понял — это решение чисто для Mono. Там все классы помечаются как безопасные и небезопасные…
> я мог править код, на лету перекомпилируя его прямо в своём приложении

Any sufficiently complicated program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
посмотрите на Boo — его вроде как немного забросили, но он позволяет делать и более сложные штуки без такого шаманства.
Немного не в тему, но какие библиотеки Вы использовали для работы с Lua? Я пару лет назад использовал LuaInterface, было очень удобно. Никакой кучи биндингов. Правда я не уверен на счёт его работы с моно.
Честно говоря уже не помню что я рассматривал. Но вроде был и LuaInterface который меня тоже чем-то не устроил.
Кстати, если не ошибаюсь, сгенерированный раз код так и остается висеть в памяти, поскольку отдельную сборку в .NET выгрузить нельзя. Только AppDomain целиком. Так что домен все равно желательно создавать. Но тогда доступ к функциям сборки будет несколько затруднен?
Я честно говоря думал что сборка автоматом выгрузится сборщиком мусора. А по поводу затруднения доступа — есть такое. Если я правильно понял — то из домена можно либо запустить на выполнение exe, либо создать экземпляр какого либо объекта и уже с ним работать. Если я правильно понял — то просто вызвать статический метод — нельзя (если он не является точкой входа)
«Я честно говоря думал что сборка автоматом выгрузится сборщиком мусора.»
Зря вы так думали. .net framework не умеет выгружать отдельные сборки из домена, только домен целиком.

«Если я правильно понял — то из домена можно либо запустить на выполнение exe, либо создать экземпляр какого либо объекта и уже с ним работать. Если я правильно понял — то просто вызвать статический метод — нельзя (если он не является точкой входа) „
Это-то мелочи. В реальности вы вообще (к счастью) не можете протащить через границу домена ни один объект, не попадающий под определенные ограничения.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории