vdevid lock что это такое

DLP-система DeviceLock 8.2 — дырявый штакетник на страже вашей безопасности

В октябре 2017 года довелось побывать на рекламном семинаре DLP-системы DeviceLock, где помимо основного функционала защиты от утечек типа закрытия USB-портов, контекстного анализа почты и буфера обмена рекламировалась защита от администратора. Модель простая и красивая — в маленькую фирму приходит установщик, ставит комплекс программ, паролит БИОС, создает администраторскую учетку DeviceLock, а местному админу оставляет только права на управление собственно Виндой и остальным софтом. Даже в случае умысла этот админ ничего украсть не сможет. Но это все теория…

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

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

На все вопросы о защите наверняка имеющихся в составе продукта драйверов представитель фирмы-разработчика Смарт Лайн уверенно заявлял, что «все на том же уровне».

Через день решил продолжить изыскания, скачал пробную версию. Сразу же удивил размерчик дистрибутива почти в 2 Гб! Привык, что системное ПО, к которому принято относить средства защиты информации (СЗИ), обычно имеет гораздо более компактный размер.

После установки удивился 2й раз — размер вышеупомянутого ехе-шника тоже весьма немаленький — 13Мб. Сразу подумалось, что при таком объеме есть за что зацепиться. Попробовал подменить модуль с помощью отложенной записи — закрыто. Покопался в каталогах программы, а там одних драйверов аж 11 штук! Потыкал в разрешения — не закрыты для изменения! Ну ладно, всем запрет, перегружаемся!

Эффект просто феерический — все функции отключились, служба не стартовала. Какая там самозащита, бери и копируй что хочешь хоть на флешки, хоть по сети. Вылез первый серьезный недостаток системы — слишком сильная взаимосвязь компонентов. Да, служба с драйверами должна общаться, но падать то зачем, если никто не отвечает? В итоге один метод обхода защиты есть.

Выяснив, что чудо-служба такая нежная и чувствительная, решил проверить ее зависимости от сторонних библиотек. Тут еще проще, список большой, просто наугад стираем библиотеку WinSock_II и наблюдаем аналогичную картину — служба не стартовала, система открыта.

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

Причем на рынке полно примеров грамотной реализации защиты от отключения, например отечественные антивирусные средства, где самозащиту просто так не объедешь. Насколько мне известно, они не поленились пройти сертификацию ФСТЭК.

Проведя несколько бесед с сотрудниками Смарт Лайн, несколько подобных мест, о которых они даже не слышали, было найдено. Один из примеров — механизм АррInitDll.

Пусть он не самый глубокий, зато во многих случаях позволяет обойтись без влезания в ядро ОС и не влиять на ее стабильность. Драйвера nVidia во всю используют данный механизм для подстройки видеодаптера под конкретную игру.

Вызывает вопросы полное отсутствие комплексного подхода к построению автоматизированой системы на базе DL 8.2. Предлагается живописать заказчику преимущества продукта, проверить вычислительную мощность имеющихся ПК и серверов (контекстные анализаторы весьма ресурсоемки и модные сейчас офисные моноблоки и неттопы на базе Атом в данном случае не подходят) и просто накатить сверху изделие. При этом такие термины, как «разграничение доступа», «замкнутая программная среда», даже не прозвучали на семинаре. Про шифрование было сказано, что помимо сложности оно вызовет вопросы регуляторов, хотя реально никаких проблем с этим нет. Вопросы про сертификацию даже во ФСТЭК отметаются ввиду их якобы сложности и затянутости. Как специалист по ИБ, неоднократно принимавший участие в подобных процедурах, могу сказать, что в процессе их проведения выявляется множество уязвимостей, подобных описанным в данном материале, т.к. специалисты сертифицирующих лабораторий имеют серьезную профильную подготовку.

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

Реально защитить она может разве что реально большие данные от непривилегированного пользователя, т.к. администратор вполне способен полностью деактивировать защиту, а для необъемных секретов и младший менеджер по клинингу догадается незаметно сфотографировать экран, а то и запомнить адресок или номер кредитки, заглянув в экран через плечо коллеги.
Причем все это справедливо только в случае невозможности физического доступа сотрудников к внутренностям ПК или хотя бы к БИОС для активации загрузки с внешних носителей. Тогда может не помочь даже БитЛокер, который вряд ли применяется в фирмах, которые только задумались о защите информации.

Вывод, как это ни банально звучит, в комплексном подходе к ИБ, включая не только программно/аппаратные решения, но и организационно-технические меры для исключения фото/видеосъемки и недопуска на объект посторонних «мальчиков с феноменальной памятью». Полагаться на чудо-продукт DL 8.2, рекламируемый как одношаговое решение большинства проблем с безопасностью предприятия нельзя ни в коем случае.

Источник

.NET: Инструменты для работы с многопоточностью и асинхронностью. Часть 2

Публикую на Хабр оригинал статьи, перевод которой размещен в блоге Codingsight.

Я продолжаю создавать текстовую версию своего выступления на митапе по многопоточности. С первой частью можно ознакомиться здесь или здесь, там речь больше шла о базовом наборе инструментов, чтобы запустить поток или Task, способах просмотреть их состояние и некоторых сладких мелочах, вроде PLinq. В этой статье хочу больше остановится на проблемах, которые могут возникнуть в многопоточной среде и некоторых способах их решения.

Содержание

О разделяемых ресурсах

Невозможно написать программу, которая бы работала в несколько потоком, но при этом не имела бы ни одного общего ресурса: т.к. даже если это получится на вашем уровне абстракции, то спустившись на один или несколько уровней ниже окажется, что общий ресурс все-таки есть. Приведу несколько примеров:

Опасаясь возможных проблем, вы заставили потоки работать с разными файлами. По файлу на поток. Вам кажется, что в программе нет ни одного общего ресурса.

Спустившись на несколько уровней ниже, мы понимаем, что жесткий диск один, а проблемы обеспечения доступа к нему придется решать его драйверу или операционной системе.

Прочитав пример#1, вы решили разместить файлы на двух разных удаленных машинах с двумя физически разными железяками и операционными системами. Держим 2 разных соединения по FTP или NFS.

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

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

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

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

Возможные проблемы при работе в многопоточной среде

Ошибки в работе ПО можно разбить на несколько групп:

Deadlock

Deadlock — взаимная блокировка. Существует много разных вариаций. Наиболее частой можно считать следующую:

vdevid lock что это такое. Смотреть фото vdevid lock что это такое. Смотреть картинку vdevid lock что это такое. Картинка про vdevid lock что это такое. Фото vdevid lock что это такое

Пока Thread#1 что-то делал, Thread#2 заблокировал ресурс B, немного позднее Thread#1 заблокировал ресурс A и пытается заблокировать ресурс B, к сожалению это никогда не произойдет, т.к. Thread#2 освободит ресурс B лишь после того как заблокирует ресурс А.

Race-Condition

Race-Condition — состояние гонки. Ситуация, в которой поведение и результат вычислений, выполняемых программой, зависит от работы планировщика потоков среды выполнения.
Неприятность этой ситуации заключается как раз в том, что ваша программа может не работать лишь один раз из ста или даже из миллиона.

Усугубляются ситуация тем, что проблемы могут идти вместе, например: при определенном поведении планировщика потоков возникает взаимная блокировка.

Кроме этих двух проблем приводящих к явным ошибкам в работе программы есть еще те, что, возможно, и не приведут к некорректному результату вычислений, но для его получения будет потрачено больше времени или вычислительной мощности. Двумя такими проблемами являются: Busy Wait и Thread Starvation.

Busy-Wait

Busy-Wait — проблема, при которой программа потребляет ресурсы процессора не для вычислений, а для ожидания.

Часто такая проблема в коде выглядит примерно так:

Это пример крайне плохого кода, т.к. Такой код полностью занимает одно ядро вашего процессора при этом не делая ровным счетом ничего полезного. Он может быть оправдан тогда и только тогда, когда критически важно обработать изменение какого-то значения в другом потоке. И говоря быстро я говорю, о случае, когда вы не можете ждать даже нескольких наносекунд. В остальных случаях, то есть во всех, что может породить здоровый мозг, разумнее использовать разновидности ResetEvent и их Slim версии. О них ниже.

Возможно, кто-то из читателей предложит решить проблему с полной загрузкой одного ядра бесполезным ожиданием добавлением в цикл конструкции вроде Thread.Sleep(1). Это действительно решит проблему, но создаст другую: время реагирование на изменение будет в среднем равен половине миллисекунды, что может и не много, но катастрофически больше, чем могло бы быть используй вы примитивы синхронизации семейства ResetEvent.

Thread Starvation

Thread-Starvation — проблема, при которой в программе слишком много одновременно работающих потоков. При чем речь именно о тех потоках, что заняты расчетами, а не просто ожиданием ответа от какого-либо IO. При этой проблеме теряется весь возможный выигрыш в производительности от использования потоков, т.к. Процессор тратит очень много времени на переключение контекстов.
Такие проблемы удобно искать с помощью различных профилировщиков, ниже пример скриншота из профилировщика dotTrace запущенного в режиме Timeline.

vdevid lock что это такое. Смотреть фото vdevid lock что это такое. Смотреть картинку vdevid lock что это такое. Картинка про vdevid lock что это такое. Фото vdevid lock что это такое
(Картинка кликабельна)

В программе что не страдает от потокового голода, розового цвета на графиках, отражающих потоки не будет. Кроме этого, в категории Subsystems видно, что программа 30.6% ждала CPU.

Когда такая проблема диагностирована, решается она довольно просто: вы запустили слишком много потоков в один момент времени, запустите меньше или не все сразу.

Средства синхронизации

Interlocked

Чтобы осознать весь ужас неатомарных операций, попробуйте написать программу, что запускает 10 потоков, каждый из которых делает миллион инкрементов одной и той же переменной, а по окончанию их работы выведите значение этой переменной — к сожалению оно будет сильно отличаться от 10 миллионов, более того при каждом запуске программы оно будет разным. Происходит это потому, что даже такая простая операция как инкремент не является атомарной, а включает в себя извлечение значения из памяти, расчет нового и запись обратно. Таким образом два потока могут одновременно сделать каждую из этих операций, в этом случае инкремент будет потерян.

Класс Interlocked предоставляет методы Increment/Decrement, нетрудно догадаться, что они делают. Их удобно использовать, если вы обрабатываете данные в несколько потоков и что-то считаете. Такой код будет работать значительно быстрее классического lock. Если для ситуации описанной в прошлом абзаце использовать Interlocked, то программа в любой ситуации будет стабильно выдавать значение 10 миллионов.

Метод CompareExchange выполняет, на первый взгляд довольно неочевидную функцию, но все ее наличие позволяет реализовывать множество интересных алгоритмов, в первую очередь семейства lock-free.

Метод принимает три значения: первое передается по ссылке и это то значение, которое будет изменено на второе, если в момент сравнения location1 совпадает с comparand, то оригинальное значение location1 будет возвращено. Звучит довольно запутано, потому проще написать код, который выполняет те же операции, что и CompareExchange:

Только реализация в классе Interlocked будет атомарной. То есть, напиши мы такой код сами, могла бы произойти ситуация, когда условие location1 == comparand уже выполнилось, но к моменту выполнения выражения location1 = value другой поток изменил значение location1 и оно будет утеряно.

Хороший пример использования этого метода можем найти в коде, что генерирует компилятор для любого события С#.

Напишем простой класс с одним событием MyEvent:

Соберем проект в конфигурации Release и откроем сборку при помощи dotPeek c включенной опцией Show Compiler Generated Code:

Здесь видно, что за кулисами, компилятор сгенерировал довольно изощренный алгоритм. Этот алгоритм защищает от ситуации потери подписки на событие, когда несколько потоков одновременно на это событие подписываются. Давайте распишем метод add подробнее, вспомнив что за кулисами делает метод CompareExchange

Так уже немного понятнее, хотя, наверное, все еще нуждается в объяснении. Словами бы я описал этот алгоритм следующим образом:

Если MyEvent все еще такой как был на момент как мы начали выполнять Delegate.Combine, то запиши в него то, что вернет Delegate.Combine, а если нет, то не беда, давай попробуем еще раз и будем повторять пока не выйдет.

Так ни одна подписка на событие не будет потеряна. Подобную проблему вам придется решать, если вдруг захотите реализовать динамический потокобезопасный lock-free массив. Если несколько потоков рвануться добавлять в него элементы, то важно чтобы все они в итоге были добавлены.

Monitor.Enter, Monitor.Exit, lock

Такая особенность работы критической секции в c# накладывает одно интересное ограничение на работу оператора lock: внутри оператора lock нельзя использовать оператор await. Сначала это вызвало у меня удивление, ведь аналогичная конструкция try-finally Monitor.Enter/Exit компилируется. В чем же дело? Здесь необходимо еще раз внимательно перечитать прошлый абзац, а затем добавить к нему некоторые знания о принципе работы async/await: код после await совершенно не обязательно будет выполнен на том же потоке, что и код до await, это зависит от контекста синхронизации и наличия или отсутствия вызова ConfigureAwait. Из этого следует, что Monitor.Exit может выполниться на потоке отличном от Monitor.Enter, что приведет к выбросу SynchronizationLockException. Если не верите, то можете выполнить в консольном приложении следующий код: он сгенерирует SynchronizationLockException.

Примечательно, что в WinForms или WPF приложении этот код отработает корректно, если его вызвать из главного потока Т.к. там будет контекст синхронизации, который реализует возврат в UI-Thread после выполнения await. В любом случае не стоит играться с критической секцией в контексте кода, содержащего оператор await. В этих случаях лучше использовать примитивы синхронизации, что будут рассмотрены позднее.

SpinLock, SpinWait

Monitor.Wait, Monitor.Pulse[All]

Эту пару методов стоит рассматривать вместе. С их помощью, можно реализовывать различные Producer-Consumer сценарии.

Producer-Consumer — паттерн многопроцессного/многопоточного проектирования предполагающий наличие одного или нескольких потоков/процессов, производящих данные и один или несколько процессов/потоков эти данные обрабатывающие. Как правило использует общую коллекцию.

Оба эти метода могут быть вызваны лишь при наличии у вызывающего их потока в данный момент блокировки. Метод Wait отпустит блокировку и повиснет до тех пор, пока другой поток не вызовет Pulse.

Для демонстрации работы я написал небольшой пример:

vdevid lock что это такое. Смотреть фото vdevid lock что это такое. Смотреть картинку vdevid lock что это такое. Картинка про vdevid lock что это такое. Фото vdevid lock что это такое
(Использовал именно изображение, а не текст, чтобы наглядно показать порядок выполнения инструкций)

Разбор:Установил задержку в 100мс при старте второго потока, специально чтобы гарантировать, что его выполнение начнется позднее.
— T1:Line#2 поток стартует
— T1:Line#3 поток входит в критическую секцию
— T1:Line#6 поток засыпает
— T2:Line#3 поток стартует
— T2:Line#4 зависает в ожидании критической секции
— T1:Line#7 отпускает критическую секцию и зависает в ожидании выхода Pulse
— T2:Line#8 входит в критическую секцию
— T2:Line#11 оповещает T1 при помощи метода Pulse
— T2:Line#14 выходит из критической секции. До этих пор T1 не может продолжить выполнение.
— T1:Line#15 выходит из ожидания
— T1:Line#16 выходит из критической секции

В MSDN есть важная ремарка, касательно использования методов Pulse/Wait, а именно: Monitor не хранит информацию о состоянии, а значит, если вызов метода Pulse до вызова метода Wait может привести к дедлоку. Если такая ситуация возможна, то лучше использовать один из классов семейства ResetEvent.

ReaderWriterLockSlim

Это горячо любимый мною примитив синхронизации, представлен одноименным классом пространства имен System.Threading. Мне кажется, много программ стали бы работать лучше, используй их разработчики именно этот класс, вместо обычного lock.

Идея: много потоков может читать, лишь один писать. Как только поток заявляет о желании писать, новые чтения не могут быть начаты, а будут ожидать завершения записи. Так же есть понятие upgradeable-read-lock, который можно использовать если в процессе чтения понимаете, о необходимости что-то записать, такой lock будет преобразован в write-lock за одну атомарную операцию.

В пространстве имен System.Threading так же есть класс ReadWriteLock, но он крайне не рекомендован для новой разработки. Slim версия позволит избежать ряда случаев, приводящих к дедлокам, к тому же позволяет быстро захватить блокировку, т.к. поддерживает синхронизацию в режиме spin-wait перед уходом в режим ядра.

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

Интерфейс класса ReaderWriterLockSlim прост и понятен, но его использование вряд ли можно назвать удобным:

Мне нравится оборачивать его использование в класс, что позволяет использовать его куда удобнее.
Идея: сделать методы Read/WriteLock что возвращают объект с методом Dispose, тогда это позволит использовать их в using и по количеству строчек это вряд ли будет отличаться от обычного lock.

Такой трюк позволит далее просто писать:

Семейство ResetEvent

К этому семейству я отношу классы ManualResetEvent, ManualResetEventSlim, AutoResetEvent.
Классы ManualResetEvent, его Slim версия и класс AutoResetEvent могут находится в двух состояниях:
— Взведенное (non-signaled), в этом состоянии все потоки, вызвавшие WaitOne, зависают, до перехода события в спущенное(signaled) состояние.
— Спущенное состояние(signaled), в этом состоянии отпускаются все потоки, зависшие на вызове WaitOne. Все новые вызовы WaitOne на событии в спущенном состоянии проходят условно-мгновенно.

Класс AutoResetEvent от класса ManualResetEvent отличает то, что он автоматически переходит во взведенное состояние, после того как отпустит ровно один поток. Если несколько потоков будут висеть в ожидании AutoResetEvent, то вызов Set отпустит лишь один произвольный, в отличии от ManualResetEvent. ManualResetEvent отпустит все потоки.

Рассмотрим пример работы AutoResetEvent:
vdevid lock что это такое. Смотреть фото vdevid lock что это такое. Смотреть картинку vdevid lock что это такое. Картинка про vdevid lock что это такое. Фото vdevid lock что это такое

В примере видно, что событие переходит во взведенное состояние(non-signaled) автоматически лишь отпустив поток, зависший на вызове WaitOne.

Класс ManualResetEvent, в отличии от ReaderWriterLock, не помечен как устаревший и не рекомендованный к использованию после появления своей Slim версии. Slim версию этого класса эффективно использовать для коротких ожиданий, т.к. оно происходит в режиме Spin-Wait, обычная версия подходит для долгих.

Кроме классов ManualResetEvent и AutoResetEvent также существует класс CountdownEvent. Этот класс удобен для реализации алгоритмов, где за частью, что удалось распараллелить, следует часть сведения результатов воедино. Такой подход известен как fork-join. Работе этого класса посвящена отличная статья, потому не буду здесь разбирать его подробно.

Источник

Vdevid lock что это такое

Согласно правилам ресурса 4pda перед написанием сообщения в теме необходимо ознакомиться с шапкой, FAQ, выполнить поиск по теме и лишь тогда, при отсутствии ответа на интересующий вопрос, задавать его в теме. Если Ваше сообщение удалено, значит на интересующий Вас вопрос есть ответ в шапке, теме, FAQ или вопрос является оффтопом для данной темы. Если Вам интересна причина удаления поста, то Вы можете обратиться к куратору темы в QMS, чтобы получить разъяснение по поводу удаления Вашего сообщения.
Пункты правил, которые нужно внимательно прочесть и выполнить перед написанием сообщения в теме:

4.1. Перед созданием новой темы или сообщения следует внимательно ознакомиться с принятыми в этом разделе правилами.

4.3. Не торопитесь создавать тему, сообщение. Весьма вероятно, что ваш вопрос обсуждался ранее, либо существует тема обсуждения вашего девайса. Не забудьте обратить внимание на подраздел «Важное» в соответствующем вашему вопросу разделе. Воспользуйтесь поиском. При этом последовательно совершите поиск по нескольким подходящим ключевым словам. Например, если ваш вопрос связан с использованием Bluetooth на Qtek S100, следует искать по словам «Bluetooth» и «Qtek».

4.4. Если вы нашли тему, которая соответствует вашей проблематике, не следует сразу же писать в ней сообщение. Возможно, ваша проблема уже обсуждалась, и решение найдено. Воспользуйтесь «версией для печати» и поиском по ключевым словам в ней. Непременно прочитайте шапку темы — в неё помещается полезная информация, специально для вас.

4.7.1. При ответе в существующую тему постарайтесь формулировать вопрос или ответ так, чтобы он был понятен остальным участникам форума. Избегайте флуда, философствований, лирических отступлений.

3.1. Прежде чем задать вопрос, прочтите FAQ по Устройству и по Прошивке (ссылка на FAQ размещается в шапке темы обсуждения прошивки устройства), если такой имеется. Если Вы не нашли ответа на свой вопрос в FAQ по вашему устройству, или же он отсутствует, то поищите похожие вопросы в общем FAQ по Android и только если ответа там нет спрашивайте. Пользователи, задающие вопросы, ответы на которые занесены в FAQ могут быть наказаны на усмотрение модератора (РО от 1 до 3 дней).

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *