Permissões de Arquivo e Diretório no Linux

IDs de Processo

Processos no Linux estão associados a vários IDs que determinam suas identidades e privilégios:

  • ID de Usuário Real (UID Real) / ID de Grupo Real: Representa o usuário e grupo que iniciaram o processo.
  • ID de Usuário Efetivo (UID Efetivo) / ID de Grupo Efetivo: Usado pelo sistema operacional para verificar permissões de acesso a arquivos. Geralmente coincide com os IDs reais, mas pode mudar para conceder privilégios temporários.
  • ID de Usuário Salvo (Saved UID) / ID de Grupo Salvo (Saved GID): Cópias dos UIDs efetivos, mantidos após a execução de um programa via chamadas exec. A disponibilidade desses IDs salvos depende da implementação do sistema (verificável com \_POSIX\_SAVED\_IDS).

A diferença entre UIDs reais e efetivos é crucial para operações privilegiadas. Por exemplo, o comando passwd permite que usuários comuns modifiquem suas senhas, embora o arquivo /etc/passwd seja protegido e só possa ser escrito pelo root. Isso é possível porque o programa passwd é executado com um UID efetivo de root, permitindo a modificação do arquivo.

Bit de Set-User-ID (SUID) em Arquivos

O bit SUID é um atributo de arquivo que, quando definido em um arquivo executável, faz com que o UID efetivo do processo que executa o arquivo seja definido para o UID do proprietário do arquivo. Isso é visível na listagem de arquivos como 's' em vez de 'x' para o proprietário.


$ ll /usr/bin/passwd
-rwsr-xr-x. 1 root root 30768 Feb 22  2012 /usr/bin/passwd
 

Exemplo demonstrando a mudança do UID efetivo:


#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

int main() {
   printf("UID Real = %d\n", getuid());
   printf("UID Efetivo = %d\n", geteuid());
   return 0;
}
 

Execução sem SUID (UID real e efetivo iguais):


user@host$ ./my_program
UID Real = 1000
UID Efetivo = 1000
 

Após configurar SUID para o proprietário root e executar como usuário comum:


user@host$ su
Password:
root# chown root my_program
root# chmod u+s my_program
root# ll my_program
-rwsr-xr-x  1 root   user  9809 2016-12-21 22:20 my_program
root# exit
user@host$ ./my_program
UID Real = 1000
UID Efetivo = 0
 

Propriedade de Novos Arquivos e Diretórios

Ao criar um novo arquivo:

  • O UID do novo arquivo é definido como o UID efetivo do processo criador.
  • O GID do novo arquivo pode ser:
    • O GID efetivo do processo criador.
    • O GID do diretório onde o arquivo está sendo criado.

Novos diretórios seguem as mesmas regras de propriedade.

Funções chmod e fchmod

Essas funções permitem modificar as permissões de acesso de arquivos existentes.


#include <sys/types.h>
#include <sys/stat.h>

int chmod(const char *pathname, mode_t mode);
int fchmod(int filedes, mode_t mode); // filedes é o descritor de arquivo
 

O retorno é 0 em caso de sucesso e -1 em caso de erro.

Para alterar as permissões de um arquivo, o UID efetivo do procseso deve corresponder ao proprietário do arquivo, ou o processo deve ter privilégios de root.

O parâmetro mode é construído usando operadores bitwise OR com as seguintes constantes (definidas em <sys>):

  • S_ISUID: Bit Set-User-ID
  • S_ISGID: Bit Set-Group-ID
  • S_ISVTX: Sticky Bit
  • S_IRWXU: Permissões de leitura, escrita e execução para o proprietário
  • S_IRUSR: Permissão de leitura para o proprietário
  • S_IWUSR: Permissão de escrita para o proprietário
  • S_IXUSR: Permissão de execução para o proprietário
  • S_IRWXG: Permissões de leitura, escrita e execução para o grupo
  • S_IRGRP: Permissão de leitura para o grupo
  • S_IWGRP: Permissão de escrita para o grupo
  • S_IXGRP: Permissão de execução para o grupo
  • S_IRWXO: Permissões de leitura, escrita e execução para outros
  • S_IROTH: Permissão de leitura para outros
  • S_IWOTH: Permissão de escrita para outros
  • S_IXOTH: Permissão de execução para outros

Exemplo de uso:


#include <stdio.h>
#include <sys/stat.h>

int main(void) {
   struct stat statbuf;

   // Verifica o estado do arquivo "foo"
   if (stat("foo", &statbuf) < 0) {
       fprintf(stderr, "Erro ao obter status do arquivo foo\n");
       return 1;
   }

   // Modifica as permissões de "foo", adicionando S_ISGID e mantendo outras permissões
   // (statbuf.st_mode & ~S_IXGRP) remove a permissão de execução do grupo
   if (chmod("foo", (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0) {
       fprintf(stderr, "Erro ao alterar permissões de foo\n");
       return 1;
   }

   // Define permissões absolutas para "bar" como "rw-r--r--"
   if (chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
       fprintf(stderr, "Erro ao alterar permissões de bar\n");
       return 1;
   }

   return 0;
}
 

Sticky Bit

O Sticky Bit (S_ISVTX) em versões antigas do UNIX era usado em arquivos executáveis para manter uma cópia do texto do programa na área de troca (swap area) após a primeira execução, acelerando execuções subsequentes. Sistemas modernos com memória virtual e sistemas de arquivos rápidos não necessitam mais dessa funcionalidade para executáveis.

Em diretórios, o Sticky Bit tem uma função importante: quando definido, apenas o proprietário do arquivo, o proprietário do diretório ou o superusuário podem excluir ou renomear arquivos dentro desse diretório, mesmo que outros usuários tenham permissão de escrita no diretório.

Diretórios como /tmp e /var/spool/uucppublic frequentemente utilizam o Sticky Bit para permitir que qualquer usuário crie arquivos, mas impeça que usuários excluam ou renomeiem arquivos de outros.

Funções chown, fchown e lchown

Essas funções alteram o proprietário (UID) e o grupo (GID) de um arquivo.


#include <sys/types.h>
#include <unistd.h>

int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int filedes, uid_t owner, gid_t group);
int lchown(const char *pathname, uid_t owner, gid_t group); // Altera o proprietário do link simbólico, não do alvo
 

O retorno é 0 em caso de sucesso e -1 em caso de erro.

A capacidade de um usuário comum alterar o proprietário de um arquivo é restrita (definida por \_POSIX\_CHOWN\_RESTRICTED). Se essa restrição estiver ativa:

  • Apenas o superusuário pode alterar o UID de um arquivo.
  • Um usuário não-root pode alterar o GID de um arquivo que possui, mas apenas para um dos seus GIDs efetivos ou de grupo adicionais.

Se essas funções forem chamadas por um processo não-root e retornarem com sucesso, os bits SUID e SGID do arquivo serão automaticamente desativados.

Comprimento do Arquivo

O membro st\_size da estrutura stat contém o comprimento do arquivo em bytes. Este campo é significativo para arquivos regulares, diretórios e links simbólicos.

  • Para diretórios, st\_size é um múltiplo de um valor específico (como 16 ou 512).
  • Para links simbólicos, st\_size é o comprimento do nome do arquivo alvo.

Truncamento de Arquivo

As funções truncate e ftruncate podem ser usadas para encurtar um arquivo para um tamanho especificado (length).


#include <sys/types.h>
#include <unistd.h>

int truncate(const char *pathname, off_t length);
int ftruncate(int filedes, off_t length);
 

Se o comprimento original do arquivo for maior que length, os dados excedentes são descartados. Se o comprimento original for menor, o comportamento depende do sistema; alguns sistemas expandem o arquivo e preenchem o espaço adicional com zeros.

Sistemas de Arquivos e Inodes

Sistemas de arquivos tradicionais (como o System V) organizam o armazenamento em discos usando partições, cada uma contendo um sistema de arquivos.

  • Inode: Uma estrutura de dados de tamanho fixo que contém metadados sobre um arquivo (tipo, permissões, tamanho, ponteiros para blocos de dados).
  • Contagem de Links (st\_nlink): Cada inode possui uma contagem de links. Um link (hard link) é uma entrada de diretório que aponta para um inode. Um arquivo só é removido (e seus blocos de dados liberados) quando sua contagem de links chega a zero. O número máximo de links é definido por LINK\_MAX.
  • Link Simbólico (Symbolic Link): Um tipo especial de arquivo cujo conteúdo é o nome de outro arquivo.
  • Entrada de Diretório: Contém o nome do arquivo e o número do inode correspondente. Entradas de diretório só podem apontar para inodes dentro do mesmo sistema de arquivos.
  • Renomear Arquivo: Renomear um arquivo dentro do mesmo sistema de arquivos simplesmente cria uma nova entrada de diretório apontanod para o mesmo inode existente, sem mover os dados do arquivo.

Contagem de Links em Diretórios

A contgaem de links em diretórios é especial:

  • Um diretório vazio (folha) tem uma contagem de links de 2: uma para a entrada que o nomeia e uma para a entrada . dentro dele.
  • Um diretório que contém subdiretórios tem uma contagem de links de pelo menos 3: a entrada que o nomeia, a entrada . dentro dele e a entrada .. em cada subdiretório.

Tags: Linux permissões arquivos diretórios inodes

Publicado em 7-25 12:37