Libseccomp: ОШИБКА: Обработка A2 нарушена при переработке src / db.c

Созданный на 26 февр. 2018  ·  18Комментарии  ·  Источник: seccomp/libseccomp

Чтобы проверить предлагаемые мной улучшения производительности двоичного дерева, я написал нереалистичный набор правил для 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);
bug priorithigh

Все 18 Комментарий

Кстати, я сделаю все, что смогу, чтобы устранить причину этого

Используя 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. Я думаю, это готово

Закрытие, поскольку теперь эта проблема должна быть решена (см. Историю выше).

Была ли эта страница полезной?
0 / 5 - 0 рейтинги