SSD Nodes Learn 🎉 VPS desde $5.50/mês
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-13

sudo-rs no Ubuntu 26.04: mudanças no sudoers

No Ubuntu 26.04, o sudo-rs deixa curingas nos argumentos sem correspondência. Veja a regra afetada e a sintaxe que deve usar no sudoers.

O que o sudo-rs altera no Ubuntu

O Ubuntu 26.04 LTS inclui o sudo-rs como sudo predefinido. Por isso, o comando sudo num servidor novo executa a reimplementação em Rust em vez do programa original em C. A maioria dos ficheiros sudoers continua a funcionar exatamente como antes. A regra que deixa de funcionar é a que contém um curinga nos argumentos de um comando, porque o sudo-rs não compara padrões glob com o texto dos argumentos.

O Ubuntu 25.10 fez a mudança primeiro, e o 26.04 LTS manteve-a. O Ubuntu 24.04 LTS não é afetado, porque continua a selecionar o sudo original, a menos que instale o sudo-rs manualmente. Isto passa a ser relevante quando atualiza do Ubuntu 24.04 para o 26.04, ou quando instala um servidor novo na versão mais recente. Se também utiliza versões intermédias, como as versões LTS e intermédias do Ubuntu diferem num servidor explica qual das máquinas recebe primeiro uma alteração deste tipo.

Verifique qual sudo o servidor está realmente a executar

Não deduza isso pelo número da versão. Consulte a própria máquina.

sudo --version
update-alternatives --config sudo
dpkg -l 'sudo*'

Confie em sudo --version no seu próprio sistema, e não em qualquer tabela de versões na Internet, incluindo esta página. update-alternatives --config sudo é a outra metade da resposta: apresenta todos os fornecedores instalados de /usr/bin/sudo e assinala o selecionado. Ter um pacote instalado não significa que ele esteja selecionado. Leia a seleção, não a lista de pacotes.

As duas implementações são empacotadas durante a transição. A versão em Rust é sudo-rs, na versão 0.2.13 em 26.04, em agosto de 2026. A original, mantida por Todd C. Miller, é empacotada como sudo.ws, e os respetivos programas têm o sufixo .ws: sudo.ws e visudo.ws.

Por que o Ubuntu mudou para sudo-rs

sudo usa setuid root. Qualquer utilizador no sistema pode iniciá-lo, e ele começa com privilégios completos. Por isso, um erro de memória no seu interior pode permitir uma exploração local para obter root. O CVE-2021-3156 foi exatamente isso: um overflow de buffer no heap acessível a qualquer utilizador local. O problema permaneceu no código distribuído durante cerca de dez anos. O Rust deteta essa classe de erro em tempo de compilação. Esse é o principal argumento para a reescrita.

A segunda razão é o âmbito. É também a razão que afeta a sua configuração. O sudo original acumulou um conjunto extenso de funcionalidades ao longo de três décadas. Cada funcionalidade representa mais código executado como root. O sudo-rs implementa deliberadamente apenas um subconjunto. As funcionalidades consideradas pouco comuns ou potencialmente prejudiciais pelos seus autores foram excluídas. Por isso, uma construção do sudoers que funcionou durante anos pode simplesmente não existir. A sua regra com wildcard é uma delas.

A segurança da memória elimina uma classe de erros. Não torna um programa livre de erros. O sudo-rs também recebeu correções de segurança próprias desde que se tornou o padrão. Aplique-lhe patches como a qualquer outro software.

Quais regras do sudoers continuam a funcionar

O ficheiro é o mesmo. O sudo-rs lê /etc/sudoers e os ficheiros adicionais em /etc/sudoers.d/, e as configurações habituais usadas por um operador de servidor são suportadas:

  • deploy ALL=(ALL:ALL) ALL e formas para grupos, como %sudo ALL=(ALL:ALL) ALL
  • as etiquetas NOPASSWD: e PASSWD:
  • User_Alias, Runas_Alias, Host_Alias e Cmnd_Alias
  • um comando com uma lista exata de argumentos, por exemplo /usr/bin/systemctl restart app-api
  • um comando seguido de "", que permite o comando apenas sem argumentos
  • um comando seguido de * como argumento final, que permite quaisquer argumentos adicionais
  • um caminho de diretório terminado em /, que permite qualquer comando nesse diretório
  • ! para retirar um comando de uma lista
  • um subconjunto útil de Defaults, incluindo secure_path, env_keep, env_check, timestamp_timeout, passwd_tries, editor, umask, targetpw, rootpw e use_pty

Dois valores predefinidos comportam-se de forma diferente e podem causar problemas. env_reset não pode ser desativado no sudo-rs: está sempre ativo. use_pty está ativo por predefinição, pelo que o comando é executado no seu próprio pseudo-terminal.

Por que a regra curinga do sudoers deixou de corresponder

Os curingas continuam permitidos num único lugar: no nome do ficheiro do comando. Uma regra com %ops ALL = /sbin/fsck* ainda permite sudo fsck e sudo fsck_exfat, porque * faz parte do caminho comparado com o sistema de ficheiros.

Dentro da lista de argumentos, o sudo-rs aceita apenas duas formas especiais, e nenhuma delas é um padrão. "" significa que não existem argumentos. Um * final significa quaisquer argumentos adicionais. Todos os outros argumentos são comparados como texto literal. Por isso, %ops ALL = /sbin/service ntp * funciona: ntp é literal e * é o último argumento. No entanto, uma regra como esta não concede nenhuma das permissões pretendidas:

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*

app-* é um padrão no meio de um argumento. O sudo-rs não o expande, portanto a regra não abrange systemctl restart app-api e o sudo recusa o comando. Dois comandos mostram a realidade de qualquer regra no seu servidor: sudo -l -U deploy, executado como root, apresenta o que essa conta pode realmente executar, e sudo visudo -c indica se o ficheiro é sequer analisado corretamente. Execute-os antes de começar a editar ficheiros ao acaso.

A regra com curinga sempre teve uma falha

No sudo original, os argumentos introduzidos são unidos numa única string e comparados com a string de argumentos da regra usando um glob. Um glob corresponde a espaços em branco. Esta é a parte que quase toda a gente não percebe.

A documentação do sudo-rs apresenta a demonstração mais clara. Uma regra de /bin/rm *.txt também permite sudo rm -rf /home .txt, porque o único * absorve -rf /home e a string unida continua a terminar em .txt. A regra é interpretada como “apenas ficheiros de texto”. Na prática, significa “quaisquer argumentos, desde que a linha termine em .txt”.

O mesmo se aplica ao exemplo com systemctl. Como os argumentos são comparados como uma única string unida, um padrão no fim também corresponde ao que for acrescentado depois. Assim, restart app-* permite restart app-api e quaisquer argumentos adicionais introduzidos pelo utilizador. Um padrão dentro de um argumento expõe os argumentos que estão à sua volta, e é nos argumentos que reside a capacidade de um comando. O sudo-rs recusa esta construção em vez de tentar torná-la segura, porque não existe uma forma geral e segura de a utilizar.

Substitua o curinga por uma lista explícita de comandos

A maioria das regras com curingas existe porque alguém não queria escrever quatro linhas. Escreva as quatro linhas.

Cmnd_Alias APP_RESTART = /usr/bin/systemctl restart app-api, /usr/bin/systemctl restart app-worker
Cmnd_Alias APP_STATUS = /usr/bin/systemctl status app-api, /usr/bin/systemctl status app-worker
deploy ALL=(root) NOPASSWD: APP_RESTART, APP_STATUS

Use o caminho correto. Uma regra que especifica /bin/systemctl num sistema onde o binário está em /usr/bin/systemctl nunca corresponde, e a falha parece idêntica a um problema de permissões. Confirme com command -v systemctl e cole o resultado.

Coloque a regra no seu próprio ficheiro drop-in, em vez de a colocar em /etc/sudoers. Assim, uma atualização do pacote nunca entra em conflito com a sua edição:

sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deploy

Dê ao ficheiro um nome sem ponto e sem til no final. O sudo original ignora os ficheiros em sudoers.d cujos nomes contêm um ponto. Por isso, 90-deploy.conf é um erro clássico que não produz qualquer efeito visível. Não há motivo para não seguir esta convenção.

Use um wrapper pertencente a root quando a lista ficar longa

Quando o conjunto permitido for demasiado grande para ser listado, transfira a decisão para fora do sudoers e coloque-a num pequeno programa pertencente a root.

sudo tee /usr/local/sbin/app-restart >/dev/null <<'EOF'
#!/bin/sh
set -eu
case "${1:-}" in
  app-api|app-worker) ;;
  *) echo "app-restart: not allowed: ${1:-}" >&2; exit 1 ;;
esac
exec /usr/bin/systemctl restart "$1"
EOF
sudo chown root:root /usr/local/sbin/app-restart
sudo chmod 0755 /usr/local/sbin/app-restart
ls -l /usr/local/sbin/app-restart

No lado do sudoers, indique apenas um comando:

deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *

O * no final é aceitável neste caso porque é o script, e não o sudo, que decide o que é permitido. Isto só é válido enquanto o script pertencer a root e não puder ser escrito por mais ninguém. Se deploy puder escrever no ficheiro, deploy poderá substituir o seu conteúdo e executar qualquer coisa como root, o que é pior do que a regra com wildcard que removeu. Verifique o modo com ls -l e, se o resultado não for evidente, aprender a interpretar a string de permissões drwxr-xr-x demora cinco minutos. A mesma regra aplica-se ao diretório: /usr/local/sbin também não pode ser gravável pela conta, porque um diretório gravável permite substituir o ficheiro por completo.

Dê ao job uma conta própria em vez de uma regra do sudo

A melhor pergunta costuma ser por que motivo o comando precisa de root. Um serviço executado pelo seu próprio utilizador pode ser gerido por esse utilizador, sem envolver nenhuma linha do sudoers. Para unidades do sistema, o systemd já delega essa decisão ao polkit. Assim, uma regra pode indicar uma unidade e um operador:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        action.lookup("unit") == "app-api.service" &&
        subject.user == "deploy") {
        return polkit.Result.YES;
    }
});

Guarde isso como /etc/polkit-1/rules.d/50-app-api.rules, e deploy poderá executar systemctl restart app-api sem usar sudo. Teste a partir do contexto exato que o utilizará, porque uma regra que funciona na sua sessão SSH deve ser confirmada a partir do cron antes de depender dela. Em qualquer caso, a conta que executa o trabalho deve existir exclusivamente para esse fim. Esse é o mesmo princípio por trás das contas de utilizador com privilégio mínimo num VPS.

O que o sudo-rs não inclui

sudo -E não está implementado. Declare as variáveis necessárias com Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" e lembre-se de que env_reset está sempre ativo, portanto tudo o que não for mantido é limpo.

O armazenamento central de sudoers em LDAP foi removido. sudoers.ldap e cvtsudoers não estão implementados, e o pacote sudo-ldap foi removido no 26.04. A autenticação LDAP através de PAM ou SSSD continua a funcionar. O que está fora do âmbito é a política armazenada num diretório.

INTERCEPT, que tentava impedir escapes para a shell a partir de um comando permitido, não está implementado. Mesmo assim, nunca resistiu a um utilizador determinado. Se uma regra permite executar um editor ou um interpretador como root, esse utilizador tem acesso root, e nenhuma opção do sudo altera isso.

A gravação de sessões não está implementada. Por isso, não existe um log de I/O nem sudoreplay. O registo é enviado apenas para o syslog, e não existe a opção logfile para o redirecionar para outro local. Assim, as mensagens do sudo vão para o destino onde o sistema já envia o syslog.

Deve voltar para sudo.ws?

Pode fazê-lo e, durante o ciclo 26.04, o original continua incluído no pacote exatamente por esse motivo.

sudo apt install sudo.ws
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.ws

Copie os caminhos exatos da saída de --config, em vez de os copiar desta página, porque essa é a lista que o seu próprio sistema aceitará. Para voltar a usar sudo-rs mais tarde, defina a alternativa para o caminho do binário sudo-rs indicado na mesma lista.

Mantenha uma segunda sessão SSH aberta, autenticada e inativa antes de alterar qualquer coisa que afete o sudo. Um ficheiro sudoers que não possa ser analisado ou uma alternativa que aponte para um binário não instalado pode deixá-lo sem forma de obter root num sistema remoto. Este procedimento deve fazer parte de tudo o que faz nos primeiros dez minutos num novo VPS.

Trate o regresso como um prazo, não como uma correção. Isso dá-lhe uma semana para reescrever as regras corretamente. A reescrita vale a pena por si só, porque cada regra com wildcard que eliminar estava a conceder mais permissões do que o autor tinha previsto.

FAQ

Porque é que a regra wildcard do sudoers deixou de funcionar no Ubuntu 26.04?

Porque o Ubuntu 26.04 LTS seleciona o sudo-rs como sudo predefinido, e o sudo-rs não corresponde a padrões wildcard dentro dos argumentos de um comando. Permite um wildcard no nome de ficheiro do comando, "" para indicar que não existem argumentos, e um único * como argumento final. Uma regra como /usr/bin/systemctl restart app-* coloca um padrão no meio de um argumento, por isso não concede permissões e o comando é recusado. Execute sudo -l -U deploy como root para ver as permissões efetivas da conta e substitua depois a regra pelos comandos exatos ou por um script wrapper pertencente a root.

Como volto ao sudo original no Ubuntu 26.04?

O original é disponibilizado pelo pacote sudo.ws. Instale-o com sudo apt install sudo.ws e aponte a alternativa para ele com sudo update-alternatives --set sudo /usr/bin/sudo.ws. Execute primeiro update-alternatives --config sudo para consultar os caminhos exatos disponibilizados pelo sistema e mantenha uma segunda sessão SSH aberta enquanto faz a alteração. Isto não repõe sudo-ldap, que foi removido do 26.04 independentemente da implementação selecionada.

O sudo-rs lê o mesmo ficheiro /etc/sudoers?

Sim. O sudo-rs lê /etc/sudoers e os ficheiros adicionais em /etc/sudoers.d/, com a mesma sintaxe para utilizadores, grupos, aliases, especificações run-as e a tag NOPASSWD. Implementa um subconjunto da linguagem sudoers, por isso as diferenças aparecem como construções em falta, e não como construções com comportamento diferente. Edite com sudo visudo e valide com sudo visudo -c antes de fechar a sessão.

O que substitui sudo -E no sudo-rs?

sudo -E não está implementado e já era desaconselhado no sudo original, porque entregar a um processo root um ambiente controlado pelo chamador é uma forma conhecida de alterar o comportamento desse processo. Indique no sudoers as variáveis de que realmente precisa, com uma linha como Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". env_reset está sempre ativo no sudo-rs e não pode ser desativado, por isso todas as variáveis que não conservar são limpas.

#sudo#sudo-rs#ubuntu#sudoers#permissions