Запретить запуск драйвера IOKit в & quot; kextunload & quot; если некоторые клиенты не остаются на связи

У меня есть базовый проект Driver / Deamons IOKit с отношением один ко многим (имеется в виду, что к одному драйверу подключено несколько клиентов).

Основной драйвер — это объект IOKit, полученный из IOService а также является поставщиком драйверов клиентов, полученных из IOUserClient, Это агенты клиентов пользовательского пространства (по одному на клиент клиентского пространства)

Моей целью было предотвратить выгрузку драйвера в случае kextunload Команда с правами суперпользователя, так что только при последнем отключении клиента (процесс завершается или вызывается IOServiceClose), драйвер будет закрыт автоматически (без необходимости делать kextunload вручную)

Чтобы проверить, какие команды IOKit мне нужно отключить / перезвонить, я завернул IOService обратные вызовы с соответствующим сообщением печати и наблюдали журналы в сценарии запуска kextunload где подключены 2 клиента:

kernel: (driver) virtual bool com_osxkernel_driver::terminate(IOOptionBits)
kernel: (driver) virtual bool com_osxkernel_driverClient::terminate(IOOptionBits)
kernel: (driver) virtual bool com_osxkernel_driverClient::terminate(IOOptionBits)
kernel: (driver) virtual void com_osxkernel_driverClient::stop(IOService *)
kernel: (driver) virtual void com_osxkernel_driverClient::stop(IOService *)
kernel: (driver) virtual void com_osxkernel_driver::stop(IOService *)

Кажется, что даже если я беру ссылку от каждого IOUserClient на его провайдера, и выпуская те ссылки на IOUserClient::clientClose
, kextunload Команда все еще успешна.

Единственный способ найти мою цель — отложить ::terminate команда и вызвать его явно из ::clientClose,

Так что я удалил звонок IOService::terminate и вместо этого позвонил из IOUserClient::clientClose(),
Вот соответствующий код:

IOReturn com_osxkernel_driverClient::clientClose()
{
myProvider->release();
return super::terminate(kIOServiceSynchronous) ? kIOReturnSuccess : kIOReturnError;
}bool com_osxkernel_driverClient::terminate(IOOptionBits options) {
os_log_info(g_logger,"%s", __PRETTY_FUNCTION__);
return true;
}

Я хотел бы знать, есть ли какие-нибудь, менее хакерские способы предотвращения kextunload от успеха и контроля времени выгрузки драйвера.

Спасибо

3

Решение

Если вы посмотрите на kextunload исходный код, вы увидите, что это вызывает в IOCatalogueTerminate(), В ядре это в конечном итоге пробивается в IOCatalogue::_terminateDrivers() функция. (IOCatalogue.cpp в источниках xnu) Там вы увидите, что для каждого экземпляра класса IOKit, принадлежащего выгружаемому kext, выполняется следующее:

if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) )
{
ret = kIOReturnUnsupported;
break;
}

Это указывает на то, что единственный способ остановить записи IORegistry вашего kext — это возвращение false из terminate(),

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

Если вы вернете false из terminate()Вам также нужно быть осторожным, чтобы не блокировать прекращение по законным причинам. (Например, если это драйвер устройства, то соответствует вашему коду, например, IOUSBInterface может попытаться terminate() экземпляр вашего драйвера, если устройство отключено от сети.)

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]