Para testar minha proposta de melhorias de desempenho de árvore binária, escrevi um conjunto irreal de regras para read () e seu argumento de tamanho de buffer (A2). Mas parece que o commit de retrabalho src / db.c (ce3dda9a1) quebrou o processamento de A2 - pelo menos para este caso de teste.
Antes do commit de retrabalho do banco de dados, uma leitura como a seguinte - read(devzero_fd, buf, 8000)
- retornou -10
. Após este commit, ele agora retorna -5
.
Aqui está o código C que usei para gerar minhas regras read () bobas:
/* read */
for (i = 5; i <= 12; i++) {
rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(i), SCMP_SYS(read), 1,
SCMP_A2(SCMP_CMP_GT, 4 << i));
if (rc < 0) {
fprintf(stdout, "%s:%d Failed to add read rule %d : rc = %d\n",
__FUNCTION__, __LINE__, i, rc);
goto error;
}
}
rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
SCMP_A2(SCMP_CMP_LE, 64));
if (rc < 0) {
fprintf(stdout, "%s:%d Failed to add read allow rule : rc = %d\n",
__FUNCTION__, __LINE__, rc);
goto error;
}
E aqui está o PFC gerado:
# filter for syscall "read" (0) [priority: 65525]
if ($syscall == 0)
if ($a2.hi32 >= 0)
if ($a2.lo32 > 64)
else
action ALLOW;
if ($a2.lo32 > 16384)
action ERRNO(12);
if ($a2.lo32 > 8192)
action ERRNO(11);
if ($a2.lo32 > 4096)
action ERRNO(10);
if ($a2.lo32 > 2048)
action ERRNO(9);
if ($a2.lo32 > 1024)
action ERRNO(8);
if ($a2.lo32 > 512)
action ERRNO(7);
if ($a2.lo32 > 256)
action ERRNO(6);
if ($a2.lo32 > 128)
action ERRNO(5);
else
action ALLOW;
# default action
action ERRNO(34);
A propósito, farei o que puder para ajudar a causar a raiz disso
Usando scmp_bpf_disasm, o libseccomp mais recente está colocando os saltos na ordem incorreta
CABEÇA
0014: 0x25 0x11 0x00 0x00000080 jgt 128 true:0032 false:0015
0015: 0x25 0x0f 0x00 0x00000100 jgt 256 true:0031 false:0016
0016: 0x25 0x0d 0x00 0x00000200 jgt 512 true:0030 false:0017
0017: 0x25 0x0b 0x00 0x00000400 jgt 1024 true:0029 false:0018
0018: 0x25 0x09 0x00 0x00000800 jgt 2048 true:0028 false:0019
0019: 0x25 0x07 0x00 0x00001000 jgt 4096 true:0027 false:0020
0020: 0x25 0x05 0x00 0x00002000 jgt 8192 true:0026 false:0021
0021: 0x25 0x03 0x00 0x00004000 jgt 16384 true:0025 false:0022
0022: 0x25 0x01 0x00 0x00000040 jgt 64 true:0024 false:0023
0023: 0x06 0x00 0x00 0x7fff0000 ret ALLOW
pré-retrabalho
0014: 0x25 0x01 0x00 0x00000040 jgt 64 true:0016 false:0015
0015: 0x06 0x00 0x00 0x7fff0000 ret ALLOW
0016: 0x25 0x0f 0x00 0x00004000 jgt 16384 true:0032 false:0017
0017: 0x25 0x0d 0x00 0x00002000 jgt 8192 true:0031 false:0018
0018: 0x25 0x0b 0x00 0x00001000 jgt 4096 true:0030 false:0019
0019: 0x25 0x09 0x00 0x00000800 jgt 2048 true:0029 false:0020
0020: 0x25 0x07 0x00 0x00000400 jgt 1024 true:0028 false:0021
0021: 0x25 0x05 0x00 0x00000200 jgt 512 true:0027 false:0022
0022: 0x25 0x03 0x00 0x00000100 jgt 256 true:0026 false:0023
0023: 0x25 0x01 0x00 0x00000080 jgt 128 true:0025 false:0024
0024: 0x06 0x00 0x00 0x00050022 ret ERRNO(34)
Interessante. Portanto, o PFC parece estar "correto", mas o BPF gerado está ... ao contrário. Ímpar. Especialmente considerando que o commit não alterou o código de geração do BPF.
Eu me pergunto se os valores de prioridade estão ficando bagunçados de alguma forma?
Desculpe pela ambigüidade. O PFC (lançar a modificação de retrabalho) também está na ordem incorreta. O PFC que postei acima é a ordem em que estava antes do retrabalho do db.c.
Aqui está o PFC gerado atualmente pelo HEAD
# filter for syscall "read" (0) [priority: 65525]
if ($syscall == 0)
if ($a2.hi32 >= 0)
if ($a2.lo32 > 128)
action ERRNO(5);
if ($a2.lo32 > 256)
action ERRNO(6);
if ($a2.lo32 > 512)
action ERRNO(7);
if ($a2.lo32 > 1024)
action ERRNO(8);
if ($a2.lo32 > 2048)
action ERRNO(9);
if ($a2.lo32 > 4096)
action ERRNO(10);
if ($a2.lo32 > 8192)
action ERRNO(11);
if ($a2.lo32 > 16384)
action ERRNO(12);
if ($a2.lo32 > 64)
else
action ALLOW;
else
action ALLOW;
# default action
action ERRNO(34);
Ok, isso faz um pouco mais de sentido. Os problemas definitivamente residem em algum lugar na camada db.
É um pouco engraçado como é exatamente ao contrário.
Eu encontrei o problema. No gerenciamento de argumento da cadeia, o comportamento de lvl_nxt e lvl_prv mudou após o retrabalho db.c massivo. Algumas pequenas mudanças em _db_tree_add () o tornaram compatível com o comportamento anterior do libseccomp.
Aqui está um branch com a correção
https://github.com/drakenclimber/libseccomp/tree/issues/112
Vou limpar as alterações, adicionar um ou dois testes e garantir que a cobertura do código seja adequada.
Eu encontrei algum tempo esta manhã, provavelmente pouco antes de você postar o acima, e decidi dar uma olhada nisso um pouco. Parece que chegamos praticamente à mesma conclusão, embora as correções sejam um pouco diferentes. Aqui está minha correção atual, embora, como a sua, ela precise de algum trabalho / limpeza adicional:
Não tenho certeza de qual abordagem eu gosto mais agora, preciso pensar um pouco sobre isso, pensamentos?
Hmmm ... eu não vou mentir; Não estou apaixonado por nenhuma das soluções neste momento.
O meu é simples, mas ignorou completamente _db_tree_prune () que - como você disse em sua essência - provavelmente tem problemas semelhantes.
Gosto da sua ideia de retrabalhar a macro gt () para utilizar as macros lt () e eq (), mas elas estão ficando complicadas - especialmente lt (). Existe alguma razão para não converter lt () em uma função embutida?
EDIT - Acabei de notar que você fez um comentário semelhante na essência.
Eu executei o gdb contra o antigo libseccomp e HEAD, e os comportamentos de lvl_prv e lvl_nxt mudaram, mas talvez isso não seja um grande problema, já que é uma variável interna que ninguém deveria ver além de nós.
Acho que depois de toda essa divagação ... não sei. Eu concordo, preciso pensar sobre isso;)
Hmmm ... eu não vou mentir; Não estou apaixonado por nenhuma das soluções neste momento.
Estou preocupado que haja alguns bugs sutis com a reordenação de um nível de árvore como este, embora pareça que talvez o nível tenha sido reordenado por aquele commit anterior e este é um dos bugs sutis.
De qualquer forma, quero entender qual deve ser a ordem desejada para um nível: "maior" primeiro ou "maior" por último. Assim que entendermos isso, podemos prosseguir com os testes / consertos. Eu acho que a resposta, mesmo que por nenhuma outra razão além da compatibilidade com versões 2.x anteriores, é "maior" primeiro, mas não posso dizer isso com certeza neste momento.
O meu é simples, mas ignorou completamente _db_tree_prune () que - como você disse em sua essência - provavelmente tem problemas semelhantes.
Ambos fazem basicamente a mesma coisa em princípio, o meu vai um pouco além, adicionando algumas condições adicionais e limpando a macro db_chain_lt (x, y).
Gosto da sua ideia de retrabalhar a macro gt () para utilizar as macros lt () e eq (), mas elas estão ficando complicadas - especialmente lt (). Existe alguma razão para não converter lt () em uma função embutida?
Principalmente por razões históricas. Eles começaram como macros muito mais simples, mas cresceram um pouco a ponto de eu acho que provavelmente deveriam ser funções. Acho que também seria bom avaliar se eles realmente precisam estar no arquivo de cabeçalho, acredito que só sejam usados por src / db.c.
Eu executei o gdb contra o antigo libseccomp e HEAD, e os comportamentos de lvl_prv e lvl_nxt mudaram, mas talvez isso não seja um grande problema, já que é uma variável interna que ninguém deveria ver além de nós.
Sim, é um estado / árvore interna, não estou muito preocupado com isso. O importante é a correção do filtro gerado.
Acho que depois de toda essa divagação ... não sei. Eu concordo, preciso pensar sobre isso;)
Heh. Vamos esperar um ou dois dias e nos reagrupar :) No momento, isso não afeta nenhuma versão lançada, está apenas no branch master, então temos algum tempo para acertar as coisas.
No momento, isso não afeta nenhuma versão lançada, está apenas no branch master, então temos algum tempo para acertar as coisas.
Soa bem. Vou fazer alguns testes enquanto pensamos em um plano
Eu escrevi um programa para avaliar o tratamento atual do seccomp A2. O programa completo está disponível aqui:
https://gist.github.com/drakenclimber/3c6b45ecd973ee495281ef225fa5e54a
Resumindo, regras maiores que são geradas em um pedido "criado pela última vez" e "processado pela primeira vez".
>
regras são criadas em ordem crescente , por exemploseccomp_rule_add(ctx, action1, syscall, 1, SCMP(SCMP_CMP_GT, 10)
seccomp_rule_add(ctx, action2, syscall, 1, SCMP(SCMP_CMP_GT, 20)
seccomp_rule_add(ctx, action3, syscall, 1, SCMP(SCMP_CMP_GT. 30)
if (A2 > 30)
do action3
if (A2 > 20)
do action2
if (A2 > 10)
do action1
>
regras são criadas em ordem decrescente , por exemploseccomp_rule_add(ctx, action3, syscall, 1, SCMP(SCMP_CMP_GT, 30)
seccomp_rule_add(ctx, action2, syscall, 1, SCMP(SCMP_CMP_GT, 20)
seccomp_rule_add(ctx, action1, syscall, 1, SCMP(SCMP_CMP_GT. 10)
if
declarações são inacessíveisif (A2 > 10)
do action1
if (A2 > 20)
do action2
if (A2 > 30)
do action1
<
A2 não são permitidos atualmente pelo seccomp. Isso parece estranho porque não consegui descobrir uma maneira de tornar o <=
equivalente ao filtro >
acimatom<strong i="43">@OracleDesktop</strong> $ ./a2test 3
Failed to add rule
action = 0x5000e op = 0x3 datum = 18000 rc = -17
Mode 3 (LE descending) test failed. rc = -17
tom<strong i="46">@OracleDesktop</strong> $ ./a2test 4
Failed to add rule
action = 0x50006 op = 0x3 datum = 250 rc = -17
Mode 4 (LE ascending) test failed. rc = -17
Estou supondo que a lógica else if
enterrada profundamente em src/db.c
está causando as <
falhas, por exemplo. Não tenho certeza se vale a pena mudar / consertar.
Vou tentar converter parte desse código em testes automatizados para que possamos capturar o comportamento atual.
Conforme está escrito, a essência aqui falhou nos testes automatizados que adicionei na semana passada. Vou me aprofundar e tentar descobrir o porquê.
batch name: 43-sim-a2_order
test mode: c
test type: bpf-sim
Test 43-sim-a2_order%%001-00001 result: SUCCESS
Test 43-sim-a2_order%%002-00001 result: SUCCESS
Test 43-sim-a2_order%%003-00001 result: SUCCESS
Test 43-sim-a2_order%%004-00001 result: SUCCESS
Test 43-sim-a2_order%%005-00001 result: SUCCESS
Test 43-sim-a2_order%%006-00001 result: SUCCESS
Test 43-sim-a2_order%%007-00001 result: SUCCESS
Test 43-sim-a2_order%%008-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%009-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%010-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%011-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%012-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%013-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%014-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%015-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%016-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%017-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%018-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%019-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Test 43-sim-a2_order%%020-00001 result: FAILURE bpf_sim resulted in ERRNO(5)
Meu mal - eu apliquei mal a essência. Os testes estão passando. Ufa :)
Ha! :)
Achei que tinha feito os testes contra ele, mas estava brincando com muitas coisas naquela época, então achei que estava apenas me lembrando errado. Obrigado por continuar a olhar para isso, ainda estou um pouco atolado com SELinux e auditoria, mas como o kernel está em -rc5 agora, espero que ele se acalme assim que eu interromper o novo código antes da fusão janela ...
Sem problemas. Essa é definitivamente uma prioridade mais alta.
Estive examinando sua essência em vários testes irrealistas. Eu não consegui quebrar, mas também estou apenas exercitando pedaços de _db_tree_prune () até agora. Estou começando a me sentir mais confortável com as mudanças, mas quero dedicar um pouco mais de tempo.
Eu cutuquei e cutuquei o código _db_tree_prune () e não consegui decifrá-lo. O teste 08-sim-subtree_checks realmente faz um bom trabalho ao testar a maioria dos caminhos de código em prune ().
Acho que as mudanças em sua essência estão prontas.
Enviei a solicitação pull # 115. Eu acho que isso está pronto para rolar
Fechando, pois isso agora deve ser resolvido (consulte o histórico acima).