Libseccomp: RFE: distinguir syscalls desconhecidos

Criado em 16 ago. 2020  ·  18Comentários  ·  Fonte: seccomp/libseccomp

Acionado por uma discussão (em junho e agosto ) sobre systemd-devel ..

systemd-nspawn escolhe retornar EPERM para syscalls não na lista de permissões. No entanto, isso causa problemas em casos como openat2 , onde a libc verifica ENOSYS e retorna para uma implementação diferente.

Parece-me que uma solução 'quase certa' poderia ser verificar se o número do syscall está dentro do intervalo de syscalls definidos que existiam no momento em que o seccomp foi criado. Tenho certeza de que existem casos de canto (eu sei que alguns arcos fazem coisas estranhas), mas se as ferramentas que analisam syscalls.csv etc pudessem gerar um simples #define para o número máximo conhecido de syscall que pode ser útil?

enhancement prioritmedium

Comentários muito úteis

Com base na discussão acima, parece que a maioria (todas?) das pessoas aqui acredita que o problema #11 é o caminho certo para resolver esse problema; alguém tem um problema em fechar esta questão em favor de mover a discussão futura para a questão original (#11)?

Todos 18 comentários

Olá @srd424. Quero ter certeza de que entendi o que você está pedindo nesta questão ... parece-me que você basicamente gostaria de saber se libseccomp "sabe" sobre um determinado syscall, independentemente de esse syscall específico ser implementado nesse arco /ABI, sim?

Se assim for, acredito que você deve ser capaz de usar seccomp_syscall_resolve_name(...) para obter as informações que deseja. Se o valor de retorno for __NR_SCMP_ERROR então o syscall é desconhecido para libseccomp, se for positivo então o syscall existe no nativo arch/ABI, e se for negativo então o syscall não existe no nativo arch/ ABI. Isso funciona para você?

Isso pode tornar os filtros .. prolixos!

O que eu esperava fazer é ter uma regra de filtro comparando o número de syscall com o número mais alto conhecido e, se maior, retornar ENOSYS , caso contrário, retornar EPERM (assumindo que as syscalls da lista de permissões foram tratadas por uma regra anterior.)

No entanto, olhando para os detalhes de seccomp_rule_add , não tenho certeza se vai funcionar .. o número syscall é tratado especialmente. Presumivelmente, um filtro bpf bruto poderia ser construído para fazer isso, mas isso significaria algumas alterações mais invasivas no libseccomp - provavelmente acima do meu nível de pagamento!

Pode ou não ser uma funcionalidade razoável para adicionar à libseccomp, pois acho que o problema original pode ocorrer para vários usuários da biblioteca. Parece que seria (apenas?) uma questão de gerar uma ação padrão um pouco mais sofisticada.

Isso pode tornar os filtros .. prolixos!

Não tenho certeza do que você quer dizer aqui...? A chamada para seccomp_syscall_resolve_name(...) na verdade não afeta o filtro, apenas consulta o banco de dados interno libseccomp syscall para fazer a resolução do syscall. Você pode chamá-lo uma vez, mil vezes ou nunca e seu filtro será exatamente o mesmo :)

O que eu esperava fazer é ter uma regra de filtro comparando o número de syscall com o número mais alto conhecido e, se maior, retornar ENOSYS, caso contrário, retornar EPERM (assumindo que as syscalls na lista de permissões foram tratadas por uma regra anterior.)

Ok, acho que estou começando a entender o que você está pedindo agora. Você deseja que o filtro em si, não o código do aplicativo, execute uma determinada ação (retorne ENOSYS no exemplo acima) se a syscall for desconhecida para libseccomp? É basicamente isso, ou estou perdendo alguma coisa de novo?

Este comentário no segundo tópico mencionado acima me fez sorrir :+1:

Eu tentei abrir uma discussão sobre o manuseio do ENOSYS em libseccomp em
https://github.com/seccomp/libseccomp/issues/286 , mas provavelmente não estou
sendo muito coerente..

Depois de ler os tópicos que você mencionou, acho que estou na mesma página.

Se alguém (libseccomp, nspawn, qualquer um) puder retornar ENOSYS , a glibc tentará fazer fallback da syscall mais recente, por exemplo, openat2 , para a syscall mais antiga, por exemplo, openat . Retornar EPERM para glibc apenas faz a glibc pensar que a chamada não foi permitida, e a glibc irá desistir. Isso é uma reformulação justa do comentário inicial nesta edição?

Acho o pedido razoável. Preciso pensar um pouco mais se libseccomp pode atender a essas necessidades, mas não tenho objeções neste momento. Há definitivamente oportunidades para melhorar a experiência do usuário final aqui.

Obrigado pelo RF.

Se alguém (libseccomp, nspawn, qualquer um) puder retornar ENOSYS , a glibc tentará fazer fallback da syscall mais recente, por exemplo, openat2 , para a syscall mais antiga, por exemplo, openat . Retornar EPERM para glibc apenas faz a glibc pensar que a chamada não foi permitida, e a glibc irá desistir. Isso é uma reformulação justa do comentário inicial nesta edição?

Sim, isso soa certo. A opinião do pessoal do systemd é que o EPERM é razoável na maioria das vezes para syscalls negadas, presumivelmente porque transmite "não permitido" ao usuário final / administrador. Daí a ideia de distinguir entre syscalls "novas" e "antigas" e fazer ENOSYS para qualquer coisa não reconhecida. Suponho que não queremos enumerar e testar cada syscall no BPF por motivos de desempenho, portanto, rastrear uma marca d'água alta para os números de syscall conhecidos por arco parecia o melhor caminho a seguir.

Seria interessante saber o que docker, podman, lxc etc. fazem com sua filtragem seccomp, para ver se eles se beneficiariam. Nesse meio tempo, fiz um PR para o nspawn que permitiria o registro de eventos seccomp, o que tornaria a depuração um pouco mais fácil.

Acho o pedido razoável. Preciso pensar um pouco mais se libseccomp pode atender a essas necessidades, mas não tenho objeções neste momento. Há definitivamente oportunidades para melhorar a experiência do usuário final aqui.

Obrigado pelo RF.

Concordo com @drakenclimber , esse pedido parece razoável, acho que só preciso de mais tempo para pensar em possíveis soluções :)

Em um nível bastante básico, isso é semelhante ao RFE #11 e, no final, pode ser a maneira mais fácil de implementar isso de uma maneira que não seja terrível para aplicativos: um aplicativo pode especificar uma versão máxima da API do kernel suportada, por exemplo v5.8 (obviamente tokenizado), bem como uma determinada ação para qualquer coisa além e então libseccomp trata do resto. Isso funcionaria para vocês @srd424?

Oi, isso foi discutido também em https://github.com/systemd/systemd/pull/16739.

um aplicativo pode especificar uma versão máxima suportada da API do kernel, por exemplo, v5.8 (obviamente tokenizada), bem como uma determinada ação para qualquer coisa além e, em seguida, libseccomp trata do resto.

Isso funcionaria muito bem. No systemd/systemd-nspawn, gostaríamos de retornar errnos personalizados para qualquer syscall explicitamente permitida e listada negada, EPERM para quaisquer outras na "versão da API do kernel suportada" e ENOSYS para quaisquer novas.

Acho que a implementação não seria muito complicada. Por exemplo, para amd64, syscalls "conhecidas" podem ser expressas como n <= 181 || 186 <= n <= 235 || 237 <= n <= 334 || 424 <= n <= 439 . E tais expressões podem ser facilmente geradas programaticamente a partir das tabelas syscall.

94 também pode estar relacionado.

Estou com pouca cafeína esta manhã, mas ter o controle do ENOSYS nos daria a possibilidade de transformar grandes listas de permissões em pequenas listas de negação para uma possível vitória de desempenho também?

Acho que a implementação não seria muito complicada. Por exemplo, para amd64, syscalls "conhecidas" podem ser expressas como n <= 181 || 186 <= n <= 235 || 237 <= n <= 334 || 424 <= n <= 439. E tais expressões podem ser facilmente geradas programaticamente a partir das tabelas syscall.

Como você mencionou, o BPF real será específico para a versão do arch/ABI e do kernel. No exemplo x86_64 acima, o BPF não será tão ruim, mas não teremos tanta sorte para outros arcos/versões. Independentemente disso, agora são duas questões que estão efetivamente solicitando a mesma coisa, então acho que é algo que queremos fazer... Eu não vou começar a pular para cima e para baixo sobre como será fácil ainda; )

94 também pode estar relacionado.

Tipo sim, tipo não. Envolve intervalos, mas o nº 94 é sobre intervalos de argumentos especificados pelo chamador (o que ainda é algo que acho que queremos fazer, o PR acabou de chegar em um momento ruim e acho que a API precisa de alguns ajustes), enquanto o que estamos falando são intervalos syscall criados implicitamente que são gerados pela própria biblioteca.

Estou com pouca cafeína esta manhã, mas ter o controle do ENOSYS nos daria a possibilidade de transformar grandes listas de permissões em pequenas listas de negação para uma possível vitória de desempenho também?

Do ponto de vista do aplicativo, por exemplo, systemd, se você está tentando bloquear "novas" syscalls, sim ... supondo que estamos falando da mesma coisa :)

Para ser mais específico .. no momento, qualquer pessoa tentando _segurar_ bloquear certas syscalls efetivamente tem que permitir a lista, porque você não pode ter certeza de quais syscalls um kernel mais recente pode adicionar. Se pudermos solicitar que libseccomp bloqueie automaticamente chamadas de sistema desconhecidas, isso significa que podemos alternar com segurança para uma pequena lista de negações?

Para ser mais específico .. no momento, qualquer pessoa tentando _segurar_ bloquear certas syscalls efetivamente tem que permitir a lista, porque você não pode ter certeza de quais syscalls um kernel mais recente pode adicionar. Se pudermos solicitar que libseccomp bloqueie automaticamente chamadas de sistema desconhecidas, isso significa que podemos alternar com segurança para uma pequena lista de negações?

Espero sinceramente que possamos chegar lá, pois isso seria um recurso absolutamente incrível. Por exemplo, o Docker está atualmente empregando uma lista de permissões e sua lista padrão agora é de ~ 240 syscalls (e sempre crescendo).

O impacto no desempenho de uma lista tão grande pode ser proibitivo. Observe que isso pode ser um pouco mitigado usando o recurso de árvore binária que adicionamos na v2.5.

Para ser mais específico .. no momento, qualquer pessoa tentando _segurar_ bloquear certas syscalls efetivamente tem que permitir a lista, porque você não pode ter certeza de quais syscalls um kernel mais recente pode adicionar. Se pudermos solicitar que libseccomp bloqueie automaticamente chamadas de sistema desconhecidas, isso significa que podemos alternar com segurança para uma pequena lista de negações?

Não vejo como isso poderia funcionar. Desconhecido para libseccomp e desconhecido para o autor da lista de negações geralmente significam coisas diferentes. O que significa que o problema conceitual não desaparecerá mesmo se libseccomp tiver uma imagem mais clara das chamadas de sistema suportadas internamente.

Bom ponto - acho que precisaríamos de conjuntos bem definidos marcados pela versão do kernel para que isso funcione, o que parece estar sendo discutido um pouco.

Acho que a implementação não seria muito complicada. Por exemplo, para amd64, syscalls "conhecidas" podem ser expressas como n <= 181 || 186 <= n <= 235 || 237 <= n <= 334 || 424 <= n <= 439. E tais expressões podem ser facilmente geradas programaticamente a partir das tabelas syscall.

Como você mencionou, o BPF real será específico para a versão do arch/ABI e do kernel. No exemplo x86_64 acima, o BPF não será tão ruim, mas não teremos tanta sorte para outros arcos/versões. Independentemente disso, agora são duas questões que estão efetivamente solicitando a mesma coisa, então acho que é algo que queremos fazer... Eu não vou começar a pular para cima e para baixo sobre como será fácil ainda; )

As tabelas são bastante contínuas:

>>> l = {int(s[1]):s[0] for s in (s.split() for s in open('syscalls-x86_64').readlines()) if len(s)>1}; x = np.array(sorted(l.keys())); np.diff(x)
array([ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  5,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1, 90,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1])
>>> l = {int(s[1]):s[0] for s in (s.split() for s in open('syscalls-alpha').readlines()) if len(s)>1}; x = np.array(sorted(l.keys())); np.diff(x)
array([ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  3,  1,  2,  1,  1,
        1,  1,  1,  2,  1,  1,  1,  3, 12,  3,  3,  1, 11,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        2,  1,  1,  1,  1,  1,  1,  5,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1, 39,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  1,  1,  1,  1,  3,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        2,  1,  1,  1])
>>> l = {int(s[1]):s[0] for s in (s.split() for s in open('syscalls-arm').readlines()) if len(s)>1}; x = np.array(sorted(l.keys())); np.diff(x)
array([1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 2, 1, 2, 3, 4,
       1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 3, 1, 1,
       1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 3,
       1, 1, 1, 1, 1, 1, 2, 1, 3, 1, 1, 1, 1, 1, 3, 3, 1, 1, 2, 1, 1, 1,
       1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
>>> l = {int(s[1]):s[0] for s in (s.split() for s in open('syscalls-riscv64').readlines()) if len(s)>1}; x = np.array(sorted(l.keys())); np.diff(x)
array([  1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,  16,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1, 130,   1,   1,   1,   1,   1,   1,   1,
         1,   1,   1,   1,   1,   1,   1,   1])

Eu implementei um filtro de syscalls "conhecidos" para systemd-nspawn em https://github.com/systemd/systemd/pull/16819. https://github.com/systemd/systemd/pull/16819/commits/158e30ffd9355a7640a7276276eb9219b6c87914 tem um dump de alguns programas gerados pelo libseccomp. Esses dumps são longos, então não vou repeti-los aqui, mas SCMP_FLTATR_CTL_OPTIMIZE torna o programa mais eficiente, mas também mais longo. As coisas poderiam ser feitas ~ 50 vezes mais curtas usando comparações de intervalo.

Acabei de encontrar este tópico, apenas entrando em contato para dizer que estive pensando em linhas semelhantes e isso é definitivamente algo que o Docker/runc gostaria de ter resolvido também. Fazer isso com uma versão máxima do kernel é provavelmente a melhor maneira de fazer isso, porque significa que os escritores de perfil (e os tempos de execução do contêiner) não precisam rastrear syscalls adicionados fora de ordem ou qual era o syscall mais recente no momento da escrita o perfil.

Com base na discussão acima, parece que a maioria (todas?) das pessoas aqui acredita que o problema #11 é o caminho certo para resolver esse problema; alguém tem um problema em fechar esta questão em favor de mover a discussão futura para a questão original (#11)?

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

Questões relacionadas

pcmoore picture pcmoore  ·  14Comentários

erdumbledore picture erdumbledore  ·  3Comentários

pcmoore picture pcmoore  ·  20Comentários

grubeli picture grubeli  ·  3Comentários

diekmann picture diekmann  ·  3Comentários