systemd adota Rust em componentes, mas mantém bibliotecas centrais em C
Linux Notícias Open Source Software livre Tecnologia

systemd adota Rust em componentes, mas mantém bibliotecas centrais em C

O systemd integra a linguagem Rust para melhorar a segurança e a eficiência, mantendo suas bibliotecas centrais em C para garantir estabilidade e desempenho confiáveis no sistema Linux. Essa combinação permite que o sistema evolua com inovação, sem perder a base sólida já testada, equilibrando modernidade e confiança para usuários e desenvolvedores.

O systemd está abrindo espaço para a linguagem Rust em seu desenvolvimento, mas não pretende substituir o código C que sustenta sua infraestrutura principal. A decisão estabelece uma estratégia gradual: novos programas independentes poderão utilizar Rust, enquanto as bibliotecas compartilhadas fundamentais continuarão sendo desenvolvidas em C.

A mudança representa um passo importante para a adoção de uma linguagem conhecida por seus mecanismos de segurança de memória em um dos projetos mais importantes do ecossistema Linux. Entretanto, os responsáveis pelo systemd não querem introduzir uma tecnologia nova sem avaliar cuidadosamente suas consequências para a arquitetura, a compatibilidade e o desempenho do sistema.

Em uma publicação, Christian Brauner e Lennart Poettering explicaram que existem diferenças significativas entre permitir Rust em pequenos executáveis e utilizá-lo em bibliotecas compartilhadas das quais diversos componentes dependem.

Por isso, o projeto decidiu começar pelos chamados componentes de nível mais baixo, ou leaf components. São programas independentes que não funcionam como dependências fundamentais de outras partes do systemd.

Por que o systemd não vai migrar completamente para Rust?

A principal razão para limitar a adoção do Rust está relacionada ao funcionamento das bibliotecas compartilhadas.

O systemd possui uma arquitetura composta por muitos executáveis e bibliotecas. Um dos elementos importantes dessa estrutura é a libsystemd-shared.so, que reúne funcionalidades utilizadas por diferentes programas do projeto.

Introduzir Rust diretamente nessa biblioteca exige recursos que a linguagem ainda não oferece de maneira adequada para as necessidades dos desenvolvedores: suporte de primeira classe a bibliotecas compartilhadas e uma interface binária estável, conhecida como ABI (Application Binary Interface).

A ABI define como diferentes partes de um programa se comunicam em nível binário. Ela estabelece, entre outros aspectos, como funções são chamadas e como os dados são organizados. Uma interface estável é especialmente importante em projetos que precisam manter compatibilidade entre diferentes componentes e versões.

O problema é que o Rust ainda não oferece uma ABI estável que permita aos mantenedores utilizar suas bibliotecas compartilhadas com a previsibilidade necessária.

Uma alternativa seria compilar estaticamente o código Rust em cada programa que precisasse dele. Entretanto, essa abordagem não é interessante para o systemd.

O projeto possui mais de 180 executáveis. Se cada um precisasse incorporar sua própria cópia de determinadas partes do código Rust, haveria duplicação de componentes e aumento desnecessário do tamanho dos programas.

Em uma infraestrutura tão ampla, essa escolha poderia gerar custos adicionais de armazenamento e manutenção. Por isso, os desenvolvedores preferem manter as funcionalidades compartilhadas em C até que as limitações técnicas do Rust sejam resolvidas.

Rust poderá ser usado em novos programas independentes

Embora exista essa restrição, a decisão não significa que o systemd esteja rejeitando Rust.

Pelo contrário: a linguagem passa a fazer parte das ferramentas disponíveis para o desenvolvimento de novos componentes. A diferença é que esses programas precisam ser independentes e não podem se transformar em dependências fundamentais de outros componentes do projeto.

Para facilitar essa integração, o systemd pretende disponibilizar interfaces Rust que encapsulam funcionalidades já existentes nas bibliotecas C.

Na prática, isso permite que um programa escrito em Rust utilize recursos internos do systemd sem precisar implementar novamente funcionalidades que já estão disponíveis no código tradicional.

Essa estratégia também ajuda a manter um comportamento uniforme entre os programas escritos nas duas linguagens.

Os desenvolvedores querem que utilitários em Rust apresentem o mesmo padrão de argumentos de linha de comando, mensagens de ajuda, registros de eventos e tratamento de erros utilizado pelos programas em C.

Assim, a adoção de uma nova linguagem não deverá criar diferenças desnecessárias na experiência de quem utiliza ou administra o sistema.

Por que o projeto prefere Meson em vez de Cargo?

Outra decisão importante envolve o processo de compilação.

O ecossistema Rust utiliza o Cargo como ferramenta padrão para gerenciamento de dependências e construção de projetos. No entanto, o systemd não pretende introduzir esse segundo sistema de compilação em sua infraestrutura.

O projeto continuará utilizando exclusivamente o Meson, ferramenta que já faz parte do processo de construção do systemd.

Manter um único sistema de compilação reduz a complexidade da infraestrutura e evita que os responsáveis precisem administrar dois fluxos diferentes para construir os componentes do mesmo projeto.

A escolha também está relacionada à segurança e à manutenção das dependências. Ao controlar o processo de compilação dentro da estrutura existente, os desenvolvedores conseguem estabelecer regras mais rígidas sobre quais bibliotecas podem ser utilizadas.

Essa preocupação é especialmente importante em um componente que participa diretamente da inicialização e do gerenciamento de serviços do Linux.

Rust sem biblioteca padrão: a estratégia no_std

O systemd também pretende utilizar Rust sem depender de sua biblioteca padrão, seguindo o modelo conhecido como no_std.

Essa abordagem restringe os recursos disponíveis aos programas escritos na linguagem. Em vez de utilizar automaticamente todas as funcionalidades da biblioteca padrão do Rust, os componentes precisam trabalhar com um conjunto mais limitado de ferramentas.

A decisão tem relação com as necessidades específicas do systemd.

Um exemplo envolve o acesso ao sistema de arquivos. O projeto utiliza mecanismos baseados em descritores de arquivos para realizar operações sensíveis com caminhos e diretórios. Essa abordagem permite controlar melhor as operações e reduzir riscos relacionados à resolução de caminhos.

Os mantenedores consideram que as funcionalidades tradicionais de manipulação de caminhos oferecidas pelo Rust não atendem, neste momento, a todos os requisitos de segurança exigidos por determinados componentes.

Por isso, os novos programas deverão aproveitar os mecanismos já utilizados pelo systemd, em vez de adotar automaticamente as soluções oferecidas pela biblioteca padrão da linguagem.

Gerenciamento de memória também terá regras próprias

Outro ponto importante envolve a alocação de memória.

O Rust possui mecanismos de segurança que ajudam a evitar problemas comuns em linguagens como C, incluindo determinadas situações de acesso inválido à memória. Entretanto, o comportamento padrão diante de algumas falhas de alocação pode não corresponder à política adotada pelo systemd.

O projeto procura tratar falhas de alocação de maneira explícita sempre que possível, evitando que um programa simplesmente encerre sua execução de forma inesperada.

Para manter esse comportamento, o systemd fornece suas próprias implementações de estruturas e mecanismos de gerenciamento de memória.

Dessa maneira, os componentes em Rust poderão seguir as mesmas regras utilizadas pelo restante da infraestrutura, inclusive quando ocorrer uma falha durante a solicitação de memória.

A intenção é aproveitar os benefícios de segurança da linguagem sem abrir mão dos padrões de confiabilidade estabelecidos pelo projeto.

O suporte a Rust continuará opcional

Uma preocupação dos mantenedores é garantir que a adoção da nova linguagem não prejudique usuários e distribuições Linux que não possuem todas as ferramentas necessárias para compilar programas em Rust.

Por esse motivo, o suporte continuará sendo opcional.

Distribuições poderão construir o systemd sem habilitar os componentes escritos em Rust, preservando a possibilidade de utilizar o projeto em arquiteturas e ambientes nos quais essa linguagem ainda não esteja disponível ou não seja adequada.

Essa decisão é importante porque o Rust não oferece suporte a todas as arquiteturas utilizadas pelo systemd.

A integração também exige ferramentas específicas de desenvolvimento, incluindo uma versão compatível do compilador Rust e do bindgen, utilizado para gerar interfaces entre Rust e C.

Dessa forma, os responsáveis pelas distribuições precisam considerar essas dependências ao preparar seus ambientes de compilação.

O systemd não pretende reescrever código C sem necessidade

Um dos pontos mais importantes da decisão é a rejeição de reescritas motivadas apenas pela preferência por uma linguagem de programação.

Os mantenedores não pretendem converter automaticamente componentes antigos e estáveis de C para Rust.

Embora Rust ofereça vantagens importantes relacionadas à segurança de memória, isso não significa que uma reescrita resolva todos os problemas de segurança de um programa.

Brauner e Poettering destacam que determinadas vulnerabilidades estão relacionadas à própria superfície de ataque de um componente. Em situações que envolvem operações sensíveis com caminhos e acesso ao sistema de arquivos, por exemplo, simplesmente trocar a linguagem de implementação não elimina necessariamente o problema.

O mais importante é compreender a origem do risco e modificar a arquitetura quando isso for necessário.

Essa postura evita reescritas caras, reduz a possibilidade de introduzir novos erros e preserva componentes que já demonstraram confiabilidade ao longo dos anos.

Rust deve ganhar espaço no ecossistema Linux

A decisão do systemd acompanha uma tendência mais ampla de adoção do Rust em projetos importantes do software livre.

O próprio kernel Linux começou a incorporar a linguagem de maneira experimental na versão 6.1. Desde então, o suporte vem evoluindo, permitindo que novos componentes aproveitem recursos de segurança oferecidos pelo Rust.

O Ubuntu também tem avançado nessa direção, adotando ferramentas desenvolvidas em Rust para substituir algumas implementações tradicionais de utilitários do sistema.

No caso do systemd, entretanto, a estratégia é mais conservadora. O projeto pretende aproveitar a linguagem em novos programas sem comprometer sua arquitetura atual ou criar dependências difíceis de manter.

A possibilidade de utilizar Rust nas bibliotecas centrais não está descartada. Os mantenedores demonstraram interesse em trabalhar com a comunidade da linguagem para superar as limitações relacionadas às bibliotecas compartilhadas e ao acesso seguro ao sistema de arquivos.

O que essa decisão significa para o Linux?

A iniciativa mostra que a adoção do Rust em projetos fundamentais do Linux não precisa acontecer por meio de uma substituição completa do código existente.

O systemd está escolhendo uma abordagem gradual, na qual cada componente pode utilizar a linguagem mais adequada às suas necessidades, desde que sejam respeitadas as regras de compatibilidade, segurança e manutenção.

Para desenvolvedores e administradores de sistemas, isso significa que o systemd poderá receber novos utilitários escritos em Rust sem abandonar imediatamente sua infraestrutura em C.

Também demonstra que a segurança de memória é apenas uma parte de um projeto confiável. Compatibilidade binária, gerenciamento de dependências, comportamento previsível e suporte a diferentes arquiteturas continuam sendo requisitos fundamentais.

No longo prazo, a evolução do suporte a bibliotecas compartilhadas no Rust poderá abrir espaço para uma integração mais profunda. Até lá, o systemd seguirá adotando a linguagem com limites bem definidos, preservando a estabilidade de sua estrutura principal.

Key Takeaways

  • O systemd passa a permitir o uso de Rust para novos programas independentes (leaf components), mas manterá suas bibliotecas centrais e compartilhadas em C para garantir estabilidade e desempenho.
  • A razão principal é técnica: o Rust ainda não oferece uma ABI estável e suporte de primeira classe a bibliotecas compartilhadas, e compilar Rust estaticamente em muitos executáveis causaria duplicação e aumento de tamanho.
  • O processo de compilação seguirá unificado com Meson (não será introduzido o Cargo) e o suporte a Rust será opcional, permitindo que distribuições construam o systemd sem componentes em Rust.
  • Os componentes em Rust serão escritos preferencialmente em modo no_std e usarão implementações próprias de alocação e interfaces que encapsulam bibliotecas C para cumprir requisitos de segurança (ex.: manipulação de caminhos e descritores).
  • O projeto rejeita reescritas automáticas de código C: a adoção de Rust será conservadora e seletiva, visando preservar compatibilidade, evitar introdução de novos erros e só modificar arquitetura quando necessário.

Edivaldo Brito é analista de sistemas, gestor de TI, blogueiro e também um grande fã de sistemas operacionais, banco de dados, software livre, redes, programação, dispositivos móveis e tudo mais que envolve tecnologia.