Тесно работая уже много лет с шиной USB и реализуя устройства всевозможных классов, я набрал довольно большой список различных приколов в поведении шины. В процессе отладки падало все что только можно, а главное стандартные драйвера из стандартной поставки MS Windows. В синий экран меня уводили устройства стандартных классов, падали драйвера USBHUB.SYS, USBHID.SYS, USBCCID.SYS (последний вообще дырявый до чертиков). Однако, в большинстве случаев проявление было сложным и требовало действия от пользователя на самом PC.
Но вот один случай все-таки очень привлек и я сохранил «важную» микропрограмму устройства для анализа и выделения проблемы. Итак, представляю Вашему внимаю USB-устройство, которое в буквальном смысле осуществляет DOS-атаку на систему под управлением Windows XP 32-bit (так же проверено под Windows 2003 Server 32-bit). Windows Vista данной проблеме вроде бы не подвержена.
Итак, после подключения устройства в USB-порт независимо от настроек автозагрузки и независимо от того, заблокирован сеанс пользователя или нет, процесс System начинает отъедать приличный объем процессорного времени. На однопроцессорной системе это все 100% (т.е. система практически вешается), на 2х и более процессорах система внешне остается вполне работоспособной и отзывчивой, но все равно в Диспетчере задач видно, что не все «слава богу». Мало того, после извлечения устройства эффект сохраняется! Остается только перезагружать систему, да и с перезагрузкой не все гладко, вроде бы работа завершается, но непосредственно перезагрузка/выключение не происходит, система остается висеть на пустом экране с курсором.
В продолжение к этому, все новые подключаемые USB устройства так же не определяются в системе. Видимо, виснет сервис, отвечающий за процесс определения устройства.
Вот что можно увидеть в Windows 2003 Server 32-bit после подключения в Диспетчере задач:

Привожу готовую микропрограмму для микроконтроллера NXP LPC214х. Сделана на основе стека LPCUSB. Микропрограмма оттестирована на стандартной отладочной плате Keil MCB2140. Микропрограмму можно взять здесь, в архиве есть HEX-файл, готовый к заливке в LPC214x и проект микропрограммы, пригодный для сборки в Keil RealView MDK версии 4.00 и выше (можно использовать среду в демо-режиме).
Теперь о сути проблемы и условиях возникновения: все дело в некорректно сформированном дескрипторе USB.
Примечание: Дескрипторы USB — это набор структур, которые описывают устройство USB. В процессе инициализации устройства, хост запрашивает данный дескриптор, обрабатывает его и в соответствии с полученной информацией инициализирует устройство (находит необходимый драйвер, получает настройки устройства, устанавливает строковые константы и т.д.).
Если быть более точным: в дескрипторе конфигурации имеется поле, которое описывает суммарный размер дескрипторов отвечающих за конфигурацию устройства (сюда входит непосредственно дескриптор конфигурации, дескриптор интерфейса, дескриптор класса и дескрипторы конечных точек). Так вот, данное значение в процессе правки дескрипторов случайно было задано ошибочным: серьезно завышено, в данном примере вместо 0x29 установлено 0x200.
Данное поле по какой-то причине обрабатывается некорректно. Более глубоких изысканий не проводил, может быть не достаточно просто завысить значение и сказывается некая специфика работы стека в данной нештатной ситуации, именно поэтому привел выше ссылку на полную микропрограмму.
Выводы о представленной проблеме оставляю на вашей совести. От себя только замечу, что основное слабое место: требуется «физический контакт» с атакуемой машиной. Именно по этой причине опасность данной ошибки в стеке USB операционной системы в большинстве случаев не велика. Сервера должны стоять в помещении с ограниченным доступом, а для рядового пользователя такой «прикол» скорее всего будет просто неприятным.
Хорошо бы понять, какие еще версии MS Windows так болезненно реагируют на данный некорректный дескриптор. Я проверил на 3х машинах под Windows XP и одной под Windows 2003 Server (с полным набором всех обновлений), 64-битных операционок под рукой, к сожалению, нет. На имеющейся машине под Windows Vista никаких зависаний не произошло, она квалифицировала устройство как полностью исправное (видимо, не использует значение данного поля вообще).
Но вот один случай все-таки очень привлек и я сохранил «важную» микропрограмму устройства для анализа и выделения проблемы. Итак, представляю Вашему внимаю USB-устройство, которое в буквальном смысле осуществляет DOS-атаку на систему под управлением Windows XP 32-bit (так же проверено под Windows 2003 Server 32-bit). Windows Vista данной проблеме вроде бы не подвержена.
Итак, после подключения устройства в USB-порт независимо от настроек автозагрузки и независимо от того, заблокирован сеанс пользователя или нет, процесс System начинает отъедать приличный объем процессорного времени. На однопроцессорной системе это все 100% (т.е. система практически вешается), на 2х и более процессорах система внешне остается вполне работоспособной и отзывчивой, но все равно в Диспетчере задач видно, что не все «слава богу». Мало того, после извлечения устройства эффект сохраняется! Остается только перезагружать систему, да и с перезагрузкой не все гладко, вроде бы работа завершается, но непосредственно перезагрузка/выключение не происходит, система остается висеть на пустом экране с курсором.
В продолжение к этому, все новые подключаемые USB устройства так же не определяются в системе. Видимо, виснет сервис, отвечающий за процесс определения устройства.
Вот что можно увидеть в Windows 2003 Server 32-bit после подключения в Диспетчере задач:

Привожу готовую микропрограмму для микроконтроллера NXP LPC214х. Сделана на основе стека LPCUSB. Микропрограмма оттестирована на стандартной отладочной плате Keil MCB2140. Микропрограмму можно взять здесь, в архиве есть HEX-файл, готовый к заливке в LPC214x и проект микропрограммы, пригодный для сборки в Keil RealView MDK версии 4.00 и выше (можно использовать среду в демо-режиме).
Теперь о сути проблемы и условиях возникновения: все дело в некорректно сформированном дескрипторе USB.
Примечание: Дескрипторы USB — это набор структур, которые описывают устройство USB. В процессе инициализации устройства, хост запрашивает данный дескриптор, обрабатывает его и в соответствии с полученной информацией инициализирует устройство (находит необходимый драйвер, получает настройки устройства, устанавливает строковые константы и т.д.).
Если быть более точным: в дескрипторе конфигурации имеется поле, которое описывает суммарный размер дескрипторов отвечающих за конфигурацию устройства (сюда входит непосредственно дескриптор конфигурации, дескриптор интерфейса, дескриптор класса и дескрипторы конечных точек). Так вот, данное значение в процессе правки дескрипторов случайно было задано ошибочным: серьезно завышено, в данном примере вместо 0x29 установлено 0x200.
0x09, // bSize DESC_CONFIGURATION, // bDescrType //LE_WORD(0x29), // wTotalLength LE_WORD(0x200), // wTotalLength 0x01, // bNumInterfaces 0x01, // bConfigurationValue 0x00, // iConfiguration 0x80, // bmAttributes 0x32, // bMaxPower
Данное поле по какой-то причине обрабатывается некорректно. Более глубоких изысканий не проводил, может быть не достаточно просто завысить значение и сказывается некая специфика работы стека в данной нештатной ситуации, именно поэтому привел выше ссылку на полную микропрограмму.
Выводы о представленной проблеме оставляю на вашей совести. От себя только замечу, что основное слабое место: требуется «физический контакт» с атакуемой машиной. Именно по этой причине опасность данной ошибки в стеке USB операционной системы в большинстве случаев не велика. Сервера должны стоять в помещении с ограниченным доступом, а для рядового пользователя такой «прикол» скорее всего будет просто неприятным.
Хорошо бы понять, какие еще версии MS Windows так болезненно реагируют на данный некорректный дескриптор. Я проверил на 3х машинах под Windows XP и одной под Windows 2003 Server (с полным набором всех обновлений), 64-битных операционок под рукой, к сожалению, нет. На имеющейся машине под Windows Vista никаких зависаний не произошло, она квалифицировала устройство как полностью исправное (видимо, не использует значение данного поля вообще).