Para fins de executar verificações de
permissão, implementações UNIX tradicionais distinguem
duas categorias de processos: processos privilegiados (cujo ID de
usuário efetivo é 0, chamado de superusuário ou root) e
processos desprivilegiados (cujo UID efetivo é diferente de
zero). Processos privilegiados ignoram todas as verificações
de permissão do kernel, enquanto processos não privilegiados
estão sujeitos à verificação de permissão
completa com base nas credenciais do processo (geralmente: UID efetivo, GID
efetivo e lista de grupos suplementares).
A partir do Linux 2.2, o Linux divide os privilégios
tradicionalmente associados ao superusuário em unidades distintas,
conhecidas como capacidades (em inglês capabilities),
que podem ser habilitadas e desabilitadas independentemente. Capacidades
são um atributo por thread.
A lista a seguir mostra as capacidades implementadas no Linux e as
operações ou comportamentos que cada capacidade permite:
- CAP_AUDIT_CONTROL
(desde o Linux 2.6.11)
- Habilitar e desabilitar auditoria do kernel; alterar regras de filtro de
auditoria; recuperar status de auditoria e regras de filtragem.
- CAP_AUDIT_READ
(desde o Linux 3.16)
- Permitir leitura do log de auditoria por meio de um soquete netlink
multicast.
- CAP_AUDIT_WRITE
(desde o Linux 2.6.11)
- Gravar registros no log de auditoria do kernel.
- CAP_BLOCK_SUSPEND
(desde o Linux 3.5)
- Empregar recursos que podem bloquear a suspensão do sistema
(epoll(7) EPOLLWAKEUP, /proc/sys/wake_lock).
- CAP_BPF (desde o
Linux 5.8)
- Empregar operações BPF privilegiadas; veja bpf(2) e
bpf-helpers(7).
- Esta capacidade foi adicionada no Linux 5.8 para separar a funcionalidade
BPF da capacidade sobrecarregada CAP_SYS_ADMIN.
- CAP_CHECKPOINT_RESTORE
(desde o Linux 5.9)
- •
- Atualizar /proc/sys/kernel/ns_last_pid (veja
pid_namespaces(7));
- •
- empregar o recurso set_tid de clone3(2);
- •
- ler o conteúdo dos links simbólicos em
/proc/pid/map_files para outros processos.
- Esta capacidade foi adicionada no Linux 5.9 para separar a funcionalidade
checkpoint/restore da capacidade sobrecarregada CAP_SYS_ADMIN.
- CAP_CHOWN
- Fazer alterações arbitrárias em UIDs e GIDs de
arquivo (veja chown(2)).
- CAP_DAC_OVERRIDE
- Ignorar verificações de permissão de leitura,
gravação e execução de arquivo. (DAC é
uma abreviação de "controle de acesso
discricionário" em inglês.)
- CAP_DAC_READ_SEARCH
- •
- Ignorar verificações de permissão de leitura de
arquivo e verificações de permissão de leitura e
execução de diretório;
- •
- invoca open_by_handle_at(2);
- •
- usar o sinalizador linkat(2) AT_EMPTY_PATH para criar um
link para um arquivo referenciado por um descritor de arquivo.
- CAP_FOWNER
- •
- Ignorar verificações de permissão em
operações que normalmente exigem que o UID do sistema de
arquivos do processo corresponda ao UID do arquivo (por exemplo,
chmod(2), utime(2)), excluindo as operações
cobertas por CAP_DAC_OVERRIDE e CAP_DAC_READ_SEARCH;
- •
- definir sinalizadores de inode (consulte FS_IOC_SETFLAGS(2const))
em arquivos arbitrários;
- •
- definir listas de controle de acesso (ACLs) em arquivos
arbitrários;
- •
- ignorar sticky bit de diretório na exclusão de arquivo;
- •
- modificar atributos estendidos de usuário em
diretório sticky de propriedade de qualquer usuário;
- •
- especificar O_NOATIME para arquivos arbitrários em
open(2) e fcntl(2).
- CAP_FSETID
- •
- Não limpar bits de modo set-user-ID e set-group-ID quando um
arquivo for modificado;
- •
- definir o bit set-group-ID para um arquivo cujo GID não corresponde
ao sistema de arquivos ou a qualquer um dos GIDs suplementares do processo
de chamada.
- CAP_IPC_LOCK
- CAP_IPC_OWNER
- Ignorar verificações de permissão para
operações em objetos IPC do System V.
- CAP_KILL
- Ignorar verificações de permissão para enviar sinais
(consulte kill(2)). Isso inclui o uso da operação
ioctl(2) KDSIGACCEPT.
- CAP_LEASE
(desde o Linux 2.4)
- Estabelecer concessões em arquivos arbitrários (consulte
fcntl(2)).
- CAP_LINUX_IMMUTABLE
- Definir os sinalizadores de inode FS_APPEND_FL e
FS_IMMUTABLE_FL (consulte FS_IOC_SETFLAGS(2const)).
- CAP_MAC_ADMIN
(desde o Linux 2.6.25)
- Permitir configuração de MAC ou alterações de
estado. Implementada para o Smack Linux Security Module (LSM).
- CAP_MAC_OVERRIDE
(desde o Linux 2.6.25)
- Substituir o Mandatory Access Control (MAC). Implementada para o Smack
LSM.
- CAP_MKNOD
(desde o Linux 2.4)
- Criar arquivos especiais usando mknod(2).
- CAP_NET_ADMIN
- Executar várias operações relacionadas a rede:
- •
- configuração de interface;
- •
- administração de firewall de IP, de m e contas;
- •
- modificar tabelas de roteamento;
- •
- vincular a qualquer endereço para proxy transparente;
- •
- definir o tipo de serviço (TOS);
- •
- limpar estatísticas do driver;
- •
- definir o modo promíscuo;
- •
- habilitar multicasting;
- •
- usar setsockopt(2) para definir as seguintes opções
de soquete: SO_DEBUG, SO_MARK, SO_PRIORITY (para uma
prioridade fora do intervalo de 0 a 6), SO_RCVBUFFORCE e
SO_SNDBUFFORCE.
- CAP_NET_BIND_SERVICE
- Vincular um socket a portas privilegiadas de domínio da Internet
(números de porta menores que 1024).
- CAP_NET_BROADCAST
- (Não usado) Fazer transmissões de socket e ouvir
multicasts.
- CAP_NET_RAW
- •
- Usar sockets RAW e PACKET;
- •
- vincular a qualquer endereço para proxy transparente.
- CAP_PERFMON
(desde o Linux 5.8)
- Empregar vários mecanismos de monitoramento de desempenho,
incluindo:
- •
- chamar perf_event_open(2);
- •
- empregar várias operações BPF que têm
implicações de desempenho.
- Esta capacidade foi adicionada no Linux 5.8 para separar a funcionalidade
de monitoramento de desempenho da capacidade sobrecarregada
CAP_SYS_ADMIN. Veja também o arquivo-fonte do kernel
Documentation/admin-guide/perf-security.rst.
- CAP_SETGID
- •
- Fazer manipulações arbitrárias de GIDs de processo e
listar de GID suplementar;
- •
- forjar GID ao passar credenciais de socket por meio de sockets de
domínio UNIX;
- •
- escrever um mapeamento de ID de grupo em um espaço de nomes de
usuário (veja user_namespaces(7)).
- CAP_SETFCAP
(desde o Linux 2.6.24)
- Definir capacidades arbitrárias em um arquivo.
- Desde o Linux 5.12, esse recurso também é necessário
para mapear o ID do usuário 0 em um novo espaço de nomes de
usuário; veja user_namespaces(7) para detalhes.
- CAP_SETPCAP
- Se os recursos de arquivo forem suportados (isto é, desde o Linux
2.6.24): adicionar qualquer recurso do conjunto delimitador da thread de
chamada ao seu conjunto herdável; remover recursos do conjunto
delimitador (por meio de prctl(2) PR_CAPBSET_DROP); fazer
alterações nos sinalizadores securebits.
- Se os recursos de arquivo não forem suportados (isto é,
antes do Linux 2.6.24): conceder ou remover qualquer recurso no conjunto
de recursos permitidos do chamador para ou de qualquer outro processo.
(esta propriedade de CAP_SETPCAP não está
disponível quando o kernel é configurado para suportar
recursos de arquivo, já que CAP_SETPCAP tem
semânticas totalmente diferentes para tais kernels.)
- CAP_SETUID
- CAP_SYS_ADMIN
- Nota: esta capacidade está sobrecarregada; consulte Notas
para desenvolvedores de kernel abaixo.
- •
- Executar uma série de operações de
administração do sistema, incluindo: quotactl(2),
mount(2), umount(2), pivot_root(2), swapon(2),
swapoff(2), sethostname(2) e setdomainname(2);
- •
- executar operações privilegiadas de syslog(2) (desde
o Linux 2.6.37, CAP_SYSLOG deve ser usado para permitir tais
operações);
- •
- executar o comando VM86_REQUEST_IRQ vm86(2);
- •
- acessar a mesma funcionalidade de checkpoint/restauração que
é governada por CAP_CHECKPOINT_RESTORE (mas a última,
capacidade mais fraca, é preferida para acessar essa
funcionalidade).
- •
- executar as mesmas operações BPF que são governadas
por CAP_BPF (mas a última, capacidade mais fraca, é
preferida para acessar essa funcionalidade).
- •
- empregar os mesmos mecanismos de monitoramento de desempenho que
são governados por CAP_PERFMON (mas a última,
capacidade mais fraca, é preferida para acessar essa
funcionalidade).
- •
- executar operações IPC_SET e IPC_RMID em
objetos IPC arbitrários do System V;
- •
- substituir limite de recurso RLIMIT_NPROC;
- •
- executar operações em atributos estendidos trusted e
security (consulte xattr(7));
- •
- usar lookup_dcookie(2);
- •
- usar ioprio_set(2) para atribuir classes de agendamento de E/S
IOPRIO_CLASS_RT e (antes do Linux 2.6.25)
IOPRIO_CLASS_IDLE;
- •
- forjar PID ao passar credenciais de soquete por soquetes de domínio
UNIX;
- •
- exceder /proc/sys/fs/file-max, o limite de todo o sistema no
número de arquivos abertos, em chamadas de sistema que abrem
arquivos (por exemplo, accept(2), execve(2), open(2),
pipe(2));
- •
- empregar sinalizadores CLONE_* que criam novos espaços de
nomes com clone(2) e unshare(2) (mas, desde o Linux 3.8,
criar espaços de nomes de usuário não requer nenhuma
capacidade);
- •
- acessar informações privilegiadas de eventos
perf;
- •
- chamar setns(2) (requer CAP_SYS_ADMIN no espaço de
nomes target);
- •
- chamar fanotify_init(2);
- •
- executar operações privilegiadas KEYCTL_CHOWN e
KEYCTL_SETPERM do keyctl(2);
- •
- executar a operação madvise(2)
MADV_HWPOISON;
- •
- empregar o TIOCSTI ioctl(2) para inserir caracteres na fila
de entrada de um terminal diferente do terminal de controle do
chamador;
- •
- empregar a chamada de sistema nfsservctl(2) obsoleta;
- •
- empregar a chamada de sistema bdflush(2) obsoleta;
- •
- executar várias operações de dispositivo de bloco
privilegiado ioctl(2);
- •
- executar várias operações de sistema de arquivo
privilegiado ioctl(2);
- •
- executar operações ioctl(2) privilegiadas no
dispositivo /dev/random (consulte random(4));
- •
- instalar um filtro seccomp(2) sem primeiro ter que definir o
atributo de thread no_new_privs;
- •
- modificar regras de permissão/negação para grupos de
controle de dispositivo;
- •
- empregar a operação ptrace(2)
PTRACE_SECCOMP_GET_FILTER para despejar os filtros seccomp do
tracee;
- •
- empregar a operação ptrace(2)
PTRACE_SETOPTIONS para suspender as proteções seccomp
do tracee (ou seja, o sinalizador PTRACE_O_SUSPEND_SECCOMP);
- •
- executar operações administrativas em muitos drivers de
dispositivo;
- •
- modificar valores de nice do autogroup escrevendo em
/proc/pid/autogroup (consulte sched(7)).
- CAP_SYS_BOOT
- Usar reboot(2) e kexec_load(2).
- CAP_SYS_CHROOT
- CAP_SYS_MODULE
- •
- Carregar e descarregar módulos do kernel (veja
init_module(2) e delete_module(2));
- •
- antes do Linux 2.6.25: remover recursos do conjunto de
delimitação de recursos de todo o sistema.
- CAP_SYS_NICE
- CAP_SYS_PACCT
- Usar acct(2).
- CAP_SYS_PTRACE
- CAP_SYS_RAWIO
- •
- Executar operações de E/S de porta (iopl(2) e
ioperm(2));
- •
- acessar /proc/kcore;
- •
- empregar a operação FIBMAP ioctl(2);
- •
- abrir dispositivos para acessar registradores específicos do modelo
x86 (MSRs, veja msr(4));
- •
- atualizar /proc/sys/vm/mmap_min_addr;
- •
- criar mapeamentos de memória em endereços abaixo do valor
especificado por /proc/sys/vm/mmap_min_addr;
- •
- mapear arquivos em /proc/bus/pci;
- •
- abrir /dev/mem e /dev/kmem;
- •
- executar vários comandos de dispositivo SCSI;
- •
- executar certas operações em dispositivos hpsa(4) e
cciss(4);
- •
- executar uma série de operações específicas de
dispositivo em outros dispositivos.
- CAP_SYS_RESOURCE
- •
- Usar espaço reservado em sistemas de arquivos ext2;
- •
- fazer chamadas ioctl(2) controlando a manipulação do
journal de ext3;
- •
- substituir limites de cota de disco;
- •
- aumentar limites de recursos (veja setrlimit(2));
- •
- substituir limite de recurso RLIMIT_NPROC;
- •
- substituir número máximo de consoles na
alocação de console;
- •
- substituir número máximo de mapas de teclas;
- •
- permitir interrupções com mais de 64hz do relógio de
tempo real;
- •
- aumentar o limite de msg_qbytes para uma fila de mensagens do
System V acima do limite em /proc/sys/kernel/msgmnb (consulte
msgop(2) e msgctl(2));
- •
- permitir que o limite de recurso RLIMIT_NOFILE no número de
descritores de arquivo, durante seu uso, seja ignorado ao passar
descritores de arquivo para outro processo por meio de um soquete de
domínio UNIX (consulte unix(7));
- •
- substituir o limite de /proc/sys/fs/pipe-size-max ao definir a
capacidade de um pipe usando o comando F_SETPIPE_SZ
fcntl(2);
- •
- usar F_SETPIPE_SZ para aumentar a capacidade de um pipe acima do
limite especificado por /proc/sys/fs/pipe-max-size;
- •
- substituir os limites /proc/sys/fs/mqueue/queues_max,
/proc/sys/fs/mqueue/msg_max e
/proc/sys/fs/mqueue/msgsize_max ao criar filas de mensagens POSIX
(consulte mq_overview(7));
- •
- empregar a operação prctl(2) PR_SET_MM;
- •
- definir /proc/pid/oom_score_adj para um valor menor que o
último valor definido por um processo com
CAP_SYS_RESOURCE.
- CAP_SYS_TIME
- Definir o relógio do sistema (settimeofday(2),
stime(2), adjtimex(2)); definir relógio de tempo real
(hardware).
- CAP_SYS_TTY_CONFIG
- Usar vhangup(2); empregar várias operações
privilegiadas ioctl(2) em terminais virtuais.
- CAP_SYSLOG
(desde o Linux 2.6.37)
- •
- Executar operações privilegiadas syslog(2). Consulte
syslog(2) para obter informações sobre quais
operações exigem privilégio.
- •
- Exibir endereços do kernel expostos via /proc e outras
interfaces quando /proc/sys/kernel/kptr_restrict tiver o valor 1.
(Consulte a discussão sobre kptr_restrict em
proc(5).)
- CAP_WAKE_ALARM
(desde o Linux 3.0)
- Disparar algo que despertará o sistema (definir temporizadores
CLOCK_REALTIME_ALARM e CLOCK_BOOTTIME_ALARM).
Uma implementação completa de capacidades requer
que:
- •
- Para todas as operações privilegiadas, o kernel deve
verificar se a thread tem a capacidade necessária em seu conjunto
efetivo.
- •
- O kernel deve fornecer chamadas de sistema permitindo que os conjuntos de
capacidades de uma thread sejam alteradas e recuperadas.
- •
- O sistema de arquivos deve oferecer suporte a anexar capacidades a um
arquivo executável, para que um processo ganhe essas capacidades
quando o arquivo for executado.
Antes do Linux 2.6.24, apenas os dois primeiros desses requisitos
são atendidos; desde o Linux 2.6.24, todos os três requisitos
são atendidos.
Ao adicionar um novo recurso do kernel que deve ser governado por
uma capacidade, considere os seguintes pontos.
- •
- O objetivo das capacidades é dividir o poder do superusuário
em partes, de modo que se um programa que tem uma ou mais capacidades for
comprometido, seu poder de causar danos ao sistema seria menor do que o
mesmo programa em execução com privilégio de
root.
- •
- Você tem a opção de criar uma nova capacidade para
seu novo recurso ou associar o recurso a uma das capacidades existentes.
Para manter o conjunto de capacidades em um tamanho administrável,
a última opção é preferível, a menos
que haja razões convincentes para escolher a primeira
opção. (Há também um limite técnico: o
tamanho dos conjuntos de capacidades é atualmente limitado a 64
bits.)
- •
- Para determinar qual capacidade existente pode ser melhor associada ao seu
novo recurso, revise a lista de capacidades acima para encontrar um
"silo" no qual seu novo recurso se encaixe melhor. Uma abordagem
a ser tomada é determinar se há outras funções
que exigem capacidades que sempre serão usadas junto com o novo
recurso. Se o novo recurso for inútil sem essas outras
funções, você deve usar a mesma capacidade que as
outras funções.
- •
- Não escolha CAP_SYS_ADMIN se você puder
evitá-la! Uma grande proporção de
verificações de capacidade existentes está associada
a essa capacidade (veja a lista parcial acima). Ela pode ser
plausivelmente chamada de "o novo root", já que, por um
lado, confere uma ampla gama de poderes e, por outro lado, seu amplo
escopo significa que essa é a capacidade necessária para
muitos programas privilegiados. Não piore o problema. As
únicas novas funções que devem ser associadas a
CAP_SYS_ADMIN são aquelas que quase correspondo aos
usos existentes naquele silo.
- •
- Se você determinou que é realmente necessário criar
uma nova capacidade para seu recurso, não a crie ou nomeie como uma
capacidade de "uso único". Assim, por exemplo, a
adição do CAP_SYS_PACCT altamente específico
provavelmente foi um erro. Em vez disso, tente identificar e nomear sua
nova capacidade como um silo mais amplo no qual outros casos de uso
futuros relacionados podem se encaixar.
Cada thread tem os seguintes conjuntos de capacidade contendo zero
ou mais das capacidades acima:
- Permitted
- Este é um superconjunto limitante para as capacidades efetivas que
a thread pode assumir. Também é um superconjunto limitante
para as capacidades que podem ser adicionadas ao conjunto herdável
por uma thread que não tem a capacidade CAP_SETPCAP em seu
conjunto efetivo.
- Se uma thread remover uma capacidade de seu conjunto permitido, ela nunca
poderá readquirir essa capacidade (a menos que seja usado
execve(2) por um programa set-user-ID-root ou um programa cujas
capacidades de arquivo associadas concedam essa capacidade).
- Inheritable
- Este é um conjunto de capacidades preservadas em um
execve(2). Capacidades herdáveis (em inglês,
"inheritable") permanecem herdáveis
ao executar qualquer programa, e capacidades
herdáveis são adicionadas ao conjunto
permitido ao executar um programa que tem os bits correspondentes
definidos no conjunto herdável do arquivo.
- Como as capacidades herdáveis geralmente não
são preservadas em execve(2) ao executar como um
usuário não root, os aplicativos que desejam executar
programas auxiliares com capacidades elevadas devem considerar o uso de
capacidades ambientais, descritas abaixo.
- Effective
- Este é o conjunto de capacidades usado pelo kernel para executar
verificações de permissão para a thread.
- Bounding (por
cada thread desde o Linux 2.6.25)
- O conjunto de limites de capacidade é um mecanismo que pode ser
usado para limitar as capacidades obtidas durante execve(2).
- Desde o Linux 2.6.25, este é um conjunto de capacidades por thread.
Em kernels mais antigos, o conjunto de limites de capacidade era um
atributo de todo o sistema compartilhado por todas as threads no
sistema.
- Para mais detalhes, veja Conjunto limitador de capacidades
abaixo.
- Ambient (desde o
Linux 4.3)
- Este é um conjunto de capacidades que são preservadas em um
execve(2) de um programa que não é privilegiado. O
conjunto de capacidades de ambiente obedece à invariante de que
nenhuma capacidade pode ser ambiente se não for permitida e
herdável.
- O conjunto de capacidades de ambiente pode ser modificado diretamente
usando prctl(2). As capacidades de ambiente são
automaticamente reduzidas se qualquer uma das capacidades permitidas ou
herdáveis correspondentes for reduzida.
- Executar um programa que altera UID ou GID devido aos bits set-user-ID ou
set-group-ID ou executar um programa que tem qualquer conjunto de
capacidades de arquivo limpará o conjunto de ambiente. As
capacidades de ambiente são adicionadas ao conjunto permitido e
atribuídas ao conjunto efetivo quando execve(2) é
chamado. Se as capacidades ambientais fizerem com que as capacidades
permitidas e efetivas de um processo aumentem durante um execve(2),
isso não aciona o modo de execução segura descrito em
ld.so(8).
Um filho criado via fork(2) herda cópias dos
conjuntos de capacidades de seu pai. Para detalhes sobre como
execve(2) afeta as capacidades, veja Transformação
de capacidades durante execve() abaixo.
Usando capset(2), uma thread pode manipular seus
próprios conjuntos de capacidades; veja Ajustando conjuntos de
capacidades programaticamente abaixo.
Desde o Linux 3.2, o arquivo /proc/sys/kernel/cap_last_cap
expõe o valor numérico da capacidade mais alta suportada pelo
kernel em execução; isso pode ser usado para determinar o bit
mais alto que pode ser definido em um conjunto de capacidades.
Desde o Linux 2.6.24, o kernel oferece suporte à
associação de conjuntos de capacidades com um arquivo
executável usando setcap(8). Os conjuntos de capacidade de
arquivo são armazenados em um atributo estendido (veja
setxattr(2) e xattr(7)) chamado security.capability.
Escrever neste atributo estendido requer a capacidade CAP_SETFCAP. Os
conjuntos de capacidade de arquivo, em conjunto com os conjuntos de
capacidade do thread, determinam as capacidades de uma thread após um
execve(2).
Os três conjuntos de capacidades de arquivo são:
- Permitted
(anteriormente conhecido como forced):
- Estas capacidades são automaticamente permitidas para a thread,
independentemente das capacidades herdáveis da
thread.
- Inheritable
(anteriormente conhecido como allowed):
- Este conjunto comparado em E lógico com o conjunto herdável
da thread para determinar quais capacidades herdáveis
são habilitadas no conjunto permitido da thread
após o execve(2).
- Effective:
- Este não é um conjunto, mas apenas um único bit. Se
este bit for definido, então durante um execve(2) todas as
novas capacidades permitidas para a thread também são
levantadas no conjunto efetivo. Se este bit não for definido,
então após um execve(2), nenhuma das novas
capacidades permitidas está no novo conjunto efetivo.
- Habilitar o bit de capacidade efetiva do arquivo implica que qualquer
capacidade permitida ou herdável do arquivo que faça com que
uma thread adquira a capacidade permitida correspondente durante um
execve(2) (veja Transformação de capacidades
durante execve() abaixo) também adquirirá essa
capacidade em seu conjunto efetivo. Portanto, ao atribuir capacidades a um
arquivo (setcap(8), cap_set_file(3), cap_set_fd(3)),
se especificarmos o sinalizador efetivo como habilitado para qualquer
capacidade, então o sinalizador efetivo também deve ser
especificado como habilitado para todas as outras capacidades para as
quais o sinalizador permitido ou herdável correspondente
está habilitado.
Para permitir extensibilidade, o kernel oferece suporte a um
esquema para codificar um número de versão dentro do atributo
estendido security.capability que é usado para implementar
recursos de arquivo. Esses números de versão são
internos à implementação e não são
diretamente visíveis para aplicativos de espaço do
usuário. Até o momento, as seguintes versões são
suportadas:
- VFS_CAP_REVISION_1
- Esta foi a implementação original da capacidade de arquivo,
que suportava máscaras de 32 bits para capacidades de arquivo.
- VFS_CAP_REVISION_2
(desde o Linux 2.6.25)
- Esta versão permite máscaras de capacidade de arquivo com
tamanho de 64 bits e foi necessária à medida que o
número de capacidades suportadas cresceu além de 32. O
kernel continua a oferecer suporte transparente à
execução de arquivos que têm máscaras de
capacidade de versão 1 de 32 bits, mas ao adicionar capacidades a
arquivos que não tinham capacidades anteriormente, ou modificar as
capacidades de arquivos existentes, ele usa automaticamente o esquema da
versão 2 (ou possivelmente o esquema da versão 3, conforme
descrito abaixo).
- VFS_CAP_REVISION_3
(desde o Linux 4.14)
- Os recursos de arquivo da versão 3 são fornecidos para
oferecer suporte a recursos de arquivo com espaço de nomes
(descritos abaixo).
- Assim como com os recursos de arquivo da versão 2, as
máscaras de recursos da versão 3 têm 64 bits de
tamanho. Mas, além disso, o ID do usuário raiz do
espaço de nomes é codificado no atributo estendido
security.capability. (O ID do usuário raiz de um
espaço de nomes é o valor que o ID do usuário 0
dentro desse espaço de nomes mapeia no espaço de nomes do
usuário inicial.)
- Os recursos de arquivo da versão 3 são projetados para
coexistir com os recursos da versão 2; ou seja, em um sistema Linux
moderno, pode haver alguns arquivos com recursos da versão 2,
enquanto outros têm recursos da versão 3.
Antes do Linux 4.14, o único tipo de atributo estendido de
capacidade de arquivo que podia ser anexado a um arquivo era um atributo
VFS_CAP_REVISION_2. Desde o Linux 4.14, a versão do atributo
estendido security.capability que é anexado a um arquivo
depende das circunstâncias em que o atributo foi criado.
A partir do Linux 4.14, um atributo estendido
security.capability é criado automaticamente como (ou
convertido para) um atributo da versão 3 (VFS_CAP_REVISION_3)
se ambas as condições a seguir forem verdadeiras:
- •
- A thread que escreve o atributo reside em um espaço de nomes de
usuário não inicial. (Mais precisamente: a thread reside em
um espaço de nomes de usuário diferente daquele do qual o
sistema de arquivos subjacente foi montado.)
- •
- A thread tem a capacidade CAP_SETFCAP sobre o inode do arquivo, o
que significa que (a) a thread tem a capacidade CAP_SETFCAP em seu
próprio espaço de nomes de usuário; e (b) o UID e o
GID do inode do arquivo têm mapeamentos no espaço de nomes
de usuário de escrita.
Quando um atributo estendido security.capability de
VFS_CAP_REVISION_3 é criado, o ID do usuário raiz do
espaço de nomes do usuário da thread de criação
é salvo no atributo estendido.
Por outro lado, criar ou modificar um atributo estendido
security.capability de uma thread privilegiada (CAP_SETFCAP)
que reside no espaço de nomes onde o sistema de arquivos subjacente
foi montado (isso normalmente significa o espaço de nomes do
usuário inicial) resulta automaticamente na criação de
um atributo da versão 2 (VFS_CAP_REVISION_2).
Observe que a criação de um atributo estendido
security.capability versão 3 é automática. Ou
seja, quando um aplicativo de espaço de usuário grava
(setxattr(2)) um atributo security.capability no formato da
versão 2, o kernel criará automaticamente um atributo da
versão 3 se o atributo for criado nas circunstâncias descritas
acima. Correspondentemente, quando um atributo security.capability
versão 3 é recuperado (getxattr(2)) por um processo que
reside dentro de um espaço de nomes de usuário que foi criado
pelo ID do usuário raiz (ou um descendente desse espaço de
nomes de usuário), o atributo retornado é (automaticamente)
simplificado para aparecer como um atributo da versão 2 (ou seja, o
valor retornado é o tamanho de um atributo da versão 2 e
não inclui o ID do usuário raiz). Essas
traduções automáticas significam que nenhuma
alteração é necessária nas ferramentas do
espaço do usuário (por exemplo, setcap(1) e
getcap(1)) para que essas ferramentas sejam usadas para criar e
recuperar atributos security.capability da versão 3.
Observe que um arquivo pode ter um atributo estendido
security.capability versão 2 ou 3 associado a ele, mas
não ambos: a criação ou modificação do
atributo estendido security.capability modificará
automaticamente a versão de acordo com as circunstâncias em
que o atributo estendido for criado ou modificado.
Durante um execve(2), o kernel calcula as novas capacidades
do processo usando o seguinte algoritmo:
P'(ambient) = (arquivo é privilegiado) ? 0 : P(ambient)
P'(permitted) = (P(inheritable) & F(inheritable)) |
(F(permitted) & P(bounding)) | P'(ambient)
P'(effective) = F(effective) ? P'(permitted) : P'(ambient)
P'(inheritable) = P(inheritable) [isto é, inalterado]
P'(bounding) = P(bounding) [isto é, inalterado]
onde:
- P()
- denota o valor de um conjunto de capacidades de thread antes de
execve(2)
- P'()
- denota o valor de um conjunto de capacidades de thread depois de
execve(2)
- F()
- denota um conjunto de capacidades de arquivo
Observe os seguintes detalhes relacionados às regras de
transformação de capacidades acima:
- •
- O conjunto de capacidades de ambiente está presente somente desde o
Linux 4.3. Ao determinar a transformação do conjunto de
ambiente durante execve(2), um arquivo privilegiado é aquele
que tem capacidades ou tem o bit set-user-ID ou set-group-ID
definido.
- •
- Antes do Linux 2.6.25, o conjunto limitador era um atributo de todo o
sistema compartilhado por todas as threads. Esse valor de todo o sistema
foi empregado para calcular o novo conjunto permitido durante
execve(2) da mesma maneira mostrada acima para
P(bounding).
Nota: durante as transições de capacidade
descritas acima, as capacidades de arquivo podem ser ignoradas (tratadas
como vazias) pelos mesmos motivos que os bits set-user-ID e set-group-ID
são ignorados; consulte execve(2). As capacidades de arquivo
são ignoradas de forma semelhante se o kernel foi inicializado com a
opção no_file_caps.
Nota: de acordo com as regras acima, se um processo com IDs
de usuário diferentes de zero executar um execve(2), quaisquer
capacidades que estejam presentes em seus conjuntos permitidos e efetivos
serão limpas. Para o tratamento de capacidades quando um processo com
uma ID de usuário zero executa um execve(2), consulte
Capacidades e execução de programas pelo root
abaixo.
Um binário sem suporte a capacidades é um aplicativo
que foi marcado para ter capacidades de arquivo, mas não foi
convertido para usar a API libcap(3) para manipular suas capacidades.
(Em outras palavras, este é um programa tradicional set-user-ID-root
que foi alternado para usar recursos de arquivo, mas cujo código
não foi modificado para entender os recursos.) Para tais aplicativos,
o bit de capacidade efetiva é definido no arquivo, de modo que os
recursos permitidos do arquivo sejam habilitados automaticamente no conjunto
efetivo do processo ao executar o arquivo. O kernel reconhece um arquivo que
tem o bit de capacidade efetiva definido como não tendo suporte a
capacidades para o propósito da verificação descrita
aqui.
Ao executar um binário sem suporte a capacidades, o kernel
verifica se o processo obteve todos os recursos permitidos que foram
especificados no conjunto de arquivos permitidos, após as
transformações de recursos descritas acima terem sido
executadas. (O motivo típico pelo qual isso pode não
ocorrer é que o conjunto limitador de recursos mascarou alguns dos
recursos no conjunto de arquivos permitidos.) Se o processo não
obteve o conjunto completo de recursos permitidos do arquivo, então
execve(2) falha com o erro EPERM. Isso evita possíveis
riscos de segurança que podem surgir quando um aplicativo sem suporte
a capacidades é executado com menos privilégios do que o
necessário. Observe que, por definição, o aplicativo
não poderia reconhecer esse problema, pois não emprega a API
do libcap(3).
Para espelhar a semântica tradicional do UNIX, o kernel
realiza um tratamento especial de capacidades de arquivo quando um processo
com UID 0 (root) executa um programa e quando um programa set-user-ID-root
é executado.
Após ter realizado quaisquer alterações no ID
efetivo do processo que foram acionadas pelo bit de modo set-user-ID do
binário — por exemplo, alternando o ID efetivo do
usuário para 0 (root) porque um programa set-user-ID-root foi
executado — o kernel calcula os conjuntos de capacidades de arquivo
da seguinte forma:
- (1)
- If the real or effective user ID of the process is 0 (root), then the file
inheritable and permitted sets are ignored; instead they are notionally
considered to be all ones (i.e., all capabilities enabled). (There is one
exception to this behavior, described in Set-user-ID-root programs that
have file capabilities below.)
- (2)
- If the effective user ID of the process is 0 (root) or the file effective
bit is in fact enabled, then the file effective bit is notionally defined
to be one (enabled).
These notional values for the file's capability sets are then used
as described above to calculate the transformation of the process's
capabilities during execve(2).
Thus, when a process with nonzero UIDs execve(2)s a
set-user-ID-root program that does not have capabilities attached, or when a
process whose real and effective UIDs are zero execve(2)s a program,
the calculation of the process's new permitted capabilities simplifies
to:
P'(permitted) = P(inheritable) | P(bounding)
P'(effective) = P'(permitted)
Consequentemente, o processo ganha todas as capacidades em seus
conjuntos de capacidades permitidas e efetivas, exceto aquelas mascaradas
pelo conjunto limitador de capacidades. (No cálculo de P'(permitted),
o termo P'(ambient) pode ser simplificado porque é, por
definição, um subconjunto próprio de
P(inheritable).)
The special treatments of user ID 0 (root) described in this
subsection can be disabled using the securebits mechanism described
below.
There is one exception to the behavior described in
Capabilities and execution of programs by root above. If (a) the
binary that is being executed has capabilities attached and (b) the real
user ID of the process is not 0 (root) and (c) the effective user ID
of the process is 0 (root), then the file capability bits are honored
(i.e., they are not notionally considered to be all ones). The usual way in
which this situation can arise is when executing a set-UID-root program that
also has file capabilities. When such a program is executed, the process
gains just the capabilities granted by the program (i.e., not all
capabilities, as would occur when executing a set-user-ID-root program that
does not have any associated file capabilities).
Note that one can assign empty capability sets to a program file,
and thus it is possible to create a set-user-ID-root program that changes
the effective and saved set-user-ID of the process that executes the program
to 0, but confers no capabilities to that process.
O conjunto limitador de capacidade é um mecanismo de
segurança que pode ser usado para limitar as capacidades que podem
ser obtidas durante um execve(2). O conjunto limitador é usado
das seguintes maneiras:
- •
- During an execve(2), the capability bounding set is ANDed with the
file permitted capability set, and the result of this operation is
assigned to the thread's permitted capability set. The capability bounding
set thus places a limit on the permitted capabilities that may be granted
by an executable file.
- •
- (Since Linux 2.6.25) The capability bounding set acts as a limiting
superset for the capabilities that a thread can add to its inheritable set
using capset(2). This means that if a capability is not in the
bounding set, then a thread can't add this capability to its inheritable
set, even if it was in its permitted capabilities, and thereby cannot have
this capability preserved in its permitted set when it execve(2)s a
file that has the capability in its inheritable set.
Note that the bounding set masks the file permitted capabilities,
but not the inheritable capabilities. If a thread maintains a capability in
its inheritable set that is not in its bounding set, then it can still gain
that capability in its permitted set by executing a file that has the
capability in its inheritable set.
Depending on the kernel version, the capability bounding set is
either a system-wide attribute, or a per-process attribute.
Capability bounding set from Linux 2.6.25 onward
From Linux 2.6.25, the capability bounding set is a
per-thread attribute. (The system-wide capability bounding set described
below no longer exists.)
The bounding set is inherited at fork(2) from the thread's
parent, and is preserved across an execve(2).
A thread may remove capabilities from its capability bounding set
using the prctl(2) PR_CAPBSET_DROP operation, provided it has
the CAP_SETPCAP capability. Once a capability has been dropped from
the bounding set, it cannot be restored to that set. A thread can determine
if a capability is in its bounding set using the prctl(2)
PR_CAPBSET_READ operation.
Removing capabilities from the bounding set is supported only if
file capabilities are compiled into the kernel. Before Linux 2.6.33, file
capabilities were an optional feature configurable via the
CONFIG_SECURITY_FILE_CAPABILITIES option. Since Linux 2.6.33, the
configuration option has been removed and file capabilities are always part
of the kernel. When file capabilities are compiled into the kernel, the
init process (the ancestor of all processes) begins with a full
bounding set. If file capabilities are not compiled into the kernel, then
init begins with a full bounding set minus CAP_SETPCAP,
because this capability has a different meaning when there are no file
capabilities.
Removing a capability from the bounding set does not remove it
from the thread's inheritable set. However it does prevent the capability
from being added back into the thread's inheritable set in the future.
Capability bounding set prior to Linux 2.6.25
Before Linux 2.6.25, the capability bounding set is a system-wide
attribute that affects all threads on the system. The bounding set is
accessible via the file /proc/sys/kernel/cap-bound. (Confusingly,
this bit mask parameter is expressed as a signed decimal number in
/proc/sys/kernel/cap-bound.)
Only the init process may set capabilities in the
capability bounding set; other than that, the superuser (more precisely: a
process with the CAP_SYS_MODULE capability) may only clear
capabilities from this set.
On a standard system the capability bounding set always masks out
the CAP_SETPCAP capability. To remove this restriction (dangerous!),
modify the definition of CAP_INIT_EFF_SET in
include/linux/capability.h and rebuild the kernel.
The system-wide capability bounding set feature was added to Linux
2.2.11.
To preserve the traditional semantics for transitions between 0
and nonzero user IDs, the kernel makes the following changes to a thread's
capability sets on changes to the thread's real, effective, saved set, and
filesystem user IDs (using setuid(2), setresuid(2), or
similar):
- •
- If one or more of the real, effective, or saved set user IDs was
previously 0, and as a result of the UID changes all of these IDs have a
nonzero value, then all capabilities are cleared from the permitted,
effective, and ambient capability sets.
- •
- If the effective user ID is changed from 0 to nonzero, then all
capabilities are cleared from the effective set.
- •
- If the effective user ID is changed from nonzero to 0, then the permitted
set is copied to the effective set.
- •
- If the filesystem user ID is changed from 0 to nonzero (see
setfsuid(2)), then the following capabilities are cleared from the
effective set: CAP_CHOWN, CAP_DAC_OVERRIDE,
CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_FSETID,
CAP_LINUX_IMMUTABLE (since Linux 2.6.30), CAP_MAC_OVERRIDE,
and CAP_MKNOD (since Linux 2.6.30). If the filesystem UID is
changed from nonzero to 0, then any of these capabilities that are enabled
in the permitted set are enabled in the effective set.
If a thread that has a 0 value for one or more of its user IDs
wants to prevent its permitted capability set being cleared when it resets
all of its user IDs to nonzero values, it can do so using the
SECBIT_KEEP_CAPS securebits flag described below.
A thread can retrieve and change its permitted, effective, and
inheritable capability sets using the capget(2) and capset(2)
system calls. However, the use of cap_get_proc(3) and
cap_set_proc(3), both provided in the libcap package, is
preferred for this purpose. The following rules govern changes to the thread
capability sets:
- •
- If the caller does not have the CAP_SETPCAP capability, the new
inheritable set must be a subset of the combination of the existing
inheritable and permitted sets.
- •
- (Since Linux 2.6.25) The new inheritable set must be a subset of the
combination of the existing inheritable set and the capability bounding
set.
- •
- The new permitted set must be a subset of the existing permitted set
(i.e., it is not possible to acquire permitted capabilities that the
thread does not currently have).
- •
- The new effective set must be a subset of the new permitted set.
Starting with Linux 2.6.26, and with a kernel in which file
capabilities are enabled, Linux implements a set of per-thread
securebits flags that can be used to disable special handling of
capabilities for UID 0 (root). These flags are as follows:
- SECBIT_KEEP_CAPS
- Setting this flag allows a thread that has one or more 0 UIDs to retain
capabilities in its permitted set when it switches all of its UIDs to
nonzero values. If this flag is not set, then such a UID switch causes the
thread to lose all permitted capabilities. This flag is always cleared on
an execve(2).
- Note that even with the SECBIT_KEEP_CAPS flag set, the effective
capabilities of a thread are cleared when it switches its effective UID to
a nonzero value. However, if the thread has set this flag and its
effective UID is already nonzero, and the thread subsequently switches all
other UIDs to nonzero values, then the effective capabilities will not be
cleared.
- The setting of the SECBIT_KEEP_CAPS flag is ignored if the
SECBIT_NO_SETUID_FIXUP flag is set. (The latter flag provides a
superset of the effect of the former flag.)
- This flag provides the same functionality as the older prctl(2)
PR_SET_KEEPCAPS operation.
- SECBIT_NO_SETUID_FIXUP
- Setting this flag stops the kernel from adjusting the process's permitted,
effective, and ambient capability sets when the thread's effective and
filesystem UIDs are switched between zero and nonzero values. See
Effect of user ID changes on capabilities above.
- SECBIT_NOROOT
- If this bit is set, then the kernel does not grant capabilities when a
set-user-ID-root program is executed, or when a process with an effective
or real UID of 0 calls execve(2). (See Capabilities and
execution of programs by root above.)
- SECBIT_NO_CAP_AMBIENT_RAISE
- Setting this flag disallows raising ambient capabilities via the
prctl(2) PR_CAP_AMBIENT_RAISE operation.
Each of the above "base" flags has a companion
"locked" flag. Setting any of the "locked" flags is
irreversible, and has the effect of preventing further changes to the
corresponding "base" flag. The locked flags are:
SECBIT_KEEP_CAPS_LOCKED, SECBIT_NO_SETUID_FIXUP_LOCKED,
SECBIT_NOROOT_LOCKED, and
SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED.
The securebits flags can be modified and retrieved using
the prctl(2) PR_SET_SECUREBITS and PR_GET_SECUREBITS
operations. The CAP_SETPCAP capability is required to modify the
flags. Note that the SECBIT_* constants are available only after
including the <linux/securebits.h> header file.
The securebits flags are inherited by child processes.
During an execve(2), all of the flags are preserved, except
SECBIT_KEEP_CAPS which is always cleared.
An application can use the following call to lock itself, and all
of its descendants, into an environment where the only way of gaining
capabilities is by executing a program with associated file
capabilities:
prctl(PR_SET_SECUREBITS,
/* SECBIT_KEEP_CAPS off */
SECBIT_KEEP_CAPS_LOCKED |
SECBIT_NO_SETUID_FIXUP |
SECBIT_NO_SETUID_FIXUP_LOCKED |
SECBIT_NOROOT |
SECBIT_NOROOT_LOCKED);
/* Setting/locking SECBIT_NO_CAP_AMBIENT_RAISE
is not required */
A set-user-ID program whose UID matches the UID that created a
user namespace will confer capabilities in the process's permitted and
effective sets when executed by any process inside that namespace or any
descendant user namespace.
The rules about the transformation of the process's capabilities
during the execve(2) are exactly as described in Transformation of
capabilities during execve() and Capabilities and execution of
programs by root above, with the difference that, in the latter
subsection, "root" is the UID of the creator of the user
namespace.
Traditional (i.e., version 2) file capabilities associate only a
set of capability masks with a binary executable file. When a process
executes a binary with such capabilities, it gains the associated
capabilities (within its user namespace) as per the rules described in
Transformation of capabilities during execve() above.
Because version 2 file capabilities confer capabilities to the
executing process regardless of which user namespace it resides in, only
privileged processes are permitted to associate capabilities with a file.
Here, "privileged" means a process that has the CAP_SETFCAP
capability in the user namespace where the filesystem was mounted (normally
the initial user namespace). This limitation renders file capabilities
useless for certain use cases. For example, in user-namespaced containers,
it can be desirable to be able to create a binary that confers capabilities
only to processes executed inside that container, but not to processes that
are executed outside the container.
Linux 4.14 added so-called namespaced file capabilities to support
such use cases. Namespaced file capabilities are recorded as version 3
(i.e., VFS_CAP_REVISION_3) security.capability extended
attributes. Such an attribute is automatically created in the circumstances
described in File capability extended attribute versioning above.
When a version 3 security.capability extended attribute is created,
the kernel records not just the capability masks in the extended attribute,
but also the namespace root user ID.
As with a binary that has VFS_CAP_REVISION_2 file
capabilities, a binary with VFS_CAP_REVISION_3 file capabilities
confers capabilities to a process during execve(). However,
capabilities are conferred only if the binary is executed by a process that
resides in a user namespace whose UID 0 maps to the root user ID that is
saved in the extended attribute, or when executed by a process that resides
in a descendant of such a namespace.
For further information on the interaction of capabilities and
user namespaces, see user_namespaces(7).