Administração Linux

Usuários, grupos e permissões no Linux: bits rwx, umask, ACLs e sudo

Iniciante11 min de leituraAtualizado

Esta página foi traduzida do inglês com a ajuda de IA e conferida com o original. Ler a versão em inglês

Em uma máquina Linux, toda decisão de acesso se resume a um ID numérico de usuário, um conjunto de IDs de grupo e doze bits associados a um arquivo. Este guia mostra onde as contas ficam armazenadas, como o kernel avalia uma verificação de permissão e como ampliar ou restringir o acesso com segurança usando chmod, umask, ACLs e sudo. Ele termina com SSH baseado em chaves, o mecanismo de login que você deveria usar em qualquer servidor exposto à rede.

O que você vai aprender

  • Descrever como contas, grupos primários e grupos suplementares são armazenados e criados
  • Ler e definir modos de arquivo nas formas simbólica e octal, e prever o que o umask vai produzir
  • Explicar o que setuid, setgid e o sticky bit fazem e onde cada um tem uso legítimo
  • Conceder uma exceção a um usuário ou grupo específico com uma ACL POSIX em vez de afrouxar o modo
  • Delegar comandos administrativos com regras de sudo e fazer login com um par de chaves SSH

Permissões são a primeira coisa que um sistema Linux verifica e a última que a maioria das pessoas aprende direito. O modelo é pequeno o bastante para caber na cabeça — um ID numérico de usuário, uma lista de IDs de grupo e doze bits por arquivo —, mas é nos detalhes que você tropeça: por que um chmod 777 em um diretório web é ao mesmo tempo um problema de segurança e, em geral, nem sequer a solução; por que se adicionar ao grupo docker não tem efeito até você fazer logout; por que uma pasta compartilhada vive gerando arquivos que mais ninguém consegue editar.

Este guia começa pelas próprias contas, passa pelos bits rwx clássicos e pelos bits especiais acima deles e depois trata dos dois mecanismos a que você recorre quando o modelo clássico não é granular o suficiente: listas de controle de acesso e sudo. Os exemplos pressupõem um sistema Debian, Ubuntu ou da família RHEL atual. Se o formato de saída do ls -l ainda não é familiar, leia antes o guia sobre o sistema de arquivos.

Quem você é para o kernel

O kernel não conhece nomes de usuário. Ele conhece um ID de usuário (UID) e um conjunto de IDs de grupo (GIDs) associados a cada processo. Os nomes existem só para que pessoas consigam ler a saída; a tradução acontece em espaço de usuário, por meio de /etc/passwd, /etc/group e do serviço de diretório que a máquina estiver configurada para consultar.

$ id
uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo),110(www-data)

O /etc/passwd tem uma linha por conta, com campos separados por dois-pontos: nome, um x no lugar onde antes ficava o hash da senha, UID, GID primário, um campo de comentário livre, diretório home e shell de login. Ele é legível por todos porque muitos programas precisam mapear IDs para nomes.

alice:x:1000:1000:Alice Martin:/home/alice:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

Os hashes de senha de verdade ficam em /etc/shadow, legível apenas pelo root, junto com as informações de envelhecimento da senha: quando ela foi alterada pela última vez, validade mínima e máxima, período de aviso e data de expiração. Um ! ou * no campo do hash significa que nenhuma senha jamais vai corresponder, e é assim que contas de serviço são bloqueadas. Essas contas também recebem /usr/sbin/nologin como shell, para que nem uma autenticação bem-sucedida consiga abrir uma sessão interativa.

Na maioria das distribuições, UIDs abaixo de 1000 são reservados ao sistema; usuários humanos começam em 1000. O UID 0 é especial no próprio kernel: é o superusuário, e a maioria das verificações de permissão simplesmente é ignorada para ele.

Criando e modificando contas

sudo useradd -m -s /bin/bash -c "Bob Chen" bob   # -m creates and populates /home/bob
sudo passwd bob
sudo usermod -aG www-data,sudo bob               # -a is essential: append, do not replace
sudo usermod -L bob                              # lock the password
sudo userdel -r bob                              # -r also removes the home directory

Debian e Ubuntu também trazem o adduser, um wrapper interativo que escolhe padrões sensatos e pede a senha. Seja qual for a ferramenta, a flag mais importante é o -a no usermod -G: sem ela, a lista de grupos suplementares é substituída, e mais de um administrador já perdeu o acesso ao sudo desse jeito.

Diretórios home novos são preenchidos a partir de /etc/skel, então tudo o que você colocar ali — um .bashrc padrão, uma configuração de editor, um diretório .ssh com o modo certo — é copiado para cada conta criada depois.

Grupos primários e suplementares

Cada conta tem exatamente um grupo primário, registrado em /etc/passwd e usado como grupo dono dos arquivos que ela cria. Ela pode ainda pertencer a qualquer número de grupos suplementares, listados em /etc/group.

www-data:x:33:alice,bob
developers:x:1500:alice,bob,carol

A maioria das distribuições cria um grupo privado por usuário (alice:alice), de modo que um modo padrão 0644 não concede nada a mais ninguém, mesmo que o arquivo seja movido depois para uma área compartilhada. O acesso compartilhado passa então a ser expresso criando um grupo com nome que indique sua finalidade e adicionando membros a ele.

Como as credenciais são definidas no início da sessão, o id é a fonte da verdade sobre o que seus processos atuais podem fazer, enquanto /etc/group mostra o que o seu próximo login vai receber. Se você não puder fazer logout, newgrp developers abre um subshell com a nova participação.

Os doze bits

Todo arquivo tem um UID dono, um GID de grupo e um modo: três conjuntos de três bits, mais três bits especiais por cima.

BitEm um arquivo comumEm um diretório
rler o conteúdolistar os nomes que ele contém
wmodificar o conteúdocriar, renomear e excluir entradas
xexecutá-lo como programaatravessá-lo, ou seja, resolver nomes através dele

O kernel avalia em uma ordem rígida e para na primeira correspondência: se o seu UID é igual ao do dono, vale o trio do dono e nada mais é consultado; caso contrário, se algum dos seus GIDs corresponde ao grupo do arquivo, vale o trio do grupo; senão, vale o trio de outros. É por isso que ----rwxrwx nega tudo ao dono e libera para todos os demais — uma ordem que surpreende quem imagina que os conjuntos se somam.

Duas consequências decorrem da linha de diretórios da tabela. Primeiro, excluir um arquivo é uma escrita no diretório, não no arquivo, então você consegue remover um arquivo somente leitura de um diretório em que pode escrever. Segundo, x sem r em um diretório é um padrão útil: você consegue abrir /srv/data/report.pdf se souber o nome, mas não consegue listar o que existe ali.

Modos octais

Cada trio é um número de três bits: r=4, w=2, x=1. Basta somar.

OctalSimbólicoUso típico
644rw-r--r--arquivos comuns de dados e de configuração
600rw-------chaves privadas, credenciais, ~/.ssh/id_ed25519
755rwxr-xr-xprogramas, scripts e a maioria dos diretórios
750rwxr-x---um diretório compartilhado com um único grupo
775rwxrwxr-xum diretório em que um grupo pode escrever
700rwx------um diretório privado como ~/.ssh

O chmod aceita as duas formas. A simbólica é relativa e muitas vezes mais segura, porque altera apenas os bits que você nomeia:

chmod 640 /etc/myapp/secrets.env
chmod u+x deploy.sh          # add execute for the owner only
chmod go-w,o-rx /srv/private # remove group write, and all "other" access
chmod -R u=rwX,g=rX,o= /srv/app   # capital X: execute only where it is already set, or on directories

Vale guardar esse X maiúsculo: chmod -R 755 marca todos os arquivos de dados como executáveis, enquanto chmod -R u=rwX,go=rX corrige os diretórios sem mentir sobre quais arquivos são programas.

A posse é alterada com chown e chgrp, e só o root pode transferir um arquivo para outra pessoa:

sudo chown -R www-data:www-data /var/www/example.com
sudo chgrp developers /srv/shared
sudo chown --reference=/etc/nginx/nginx.conf /etc/nginx/conf.d/site.conf

umask: as permissões com que os arquivos nascem

Os programas pedem um modo ao criar um arquivo — por convenção, 0666 para dados e 0777 para diretórios. O umask do processo remove bits desse pedido antes de o arquivo ser criado. É uma máscara de bits a zerar, não a conceder.

Com o padrão comum 022, um arquivo novo recebe 0666 & ~022 = 0644 e um diretório novo 0777 & ~022 = 0755. Com umask 027, o mesmo arquivo vira 0640 e o diretório 0750, invisíveis para usuários de fora do grupo. Use umask 077 em uma máquina onde nada deve ser compartilhado por padrão.

$ umask
0022
$ umask 027; touch a; mkdir b; ls -ld a b
-rw-r-----  1 alice alice    0 Sep  7 11:20 a
drwxr-x---  2 alice alice 4096 Sep  7 11:20 b

Como o umask é uma propriedade do processo, ele é herdado pelos processos filhos e precisa ser definido onde o processo começa: em /etc/profile ou ~/.profile para shells de login, com uma diretiva UMask= em um serviço do systemd ou na configuração do próprio daemon. Observe que arquivos nunca recebem o bit de execução a partir de um pedido 0666, e é por isso que um script extraído de um arquivo compactado tantas vezes precisa de um chmod +x explícito.

setuid, setgid e o sticky bit

Acima dos nove bits de permissão ficam mais três, exibidos nas posições x do ls -l.

setuid (4000, um s no trio do dono) faz um executável rodar com os privilégios do seu dono, e não de quem o chama. /usr/bin/passwd é o exemplo clássico: um usuário sem privilégios precisa conseguir reescrever uma linha de /etc/shadow, e o setuid root é o que torna isso possível. O setuid é poderoso e historicamente foi a origem de muitas escalações de privilégio locais, então o lugar dele é nos binários da distribuição e praticamente em nenhum outro. Procurar surpresas cabe em uma linha:

sudo find / -xdev -type f -perm -4000 -printf '%M %u %p\n' 2>/dev/null

setgid (2000) faz o mesmo com o grupo em um executável, mas sua forma mais útil é em um diretório: arquivos criados dentro dele herdam o grupo do diretório em vez do grupo primário de quem os criou, e novos subdiretórios também herdam o bit setgid. É a receita padrão para uma área de projeto compartilhada.

sudo install -d -o root -g developers -m 2775 /srv/projects

O sticky bit (1000, um t no trio de outros) faz com que, em um diretório gravável por todos, só o dono de cada arquivo possa apagá-lo. O /tmp é drwxrwxrwt exatamente por isso: qualquer um pode criar arquivos ali, ninguém pode apagar os de outra pessoa.

chmod 2775 /srv/projects   # setgid directory
chmod 1777 /srv/scratch    # sticky, world-writable
chmod g+s,o-rwx /srv/team  # symbolic equivalents

Diretórios setgid fixam o grupo, mas não o modo, então um membro que cria um arquivo com umask 022 ainda produz rw-r--r--, que os colegas não conseguem editar. Combine o bit setgid com umask 002 para os usuários envolvidos ou use uma ACL, que é a melhor resposta.

ACLs, quando três conjuntos não bastam

Uma lista de controle de acesso (ACL) POSIX associa a um arquivo entradas nomeadas de usuários e grupos, para que você possa dar acesso a mais uma pessoa sem inventar um grupo nem afrouxar other. O sistema de arquivos precisa estar montado com suporte a ACL, o que é o padrão para ext4 e XFS nos kernels atuais.

$ setfacl -m u:jenkins:rx /srv/app/bin
$ setfacl -m g:auditors:r /var/log/app/audit.log
$ getfacl /srv/app/bin
# file: srv/app/bin
# owner: deploy
# group: deploy
user::rwx
user:jenkins:r-x
group::r-x
mask::r-x
other::---

O ls -l marca um arquivo que tem ACL com um + no final. A entrada mask é um teto para todas as entradas nomeadas e para a classe de grupo; em um arquivo com ACL, chmod g= ajusta a máscara e não a entrada do grupo, o que explica a confusão ocasional do tipo “eu concedi e continua sem funcionar”.

As ACLs padrão de um diretório são o mecanismo de herança que falta aos bits clássicos. Elas se aplicam às entradas criadas depois, então um usuário de deploy pode manter acesso de escrita a tudo o que um build colocar em uma árvore:

sudo setfacl -R -m u:deploy:rwx -m d:u:deploy:rwx /var/www/example.com
sudo setfacl -x u:jenkins /srv/app/bin     # remove one entry
sudo setfacl -b /srv/app/bin               # remove the whole ACL

Use ACLs de forma deliberada e documente-as. Em um ls -l simples, nada as denuncia além daquele +, e um enigma de permissões que ninguém consegue explicar é pior do que um grupo meio desajeitado.

Delegando privilégios com sudo

A prática moderna é desativar o login direto como root e conceder privilégios específicos por meio do sudo. A política fica em /etc/sudoers e, de preferência, em arquivos dentro de /etc/sudoers.d/. Edite sempre com o visudo, que valida a sintaxe antes de instalar o arquivo.

# /etc/sudoers.d/deploy   (mode 0440, edited with: sudo visudo -f /etc/sudoers.d/deploy)
Cmnd_Alias APPCTL = /usr/bin/systemctl restart app, /usr/bin/systemctl status app

%developers ALL=(ALL) APPCTL
deploy      ALL=(www-data) NOPASSWD: /usr/bin/rsync

Leia uma regra como quem host=(como quem) o quê. A primeira linha permite que membros do grupo developers reiniciem um serviço depois de digitar a própria senha. A segunda permite que a conta deploy rode rsync como www-data sem senha, que é exatamente do que um pipeline automatizado precisa.

Dois hábitos mantêm o sudo sob controle. Conceda comandos, não shells: %developers ALL=(ALL) NOPASSWD: ALL é acesso root com passos extras, e qualquer comando permitido que consiga abrir um shell ou editar um arquivo arbitrário (vi, less, find, tar) equivale a root completo. E preserve o log: cada invocação é registrada no journal ou no syslog, o que faz do journalctl -t sudo uma trilha de auditoria realmente útil, como mostra o guia de logs e solução de problemas.

Fazendo login com chaves em vez de senhas

A autenticação SSH por senha atrai ataques de força bruta a partir do momento em que uma máquina ganha um endereço público. Pares de chaves eliminam por completo o segredo que dá para adivinhar.

ssh-keygen -t ed25519 -C "alice@laptop"        # private key stays on your machine
ssh-copy-id [email protected]           # appends the public key remotely
ssh -o PreferredAuthentications=publickey [email protected]

A chave privada precisa ter modo 600 e o diretório ~/.ssh, 700; o sshd recusa chaves legíveis pelo grupo ou por todos, e recusa o authorized_keys se o próprio diretório home for gravável pelo grupo. Quando todas as contas que precisam de acesso tiverem uma chave, faça o hardening do daemon em /etc/ssh/sshd_config.d/:

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
AllowGroups sshusers

Valide com sudo sshd -t e faça reload em vez de restart, e — esta é a parte que o pessoal pula — mantenha sua sessão atual aberta enquanto testa uma nova a partir de outro terminal. Um erro de digitação no sshd_config de uma máquina remota é, na melhor das hipóteses, um chamado de suporte.

Erros comuns

chmod 777 como passo de depuração. Dá acesso de escrita a todos os usuários da máquina e raramente resolve o problema real, que costuma ser um dono errado ou um x faltando em um diretório pai. Encontre o ponto do caminho que falha com namei -l /var/www/example.com/index.php.

usermod -G sem -a. Remove silenciosamente todos os outros grupos suplementares, incluindo sudo e wheel.

chmod recursivo com modo numérico. chmod -R 755 torna executáveis todos os arquivos de configuração e imagens. Use u=rwX,go=rX, ou find … -type d -exec chmod 755 e -type f -exec chmod 644.

Achar que permissões protegem o histórico de um arquivo. Restringir um modo não faz nada pelas cópias já feitas, e um segredo que entrou em um commit no Git ou foi gravado em uma imagem de contêiner continua lá. Faça a rotação dele.

Esquecer que o root ignora os bits. Um modo somente leitura não protege contra um processo root, nem dentro de um contêiner que roda como root com o caminho montado via bind mount.

Mudanças de grupo sem uma nova sessão. O id reflete a sessão; confira ali antes de concluir que o grupo não fez efeito.

Principais pontos

  • O kernel autoriza por UID e GID; os nomes vêm de /etc/passwd e /etc/group, e os hashes e a expiração, de /etc/shadow.
  • As verificações de permissão param na primeira classe correspondente — dono, depois grupo, depois outros —, então os trios nunca se somam.
  • Em diretórios, x significa atravessar e w significa criar ou excluir, e é por isso que dá para apagar um arquivo somente leitura e que um x faltando quebra um caminho inteiro.
  • O umask subtrai bits no momento da criação; defina-o no perfil de login ou em uma unit de serviço, não a posteriori.
  • setgid em um diretório resolve a herança de grupo, o sticky bit protege diretórios graváveis por todos e o setuid pertence quase exclusivamente aos binários da distribuição.
  • Recorra a uma ACL POSIX, com uma entrada padrão para herança, quando um usuário ou grupo precisar de uma exceção; recorra a regras de sudo limitadas a comandos específicos quando uma pessoa precisar de privilégios.
  • Troque as senhas do SSH por pares de chaves, depois desative PasswordAuthentication e verifique a partir de uma segunda sessão antes de fechar a primeira.

Fontes e leituras complementares

Perguntas frequentes

Por que não consigo entrar em um diretório mesmo que os arquivos dele sejam legíveis?
Diretórios usam o bit de execução de outro jeito: x significa o direito de atravessar o diretório, ou seja, de resolver um nome dentro dele. Sem x em cada diretório do caminho, o kernel para antes mesmo de olhar o arquivo. Um diretório com r mas sem x permite listar os nomes, mas não fazer stat nem abrir nada, e é por isso que 0644 em um diretório quase sempre é um erro.
Eu me adicionei a um grupo, mas continuo recebendo “permission denied”. O que está errado?
A participação em grupos é copiada para as credenciais do processo no momento do login. Seu shell atual foi iniciado antes da mudança, então ainda carrega a lista antiga. Faça logout e login de novo, abra uma nova sessão ou rode newgrp nomedogrupo no shell em que você está. Confira a lista efetiva com o comando id, e não lendo /etc/group, porque o kernel usa o que foi atribuído à sua sessão.
Devo editar o /etc/sudoers diretamente?
Não. Use o visudo, que bloqueia o arquivo e se recusa a instalar uma versão que não passe na verificação de sintaxe. Um arquivo sudoers malformado pode impedir que qualquer administrador eleve privilégios naquela máquina. Melhor ainda: coloque um arquivo pequeno em /etc/sudoers.d/ e edite-o com visudo -f, assim as atualizações de pacotes nunca entram em conflito com suas regras e cada delegação fica em seu próprio arquivo.
Qual é a diferença entre su e sudo?
O su abre um shell como outro usuário e pede a senha desse usuário, então quem o usa precisa das credenciais da conta de destino. O sudo executa um único comando segundo uma política guardada em /etc/sudoers, autentica com a senha de quem o chama e registra cada execução. O sudo permite delegar com precisão e auditar depois, e é por isso que a maioria das distribuições hoje desativa completamente o login direto como root.