Conceitos em Linux (IV)
4 - Muitos usuários:Uma das tarefas do Linux é gerenciar vários usuários. Para garantir a estabilidade do sistema, é necessário que haja pelo menos a separação entre o que um usuário comum pode fazer e o que é possível ao administrador. É também conveniente que vários usuários possam compartilhar recursos sem que um interfira com os recursos privativos de outro. Vejamos como o Linux implementa este tipo de separação.
Cada usuário possui um uid, um número que o identifica como apto a utilizar recursos e pertence a pelo menos um grupo, identificado por um número único no sistema (gid).
Num nível fundamental, a segurança de um sistema Linux e a privacidade dos seus usuários dependem dos privilégios de acesso dos usuários e seus grupos a cada arquivo. Para tanto, cada arquivo deve ter registrado (em seu i-node):
seu dono: o uid de quem o detém
seu grupo: o gid de quem o detém
os privilégios de seu dono
os privilégios de seu grupo
os privilégios dos outros usuários
Os privilégios podem ser:
direito de leitura
direito de escrita
direito de execução
acesso especial com set-uid
acesso especial com set-gid
acesso especial com stick-bit ativo
Isso é implementado com um campo de 12 bits listado abaixo:
set-uid
set-gid
stick-bit
dono – leitura
dono – gravação
dono – execução
grupo – leitura
grupo – gravação
grupo – execução
outros – leitura
outros – gravação
outros – execução
Podemos agrupá-los em 4 campos de três bits. Assim, as permissões de acesso especial ficam com o primeiro grupo, as do dono com o segundo, as do grupo com o terceiro e as de outros com o quarto. Com três bits, temos números que vão de 0 a 7. Desta forma, as permissões ficam:
100 = 4: set-uid
010 = 2: set-gid
001 = 1: stick-bit
100 = 4: dono – leitura
010 = 2: dono – gravação
001 = 1: dono – execução
100 = 4: grupo – leitura
010 = 2: grupo – gravação
001 = 1: grupo – execução
100 = 4: outros – leitura
010 = 2: outros – gravação
001 = 1: outros – execução
Podemos combinar as permissões tomando os valores intermediários, respeitando a representação binária. Por exemplo, tomando o campo do dono, podemos dar permissão de leitura e escrita fazendo 110 = 6 ou leitura e execução 101 = 5, ou tudo 111 = 7. Seguindo esta lógica, para dar acesso total ao dono, de leitura e execução para o grupo, leitura apenas para outros, sem acesso especial, escrevemos como: 0754.
Comentarei mais sobre privilégios adiante. Agora vejamos como é identificado um processo em execução, no tocante às permissões de acesso.
Quando um programa é carregado, ele é identificado por três valores de usuário:
ruid: o uid real, uid de quem chamou o processo e só pode ser alterado pelo superusuário;
euid: o uid efetivo, uid que é usado para avaliar os privilégios de acesso do usuário e pode ser alterado pelo superusuário para qualquer valor ou pelo usuário para os valores ruid ou suid;
suid: o uid salvo, geralmente o uid do dono (ruid) e pode ser alterado caso o bit set-uid esteja ativo no arquivo que contém o programa, situação na qual este valor passa a ser o uid do dono do arquivo e não o de quem o chamou.
Um tratamento análogo é feito para o grupo.
Esta é a utilidade dos bits set-uid e set-gid. Se ativarmos o bit set-uid em um arquivo executável (programa), o chamador poderá invocar eventualmente os privilégios do dono do programa. Para entender como isso se torna importante, vamos a dois exemplos.
Digamos que eu tenha um programa que grave CDs (cdrecord). Seria muito interessante se qualquer um que o chame tenha privilégios de superusuário, pois tal programa deve obter prioridade de execução de tempo real. Entretanto não é conveniente distribuir a senha de superusuário para todos os usuários certo? Alguém discorda? Isso pode ser resolvido marcando o arquivo cdrecord com set-uid ativo, sendo seu dono o superusuário (uid = 0).
Quando um usuário carregá-lo (digamos luiz, com uid = 500), suas permissões ficarão assim:
ruid = 500
euid = 500
suid = 0
Então o processo faz a chamada ao sistema seteuid(0), que tenta acertar o uid efetivo para 0. Como o suid é zero, isso é permitido e as permissões ficam:
ruid = 500
euid = 0
suid = 0
Como o euid é zero, o processo adquire todos os privilégios do superusuário, pois é este valor que é analisado para avaliar permissões.
Um exemplo importante é o programa “passwd”. É necessário que ele tenha privilégios administrativos para poder escrever no arquivo de senhas caso seja necessário alterá-las. Mas usuários comuns devem ser capazes de alterar as próprias senhas, o que torna o esquema anterior imprescindível ao processo de autenticação dos usuários.
Agora podemos ver com calma os tipos de privilégios. Para arquivos ordinários, podemos selecionar quem terá permissão para ler, escrever (alterar ou apagar) ou executar cada um em separado, selecionando os usuários por dono, grupo ou os que não se encaixam nestas categorias. É importante que outros não tenham acesso a seus arquivos, se deseja compartilhar algo, crie um grupo de compartilhamento, marque seu arquivo como pertencente a este grupo e peça às pessoas que querem acesso a estes arquivos para entrar neste grupo. Caso seu arquivo seja marcado com set-uid ou set-gid ativos, todos terão os privilégios do dono ou do grupo, respectivamente.
É interessante notar que diretórios são tratados como executáveis. Para abrir um diretório, é necessário que o usuário tenha permissão para execução.
Para executáveis, há ainda o stick-bit (em versões mais antigas, nas mais novas ele não tem efeito). Caso seja um diretório, o efeito de o stick-bit estar ativo é que usuários que têm permissão de escrita no diretório, ou seja, podem criar ou apagar arquivos, só podem apagar os arquivos dos quais sejam donos. Isso é particularmente útil em diretórios compartilhados, onde vários usuários possuem arquivos que não devem ser apagados por outros. No caso de um arquivo executável comum, o efeito do stick-bit ativo é que ao se carregar o programa, é feita uma cópia do seu texto na área de troca (swap), assim seu carregamento será muito mais rápido em uma próxima chamada. Resumindo:
set-uid: ajusta o uid salvo do processo para o do dono do arquivo, para que este possa ajustar seu uid efetivo, mudando seus privilégios;
set-gid: ajusta o gid salvo do processo para o do grupo do arquivo, para que este possa ajustar seu gid efetivo, mudando seus privilégios;
stick-bit: em diretórios impede que usuários com permissão de escrita apaguem arquivos que não lhe pertençam, em executáveis permitem que se salve uma cópia do texto do programa na área de troca.
Disso tudo torna-se claro que a segurança do sistema depende fundamentalmente das permissões de acesso a cada arquivo, diretório ou binário, principalmente quais programas têm ou não permissões especias e também do sistema de autenticação (sua intergridade adicionada a boas senhas). É importantíssimo que os usuários tenham consciência de que a segurança do sistema todo depende de quão boas são as senhas de todos. Só com este cuidado já é possível tornar um Linux minimamente seguro.
Para mais informações sobre implementação de segurança em sistemas operacionais de forma geral, leia “Sistemas Operacionais Modernos” (2ª ed.), por Andrew Tanenbaum (editora Prentice Hall).
Leia os sites de segurança:
linux security
linux security Brasil
Leia os sites de informação sobre Linux:
IBM Developer Works
Referência Debian
Para informações gerais sobre hardware, software e configurações relacionadas ao Linux continuo recomendando:
www.guiadohardware.net
www.vivaolinux.com.br
Para um excelente guia de comandos e configurações recomendo:
www.guiafoca.org
Próximo tópico: o padrão de hierarquia de sistema de arquivos

