Чтобы проверить предлагаемые мной улучшения производительности двоичного дерева, я написал нереалистичный набор правил для read () и его аргумента размера буфера (A2). Но похоже, что фиксация переделки src / db.c (ce3dda9a1) нарушила обработку A2 - по крайней мере, для этого тестового примера.
До фиксации переделки базы данных чтение, подобное следующему - read(devzero_fd, buf, 8000)
- возвращало -10
. После этого коммита теперь возвращается -5
.
Вот код C, который я использовал для создания своих глупых правил read ():
/* 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;
}
И вот сгенерированный PFC:
# 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);
Кстати, я сделаю все, что смогу, чтобы устранить причину этого
Используя scmp_bpf_disasm, последняя версия libseccomp размещает переходы в неправильном порядке
ГОЛОВА
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
предварительная доработка
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)
Интересно. Итак, PFC кажется "правильным", но сгенерированный BPF ... наоборот. Странный. Тем более, что коммит не изменил код генерации BPF.
Интересно, не перепутались ли как-то значения приоритета?
Извините за двусмысленность. PFC (после изменения доработки) также находится в неправильном порядке. PFC, который я разместил выше, - это порядок, в котором он был до переделки db.c.
Вот PFC, в настоящее время генерируемый 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);
Ладно, в этом есть немного больше смысла. Проблемы определенно живут где-то в слое db.
Немного забавно, как именно наоборот.
Я нашел проблему. В управлении аргументами цепочки поведение lvl_nxt и lvl_prv поменялось местами после масштабной переделки db.c. Пара небольших изменений в _db_tree_add () заставила его соответствовать предыдущему поведению libseccomp.
Вот ветка с исправлением
https://github.com/drakenclimber/libseccomp/tree/issues/112
Я уберу изменения, добавлю пару тестов и проверю, насколько хорошо покрыт код.
Сегодня утром я нашел время, вероятно, незадолго до того,
Я не уверен, какой подход мне больше нравится сейчас, мне нужно немного подумать над этим, мысли?
Хммм ... не буду врать; На данный момент я не в восторге ни от одного из исправлений.
Мой прост, но он полностью игнорирует _db_tree_prune (), который, как вы сказали в своей сути, вероятно, имеет аналогичные проблемы.
Мне нравится ваша идея переработать макрос gt () для использования макросов lt () и eq (), но они становятся громоздкими, особенно lt (). Есть ли причина не преобразовывать lt () во встроенную функцию?
ИЗМЕНИТЬ - Я только что заметил, что вы сделали аналогичный комментарий в сущности.
Я запустил gdb против старых libseccomp и HEAD, и поведение lvl_prv и lvl_nxt изменилось, но, возможно, это не имеет большого значения, поскольку это внутренняя переменная, которую никто не должен видеть, кроме нас.
Думаю, после всей этой бессвязной болтовни ... не знаю. Я согласен, мне нужно подумать над этим;)
Хммм ... не буду врать; На данный момент я не в восторге ни от одного из исправлений.
Меня беспокоит, что есть некоторые тонкие ошибки с переупорядочением такого уровня дерева, хотя кажется, что, возможно, уровень был переупорядочен предыдущей фиксацией, и это одна из тонких ошибок.
В любом случае, я хочу понять, каким должен быть желаемый порядок для уровня: «самый большой» сначала или «самый большой» последний? Как только мы это поймем, мы сможем приступить к тестированию / исправлению. Я думаю, что ответ, хотя бы по какой-либо другой причине, кроме совместимости с предыдущими выпусками 2.x, в первую очередь "самый большой", но я не могу сказать это наверняка на данный момент.
Мой прост, но он полностью игнорирует _db_tree_prune (), который, как вы сказали в своей сути, вероятно, имеет аналогичные проблемы.
Они оба в принципе делают одно и то же, мой идет немного дальше, добавляя некоторые дополнительные условия и очищая макрос db_chain_lt (x, y).
Мне нравится ваша идея переработать макрос gt () для использования макросов lt () и eq (), но они становятся громоздкими, особенно lt (). Есть ли причина не преобразовывать lt () во встроенную функцию?
В основном исторические причины. Они начали жизнь как гораздо более простые макросы, но они довольно сильно выросли до такой степени, что я думаю, что они, вероятно, должны быть функциями. Я думаю, что было бы также хорошо оценить, действительно ли они должны быть в файле заголовка, я считаю, что они используются только src / db.c.
Я запустил gdb против старых libseccomp и HEAD, и поведение lvl_prv и lvl_nxt изменилось, но, возможно, это не имеет большого значения, поскольку это внутренняя переменная, которую никто не должен видеть, кроме нас.
Да, это внутреннее состояние / дерево, меня это не особо беспокоит. Главное - корректность сгенерированного фильтра.
Думаю, после всей этой бессвязной болтовни ... не знаю. Я согласен, мне нужно подумать над этим;)
Хех. Давайте подождем день или два и перегруппируемся :) Сейчас это не влияет ни на какие выпущенные версии, это только в основной ветке, так что у нас есть время, чтобы все исправить.
Сейчас это не влияет ни на какие выпущенные версии, это только в основной ветке, так что у нас есть время, чтобы все исправить.
Звучит отлично. Я проведу несколько тестов, пока мы обдумываем план
Я написал программу для оценки текущей обработки seccomp A2. Вся программа доступна здесь:
https://gist.github.com/drakenclimber/3c6b45ecd973ee495281ef225fa5e54a
Вкратце, правила «больше, чем» создаются в порядке «последний созданный» «первый обработанный».
>
создаются в порядке возрастания , напримерseccomp_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
>
создаются в порядке убывания, напримерseccomp_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
недоступныif (A2 > 10)
do action1
if (A2 > 20)
do action2
if (A2 > 30)
do action1
<
A2 в настоящее время не разрешены seccomp. Это кажется странным, потому что я не смог найти способ сделать <=
эквивалентом фильтра >
выше.tom<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
Я предполагаю, что логика else if
скрытая глубоко в src/db.c
, вызывает сбои <
, например. Не уверен, стоит ли менять / поправлять.
Я попытаюсь преобразовать часть этого кода в автоматизированные тесты, чтобы мы могли фиксировать текущее поведение.
Как было написано, суть здесь не в автоматических тестах, которые я добавил на прошлой неделе. Я покопаюсь и попытаюсь понять, почему.
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)
Мое плохое - я неверно истолковал суть. Испытания проходят. Фух :)
Ха! :)
Я думал, что проверил его, но в то время я играл со многими вещами, поэтому решил, что просто неправильно запоминаю. Спасибо, что продолжаете смотреть на это, я все еще немного увяз в SELinux и аудите, но поскольку ядро сейчас находится на -rc5, я ожидаю, что оно скоро успокоится, когда я поставлю паузы в новом коде перед слиянием окно ...
Не стоит беспокоиться. Это определенно более высокий приоритет.
Я проверял вашу суть через различные нереалистичные тесты. У меня еще не получилось сломать его, но я также пока тренирую только отдельные части _db_tree_prune (). Я начинаю чувствовать себя более комфортно с изменениями, но хочу уделить им немного больше времени.
Я тыкал и толкал код _db_tree_prune (), и я не мог его сломать. Test 08-sim-subtree_checks действительно хорошо тестирует большинство путей кода в prune ().
Я думаю, что изменения в твоей сущности - это хорошо.
Я отправил запрос на перенос № 115. Я думаю, это готово
Закрытие, поскольку теперь эта проблема должна быть решена (см. Историю выше).