O que é um sistema operacional baseado em capacidades
Os sistemas operacionais modernos impõem limites de segurança entre processos, arquivos, dispositivos e usuários. No entanto, a forma como esses limites são implementados varia significativamente entre diferentes projetos de sistema.
A maioria dos sistemas operacionais convencionais depende de controle de acesso baseado em identidade e de espaços de nomes globais. Sistemas operacionais baseados em capacidades adotam uma abordagem fundamentalmente diferente: representam a autoridade explicitamente e a tornam um conceito de primeira classe.
Este artigo apresenta sistemas baseados em capacidades, explica como eles diferem de modelos tradicionais e descreve por que são centrais para o design do EriX.
O problema: autoridade ambiente⌗
Em sistemas tradicionais, processos frequentemente têm acesso a recursos por meio de autoridade ambiente.
Autoridade ambiente significa que um programa pode acessar um recurso simplesmente porque ele existe em um espaço de nomes compartilhado e o sistema determina que o programa tem permissão para usá-lo.
Por exemplo:
- Um processo pode abrir
/etc/passwdse tiver permissões suficientes. - Um programa pode se conectar a um socket de rede se o sistema operacional permitir.
- Um serviço pode acessar arquivos com base na identidade do usuário ou na associação a grupos.
Em todos esses casos, a autoridade para acessar o recurso é implícita.
O processo não possui uma referência direta e explícita ao recurso. Em vez disso, depende de:
- nomes globais (caminhos de arquivo, portas, identificadores de dispositivo)
- verificações de acesso (IDs de usuário, permissões, ACLs)
Esse modelo cria vários problemas:
1. Problema do delegado confuso⌗
Um programa pode acidentalmente usar sua autoridade de forma indevida em nome de outro programa.
Por exemplo, um serviço privilegiado pode ler um arquivo solicitado por um cliente não confiável, mesmo que esse cliente não devesse ter acesso a ele.
2. Autoridade ampla demais⌗
Programas frequentemente executam com mais permissões do que realmente precisam. Isso aumenta o impacto de bugs ou comprometimentos.
3. Raciocínio difícil⌗
É difícil determinar o que um processo pode fazer sem analisar o estado global, as identidades de usuário e as políticas de controle de acesso.
A ideia central: capacidades⌗
Uma capacidade é um token não falsificável que concede acesso a um objeto específico com direitos específicos.
Em vez de perguntar:
“Este processo tem permissão para acessar este recurso?”
um sistema baseado em capacidades pergunta:
“Este processo possui uma capacidade que autoriza esta operação?”
Se a resposta for não, a operação não pode prosseguir.
Propriedades das capacidades⌗
Capacidades têm várias propriedades definidoras:
1. Não falsificabilidade⌗
Um processo não pode criar uma capacidade válida do nada.
Capacidades são criadas e gerenciadas pelo kernel, o que garante que não possam ser falsificadas nem adivinhadas.
2. Autoridade explícita⌗
Toda autoridade é representada explicitamente por meio de capacidades.
Se um processo pode executar uma operação, ele deve possuir uma capacidade que a permita. Não existe acesso implícito por meio de espaços de nomes globais.
3. Direitos granulares⌗
Capacidades podem codificar permissões específicas, como:
- acesso somente leitura
- acesso de escrita
- permissões de execução
- subconjuntos limitados de operações
Isso permite controle preciso sobre o que cada processo pode fazer.
4. Transferibilidade⌗
Capacidades podem ser transferidas entre processos, normalmente por meio de comunicação entre processos (IPC).
Isso permite delegação controlada de autoridade.
Objetos e capacidades⌗
Em um sistema baseado em capacidades, tudo é modelado como um objeto:
- regiões de memória
- arquivos
- dispositivos
- endpoints de IPC
- processos
Uma capacidade é uma referência a um objeto combinada com um conjunto de direitos.
Um processo interage com o sistema invocando operações sobre objetos por meio de suas capacidades.
Não há necessidade de nomes globais como caminhos de arquivo ou identificadores de dispositivo dentro do kernel. Todo acesso é mediado por capacidades.
Como sistemas baseados em capacidades funcionam⌗
Em alto nível, um sistema baseado em capacidades funciona assim:
- O kernel cria objetos e capacidades.
- Cada processo possui um espaço de capacidades (frequentemente chamado de CSpace), que armazena suas capacidades.
- Um processo só pode operar sobre objetos para os quais possui capacidades.
- Capacidades podem ser transferidas entre processos por meio de IPC.
- O kernel impõe todas as verificações de capacidades.
Isso resulta em um sistema no qual a autoridade é:
- explícita
- localizada
- transferível
- fácil de analisar
Exemplo: abrir um arquivo⌗
Modelo tradicional⌗
Em um sistema tradicional:
- Um processo chama
open("/etc/config") - O kernel verifica permissões:
- ID de usuário
- associação a grupos
- bits de modo do arquivo
- Se permitido, um descritor de arquivo é retornado
A autoridade vem de estado global e identidade.
Modelo baseado em capacidades⌗
Em um sistema baseado em capacidades:
- Um processo já deve possuir uma capacidade de arquivo
- Ele usa essa capacidade para realizar operações de leitura ou escrita
Se o processo não tiver a capacidade, ele não poderá acessar o arquivo, independentemente do nome que usar.
Não existe etapa de busca global dentro do kernel.
Delegação e menor privilégio⌗
Um dos aspectos mais poderosos de sistemas baseados em capacidades é a delegação.
Um processo pode dar a outro processo um subconjunto de sua autoridade transferindo uma capacidade.
Por exemplo:
- Um servidor de arquivos dá a um cliente acesso somente leitura a um arquivo
- Um gerenciador de memória concede acesso a uma região específica de memória
- Um processo concede acesso a um endpoint de IPC
Isso viabiliza o princípio do menor privilégio:
Cada componente recebe apenas a autoridade de que realmente precisa.
Eliminando a autoridade ambiente⌗
Sistemas baseados em capacidades eliminam completamente a autoridade ambiente.
Não há:
- espaços de nomes globais dentro do kernel
- acesso implícito baseado em identidade
- privilégios ocultos
Toda autoridade deve ser passada explicitamente.
Isso torna muito mais fácil analisar:
- o que um processo pode fazer
- como a autoridade flui pelo sistema
- onde podem surgir problemas de segurança
Revogação (um problema difícil)⌗
Um dos desafios em sistemas baseados em capacidades é a revogação.
Depois que uma capacidade é dada a um processo, como ela pode ser retirada?
Diferentes sistemas implementam revogação de maneiras diferentes:
- camadas de indireção
- rastreamento de referências
- árvores de capacidades
- mecanismos de versionamento
Revogação é uma área importante de pesquisa e será explorada em estágios posteriores do EriX.
Sistemas baseados em capacidades na prática⌗
Ideias baseadas em capacidades não são novas. Vários sistemas as implementaram:
- KeyKOS / EROS
- seL4 (um micronúcleo formalmente verificado)
- CHERI (capacidades assistidas por hardware)
- Capsicum (extensões de capacidades para FreeBSD)
Esses sistemas demonstram que projetos baseados em capacidades são ao mesmo tempo práticos e poderosos.
Como o EriX usa capacidades⌗
O EriX foi projetado desde o início como um sistema baseado em capacidades.
No EriX:
- toda autoridade é representada por meio de capacidades
- capacidades são fortemente tipadas
- capacidades são imutáveis depois de criadas
- capacidades são transferidas via IPC
- o kernel impõe não falsificabilidade e invariantes de segurança
Não há espaços de nomes globais dentro do kernel. Todo acesso a recursos é mediado por capacidades.
Isso se alinha ao objetivo mais amplo de tornar a autoridade:
- explícita
- mínima
- fácil de analisar
Por que isso importa⌗
Sistemas baseados em capacidades fornecem uma base para construir:
- sistemas mais seguros
- arquiteturas mais modulares
- sistemas mais fáceis de analisar e verificar
Ao remover autoridade implícita e tornar todo acesso explícito, eles eliminam classes inteiras de vulnerabilidades comuns em sistemas tradicionais.
Olhando adiante⌗
Capacidades são um conceito fundamental no EriX. Em artigos futuros, exploraremos como elas são implementadas na prática, incluindo:
- espaços de capacidades (CSpace)
- comunicação entre processos (IPC)
- gerenciamento de memória usando capacidades não tipadas
- delegação e grafos de autoridade
Entender capacidades é o primeiro passo para entender o restante do sistema.