windows-drivers-rs - plataforma que permite desenvolver drivers do Windows em Rust
(github.com/microsoft)- Conjunto de crates Rust que permite desenvolver Windows Drivers em Rust, com foco em dar suporte aos modelos de desenvolvimento de drivers WDM e WDF
- Os principais componentes são
wdk-build, para configuração de build do WDK;wdk-sys, com bindings FFI diretos para a API do WDK;wdk, com bindings seguros e idiomáticos para a API do WDK;wdk-panic, para panic handler;wdk-alloc, para suporte aalloc; ewdk-macros, um conjunto de macros que ajuda no uso direto dos bindings dewdk-sys - Foi criado tendo em mente suporte a drivers WDM, KMDF, UMDF e serviços Win32, incluindo suporte a todas as versões de WDF incluídas no WDK 22H2 ou superior
- Os crates publicados no
crates.ioatualmente suportam apenas KMDF v1.33; bindings para outras configurações podem ser gerados clonandowindows-drivers-rse depois modificando a configuração debuild.rsemwdk-sys - O fluxo de uso consiste em criar um pacote Cargo
lib, adicionar as dependênciaswdk-build,wdk,wdk-sys,wdk-allocewdk-panic, configurarcdylib, definir os metadados do WDK, chamarwdk_build::configure_wdk_binary_build()embuild.rs, adicionarDriverEntrye executarcargo make- Crates de Kernel Mode como drivers KMDF e WDM exigem estratégia de panic
abort,#![no_std]e configuração de panic handler - Para usar o módulo
allocda biblioteca padrão do Rust, é necessário configurar o allocator globalwdk_alloc::WdkAllocator
- Crates de Kernel Mode como drivers KMDF e WDM exigem estratégia de panic
- Os requisitos de build incluem
libclangparabindgen,cargo-makepara tarefas pós-build e um ambiente WDK válido; a forma recomendada é entrar no prompt de desenvolvedor do eWDK - Por padrão,
cargo makefaz o build e empacota o driver, gerando como resultado um pacote de driver assinado e o arquivoWDRLocalTestCert.ceremtarget/<Cargo profile>/packageou sob o caminho da arquitetura alvo - Há suporte para passar argumentos como
cargo make default --target <TARGET TRIPLE>,--release,--features <FEATURES>e+<TOOLCHAIN>; também é possível ativar a verificação de assinatura dos arquivos.syse.catgerados comWDK_BUILD_ENABLE_SIGNTOOL_VERIFY=true - A nova extensão do Cargo
cargo-wdkestá em desenvolvimento, em estado Preview, para substituir ocargo-makecomo ferramenta recomendada para build de drivers Rust - Exemplos mínimos de WDM, KMDF e UMDF estão no diretório examples, e exemplos de criação de drivers podem ser vistos em Windows-rust-driver-samples
- Ainda está em estágio inicial de desenvolvimento e não é recomendado para uso em produção
3 comentários
Opiniões do Hacker News
Para quem não se lembra, Mark Russinovich, antes de suceder seu chefe e passar a ser citado como candidato a próximo CEO da MSFT, comandava uma empresa de ferramentas de software e consultoria em kernel NT à qual os engenheiros de Redmond recorriam para aprender desenvolvimento do kernel NT.
Ele também descobriu recursos de proteção de arquivos como o rootkit de DRM da Sony e o rootkit da Symantec, e ainda pegou a Best Buy pirateando o ERD Commander.
Hoje me arrependo um pouco de ter apagado o LinkedIn em 2014. Era uma conta em que todo o Valley e o Mark eram conexões de primeiro grau, mas o relativo anonimato também traz liberdade e agilidade. Qual era mesmo aquela música de reggae do Desmond Dekker sobre ser inútil ficar falando do quanto você fez, ganhou e quem conhece?
É bem interessante que empresas desse porte, mesmo tendo uma posição muito mais vantajosa, com acesso ao código-fonte real e aos engenheiros, não consigam fazer bem esse tipo de coisa por conta própria. Esses terceiros — pelo menos Levin — tiveram de depender em boa parte de engenharia reversa.
https://newosxbook.com
Considerando que praticamente toda empresa no mundo que usa Windows utiliza pelo menos uma ferramenta da Sysinternals, talvez a influência da Sysinternals tenha sido maior até do que a do próprio Azure.
Provavelmente foi por isso que a MSFT fez o acquihire de Mark Russinovich e sua equipe.
A impressão que tive do primeiro livro foi a de alguém que vê o mundo de forma extremamente preto no branco.
Tweet original: https://twitter.com/markrussinovich/status/17057307039574058...
http://farside.link/twitter.com/markrussinovich/status/17057...
Legal /s, mas isso não parece Rust idiomático:
pub struct QueueContext {
buffer: PVOID,
length: usize,
timer: wdf::Timer,
current_request: WDFREQUEST,
current_status: NTSTATUS,
spin_lock: wdf::SpinLock,
}
Ao escrever drivers Rust no kernel Linux há um problema parecido, e o mesmo vale para outros projetos que interoperam com C.
Tipos como NTSTATUS têm bastante documentação associada. Diferentemente de C ou C++, em Rust não dá para simplesmente atribuir um valor inteiro a um valor de enum. Você poderia criar uma classe wrapper para obrigar casts toda vez, mas aí metade do código viraria
.into()e isso provavelmente também adicionaria overhead ao driver.Pelo que parece, exceto talvez pelo
void*do buffer, esses valores de enum não estão sendo definidos nem alterados, apenas lidos. Para NTSTATUS, um blocomatch {}parece suficiente. WDFREQUEST é um handle, então não há muito que se possa fazer além de trocá-lo por outro handle do mesmo tipo.Timer e SpinLock foram transformados em objetos mais idiomáticos em Rust, que encapsulam internamente chamadas de biblioteca unsafe. Fora isso, não vejo bem como tornar esse código mais idiomático em Rust sem impor um custo de desempenho considerável.
Sabe o que seria melhor? Escrever drivers de dispositivo em uma linguagem com memória gerenciada, como C#.
Concordo com a avaliação da Microsoft de que, em vez de tornar o kernel mais acessível, o melhor é executar menos código de fabricantes dentro do kernel. C# não é adequado para situações como “quero acessar um certo buffer, mas ele ainda não foi paginado para a memória, e estou dentro de um tratador de interrupção”, então parece quase impossível rodar um coletor de lixo no kernel sem bugs.
Drivers podem acessar memória em momentos em que uma falta de página é impossível, por exemplo durante um tratador de interrupção, então é preciso controlar a disponibilidade de memória de forma muito rígida. A linguagem e o runtime de C# teriam, no mínimo, de adicionar recursos para lidar explicitamente com isso.
Acho que isso está sendo um pouco subestimado, então vou acrescentar algo. Russinovich é alguém que criou inúmeros materiais e ferramentas relacionados ao kernel do Windows. Entre os desenvolvedores ligados ao kernel do Windows (incluindo os que criaram rootkits), provavelmente não há ninguém que não tenha estudado vendo os materiais ou a documentação do Russinovich.
Ouvi dizer que estão reescrevendo o kernel do Windows em Rust e, finalmente, o SDK para drivers está saindo. Pelo visto, em breve deve aparecer um aviso dizendo para criar drivers em Rust a partir de 20XX.