Libseccomp: RFE: Suporte "versão máxima do kernel"

Criado em 21 ago. 2015  ·  14Comentários  ·  Fonte: seccomp/libseccomp

À medida que as chamadas do sistema são adicionadas ao kernel, sinto que não há discussão suficiente por padrão sobre a ampla variedade de aplicativos que de repente terão acesso a uma nova superfície de ataque.

O exemplo canônico aqui é perf_event_open() , a fonte de vários CVEs. Embora o perf seja incrível, meu (por exemplo) servidor web não deve (por padrão) ser capaz de usá-lo.

É possível usar o secomp hoje na lista negra. listas brancas podem ficar muito difíceis de gerenciar.

Uma coisa que pode ser útil é um filtro para qualquer chamada de sistema mais recente do que uma versão específica do kernel, digamos 3.10. Dessa forma, cada nova chamada de sistema teria que ser verificada para uso, por exemplo, em contêineres antes de ser adicionada. A atualização do kernel não exporia os contêineres de repente a uma nova superfície de ataque.

Em uma discussão com @pcmoore , ele indicou que isso poderia ser outra anotação na estrutura em, por exemplo arch-x86-syscalls.c .

enhancement pendininfo prioritmedium

Comentários muito úteis

Parece que a edição nº 286 é a questão concreta para ajudar a impulsionar esse trabalho ... mesmo que tenha sido quase cinco anos ;)

Acho que o primeiro passo para isso é adicionar um novo campo ao arquivo syscalls.csv que indica quando o syscall foi introduzido pela primeira vez. Isso será uma boa parte do trabalho, pois atualmente temos ~ 469 syscalls definidas (!). No entanto, poderíamos amortizar esse trabalho para as syscalls existentes com um valor "indefinido" que trataríamos simplesmente como a syscall sendo criada no início dos tempos. É claro que todas as novas adições à tabela syscalls.csv precisariam ser adicionadas com a versão do kernel.

Alguns pensamentos mais rápidos:

  • formato syscall.csv
#syscall (v5.8.0-rc5 2020-07-14),kver_min,x86,x86_64,...
accept,<version>,PNR,43,...

... onde <version> pode ser algo como "5_8", "UNDEF" ou similar.

  • tokens de versão
enum kernel_version {
    KV_UNDEF = 0,
    KV_1_0,
    KV_1_1,
    KV_1_3,
    KV_2_0,
    ...
    KV_5_8,
    _KV_MAX,
};

Todos 14 comentários

+1
Isso ajudaria a tornar as listas negras utilizáveis ​​para mitigação de problemas de segurança.

@nmav para ser claro, este RFE é para adicionar informações às tabelas internas do syscall sobre quando o syscall foi introduzido pela primeira vez no kernel do Linux, não para adicionar lógica para determinar se o kernel em execução atual suporta um determinado syscall. No entanto, se você estiver tentando bloquear uma syscall, poderá fazê-lo com libseccomp, independentemente de ser suportado em um determinado arch/ABI e versão do kernel, libseccomp fará a coisa certa para você.

Este RFE tem quase cinco anos e, fora de uma única discussão com @cgwalters , não vi ou ouvi falar de muito outro interesse em tal recurso. Com muitas outras questões em aberto, a maioria com prioridade mais alta, não está claro quando trabalharíamos nisso, ou mesmo se tal coisa seria uma adição útil.

@cgwalters e @drakenclimber o que você acha dessa questão em 2020? Estou tentado a fechar isso como WONTFIX, mas gostaria de obter alguns comentários e feedback antes de darmos esse passo.

@cgwalters e @drakenclimber o que você acha dessa questão em 2020? Estou tentado a fechar isso como WONTFIX, mas gostaria de obter alguns comentários e feedback antes de darmos esse passo.

Sinceramente, acho essa ideia muito legal. Vários dos meus clientes internos estão usando listas de permissões exatamente por esse motivo. Se eles usarem uma lista de negações e uma nova syscall for adicionada ao kernel, essa syscall seria outra avenida de ataque.

Vamos deixá-lo aberto mais um pouco. Vou perguntar na Oracle e ver se algum cliente está interessado o suficiente nesse recurso para eu pegá-lo. Mas @cgwalters (ou qualquer outra pessoa) é totalmente bem-vindo se tiver tempo e interesse :).

Ok, desde que haja interesse, não tenho problema em manter este aberto.

Eu ainda acho que seria útil!

Parece que a edição nº 286 é a questão concreta para ajudar a impulsionar esse trabalho ... mesmo que tenha sido quase cinco anos ;)

Acho que o primeiro passo para isso é adicionar um novo campo ao arquivo syscalls.csv que indica quando o syscall foi introduzido pela primeira vez. Isso será uma boa parte do trabalho, pois atualmente temos ~ 469 syscalls definidas (!). No entanto, poderíamos amortizar esse trabalho para as syscalls existentes com um valor "indefinido" que trataríamos simplesmente como a syscall sendo criada no início dos tempos. É claro que todas as novas adições à tabela syscalls.csv precisariam ser adicionadas com a versão do kernel.

Alguns pensamentos mais rápidos:

  • formato syscall.csv
#syscall (v5.8.0-rc5 2020-07-14),kver_min,x86,x86_64,...
accept,<version>,PNR,43,...

... onde <version> pode ser algo como "5_8", "UNDEF" ou similar.

  • tokens de versão
enum kernel_version {
    KV_UNDEF = 0,
    KV_1_0,
    KV_1_1,
    KV_1_3,
    KV_2_0,
    ...
    KV_5_8,
    _KV_MAX,
};

A versão do kernel é a coisa certa para rastrear? É garantido que syscalls mais recentes não sejam portadas para, por exemplo, ramificações estáveis ​​do kernel com um número de versão inferior?

A Red Hat fará backport de todos os tipos de coisas para seus kernels, então não.

Se o RedHat fizer backport de uma syscall para uma versão mais antiga do kernel, eles também podem corrigir sua versão do libseccomp para corresponder. Embora, para ser justo, isso possa importar mais para certos casos de uso, mas como uma abordagem para corrigir o #286, acho que é bastante viável. O outro problema é que não tenho certeza se há uma abordagem melhor - syscalls podem ser adicionados em ordem não consecutiva (por exemplo openat2 foi adicionado antes close_range - embora este exemplo seja gentil por minha culpa).

Se o RedHat fizer backport de uma syscall para uma versão mais antiga do kernel, eles também podem corrigir sua versão do libseccomp para corresponder.

Sim, exatamente. O projeto libseccomp upstream não tem controle sobre as várias distribuições Linux corporativas e se essas distribuições decidirem se desviar dos projetos upstream (o Kernel Linux ou libseccomp), elas estarão por conta própria para suporte. Embora façamos o nosso melhor para ajudar, não podemos sacrificar o projeto upstream em favor dessas distribuições corporativas com seu próprio suporte e equipe de engenharia.

Como ponto de referência, a página de manual syscalls(2) tem algumas informações históricas sobre quando várias syscalls foram introduzidas no kernel:

Eu posso fazer o syscall spelunking para descobrir um número de versão para cada syscall - a única questão é se devemos ter o número da versão por arquitetura, pois tenho certeza de que certas syscalls foram adicionadas a diferentes arquiteturas em diferentes versões.

... a única questão é se devemos ter o número da versão por arquitetura, pois tenho certeza de que certas syscalls foram adicionadas a diferentes arquiteturas em diferentes versões.

Eles definitivamente eram, e ainda são, até onde eu posso ver. Embora seja um pouco irritante e definitivamente exploda o CSV, rastrear a primeira aparição do syscall para cada arco/ABI é provavelmente a coisa certa a fazer.

Qualquer ajuda que você possa fornecer neste @cyphar seria muito apreciada.

Esta página foi útil?
0 / 5 - 0 avaliações