Как отобразить память в DriverKit с помощью IOMemoryDescriptor :: CreateMapping?

Я пытаюсь узнать больше о DriverKit и управлении памятью, и я прочитал этот вопрос:

Как выделить память в системном расширении DriverKit и сопоставить ее с другим процессом?

И я хотел бы понять, как использовать IOMemoryDescriptor::CreateMapping.

Я написал небольшое приложение, чтобы проверить это там, где я это делаю (очень упрощенный код):

uint8_t * buffer = new uint8_t[256];
for (int i = 0 ; i < 256 ; i++)
   buffer[i] = 0xC6;

clientData in, out;
in.nbytes = 256;
in.pbuffer = buffer;
size_t sout = sizeof(out);

IOConnectCallStructMethod(connection, selector,&in,sizeof(in),&out,&sout);

// out.pbuffer now has new values in it

В моем пользовательском клиентском классе Kext я делал (упрощаю):

IOReturn UserClient::MyExtFunction(clientData * in, clientData * out, IOByteCount inSize, IOByteCount * outSize)
{
   MyFunction(in->nBytes, in->pbuffer);//this will change the content of pbuffer

   *out = *in; 
}


IOReturn UserClient::MyFunction(SInt32 nBytesToRead,void* pUserBuffer,SInt32* nBytesRead)
{
    PrepareBuffer(nBytesToRead,&pBuffer);
    ...
    (call function that will fill pBuffer)
}


IOReturn UserClient::PrepareBuffer(UInt32 nBytes,void** pBuffer);
{
   IOMemoryDescriptor * desc = IOMemoryDescriptor::withAddressRange((mach_vm_address_t)*pBuffer,nBytes,direction, owner task);

   desc->prepare();
   IOMemoryMap * map = desc->map();
   *pBuffer = (void*)map->getVirtualAddress();

   return kIOReturnSuccess;
}

Это то, что я не знаю, как воспроизвести в DExt, и где, как мне кажется, я действительно не понимаю основ CreateMapping.

Или то, что я раньше делал, невозможно?

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

Я могу создать IOBufferMemoryDescriptor, но как мне привязать его к буферу из моего приложения? Я также не понимаю различных вариантов CreateMapping.

Обратите внимание, что в другом тестовом приложении я успешно использовал _9 _ / _ 10_, но я хотел бы узнать конкретно о CreateMapping ().

(Надеюсь, все в порядке, я много редактировал этот вопрос ... все еще новичок в StackOverflow)


person ScottBraun    schedule 08.10.2020    source источник


Ответы (2)


Или то, что я раньше делал, невозможно?

Короче нет.

Вы пытаетесь отобразить произвольную память пользовательского процесса, которую клиентское приложение явно не пометило как доступную для драйвера с помощью IOKit. Это не согласуется с идеями Apple о безопасности, защите и песочнице, поэтому такого рода вещи недоступны в DriverKit.

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

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

  • Путем передачи буферов ›= 4097 байтов в качестве входных или выходных аргументов структуры в IOConnectCall…Method()s, чтобы они приходили как IOMemoryDescriptors в драйвере. Обратите внимание, что они могут сохраняться в драйвере на более длительный срок, но, по крайней мере, для структур ввода, обновления на стороне пользовательского пространства не будут отражаться на стороне драйвера, поскольку используется отображение копирования при записи. Значит, их следует использовать исключительно для отправки данных в намеченном направлении.
  • Путем пользовательского процесса, отображающего существующий IOMemoryDescriptor в его пространство, используя _4 _ / _ 5_.

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

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

Я отправил отзыв в Apple с просьбой о более мощном механизме обмена данными между пользовательскими клиентами и десктопами; Я не знаю, будет ли это реализовано, но если такая возможность будет полезна, я рекомендую вам сделать то же самое. (объясняя, для чего вы хотите использовать это с примерами) Чем больше из нас сообщит об этом, тем больше вероятность, что это произойдет. (IOMemoryDescriptor::CreateSubMemoryDescriptor() был добавлен после того, как я подал на него запрос; я не буду утверждать, что я был первым, кто это сделал, или что Apple не планировала добавлять его до моего предложения, но они активно улучшают API DriverKit.)

Исходный ответ до того, как вопрос был изменен, чтобы быть более конкретным:

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

Ваш вопрос немного расплывчатый, но позвольте мне посмотреть, смогу ли я понять, что вы сделали в своем kext, и что вы делаете в своем dext:

  • Вы звоните IOConnectCallStructMethod(connection, selector, buffer, 256, NULL, NULL); в своем приложении. Это означает, что buffer передается как входной аргумент структуры вашему внешнему методу.
  • Поскольку длина вашего буфера составляет 256 байт, что меньше или равно sizeof(io_struct_inband_t), содержимое буфера отправляется ядру in-band - другими словами, оно копируется во время IOConnectCallStructMethod() вызов.
  • Это означает, что в функции диспетчеризации внешнего метода вашего kext ввод структуры передается через поля _13 _ / _ 14_ во входящей структуре IOExternalMethodArguments. structureInput является указателем в контексте ядра и может быть разыменован напрямую. Указатель действителен только во время выполнения диспетчеризации вашего метода и не может использоваться после синхронного возврата метода.
  • Если вам нужно использовать буфер для ввода-вывода устройства, вам может потребоваться заключить его в IOMemoryDescriptor. Один из способов сделать это действительно через IOMemoryDescriptor::CreateMapping().
  • Если размер буфера составляет 4097 байт или больше, он будет передан через structureInputDescriptor IOMemoryDescriptor, который может быть передан непосредственно на ввод-вывод устройства или отображен в память для разыменования в ядре. Этот дескриптор памяти напрямую ссылается на память пользовательского процесса.

Расширения DriverKit значительно более ограничены в возможностях, но аргументы внешнего метода поступают почти таким же образом.

person pmdj    schedule 09.10.2020
comment
Прошу прощения за то, что был слишком расплывчатым, я только что понял это и постараюсь дать лучшее объяснение. Но сначала спасибо за ваш ответ (и ваши ответы на вопросы, заданные другими, это действительно помогло мне). Я отредактировал свой вопрос, чтобы лучше прояснить, что я пытаюсь сделать. - person ScottBraun; 09.10.2020
comment
Большое спасибо, я обязательно отправлю отзыв в Apple. - person ScottBraun; 09.10.2020

person    schedule
comment
Я не уверен, что это отвечает на вопрос? Насколько я понимаю, вопрос заключается в отображении диапазона памяти пользовательского процесса, а не в недавно выделенном дескрипторе буферной памяти. - person pmdj; 09.04.2021