См. Проблему № 249, в частности этот комментарий :
Зачем проверять несуществующий системный вызов 4294957285 в фактически сгенерированном bpf?
Мы не должны, и раньше мы этого не делали, но похоже, что в текущей libseccomp есть ошибка.
Благодарим @ vt-alt за сообщение об этой ошибке.
РЕПРОДУКТОР УДАЛЕН В СЛУЧАЕ УЛУЧШЕННОЙ ТЯГИ НИЖЕ
Чтобы было ясно, мы все равно должны генерировать псевдосистемные вызовы в PFC для целей отладки, но мы не должны генерировать (бесполезное) правило фильтра BPF.
Спасибо за создание проблемы из моего отчета.
Чтобы было ясно, мы все равно должны генерировать псевдосистемные вызовы в PFC для целей отладки, но мы не должны генерировать (бесполезное) правило фильтра BPF.
Пожалуйста, подумайте еще раз. Я считаю, что это только усложнит и затемнит ситуацию, если PFC не будет отражать BPF.
Пожалуйста, подумайте еще раз. Я считаю, что это только усложнит и затемнит ситуацию, если PFC не будет отражать BPF.
Если системный вызов отсутствует в PFC, мы получим несколько ложных отчетов об ошибках, в которых говорится о том, что библиотека не может добавить фильтр для (несуществующих) системных вызовов.
Для тех, кто понимает концепцию псевдосистемных вызовов, удаление их из вывода PFC - тривиальное упражнение. Также стоит упомянуть, что вывод PFC не предназначен для того, чтобы быть точной копией вывода BPF, это просто инструмент отладки и простой способ визуализировать сгенерированный код фильтра.
простой способ визуализировать сгенерированный код фильтра
Но тогда он не будет визуализировать _генерированный_ код фильтра, поскольку в сгенерированном коде должны отсутствовать псевдосистемные вызовы.
Если системный вызов отсутствует в PFC, мы получим несколько ложных отчетов об ошибках, в которых говорится о том, что библиотека не может добавить фильтр для (несуществующих) системных вызовов.
Намного легче понять, что в коде не должно быть проверок псевдосистемных вызовов (как в случае «оптимизировано», потому что «для арки нет таких системных вызовов»), чем логическое различие (наличие и отсутствие условных выражений) в коде. визуализация кода и собственно кода.
Я бы предпочел, чтобы PFC отражал bpf, чем использовать scmp_bpf_disasm
поскольку вывод PFC намного легче читать.
Я понимаю вашу озабоченность @ vt-alt, и, возможно, в будущем выпуске мы сделаем это с помощью PFC, но я считаю, что удаление псевдосистемных вызовов из вывода PFC является ошибкой.
@drakenclimber, у вас есть твердое мнение по этому
Доработанный репродуктор для x86_64:
#include <stdlib.h>
#include <errno.h>
#include <seccomp.h>
#include "util.h"
int main(int argc, char *argv[])
{
int rc;
struct util_options opts;
scmp_filter_ctx ctx = NULL;
rc = util_getopt(argc, argv, &opts);
if (rc < 0)
goto out;
ctx = seccomp_init(SCMP_ACT_KILL);
if (ctx == NULL)
return ENOMEM;
rc = seccomp_arch_add(ctx, SCMP_ARCH_X32);
if (rc < 0)
goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);
if (rc < 0)
goto out;
rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(arm_fadvise64_64), 0);
if (rc < 0)
goto out;
rc = util_filter_output(&opts, ctx);
if (rc)
goto out;
out:
seccomp_release(ctx);
return (rc < 0 ? -rc : rc);
}
ОБНОВЛЕНО: исправлена проблема с ЦКИП
Еще не полностью протестирован, но это может быть исправление - можете ли вы убедиться, что это разумно для алгоритма оптимизации сбалансированного дерева @drakenclimber?
diff --git a/src/arch-arm.c b/src/arch-arm.c
index 3465111..4dd4b63 100644
--- a/src/arch-arm.c
+++ b/src/arch-arm.c
@@ -54,7 +54,7 @@ int arm_syscall_resolve_name_munge(const char *name)
if (sys == __NR_SCMP_ERROR)
return sys;
- return sys + __SCMP_NR_BASE;
+ return (sys | __SCMP_NR_BASE);
}
/**
@@ -68,7 +68,7 @@ int arm_syscall_resolve_name_munge(const char *name)
*/
const char *arm_syscall_resolve_num_munge(int num)
{
- return arm_syscall_resolve_num(num - __SCMP_NR_BASE);
+ return arm_syscall_resolve_num(num & (~__SCMP_NR_BASE));
}
const struct arch_def arch_def_arm = {
diff --git a/src/arch-x32.c b/src/arch-x32.c
index 7b97fb3..3890968 100644
--- a/src/arch-x32.c
+++ b/src/arch-x32.c
@@ -43,7 +43,7 @@ int x32_syscall_resolve_name_munge(const char *name)
if (sys == __NR_SCMP_ERROR)
return sys;
- return sys + X32_SYSCALL_BIT;
+ return (sys | X32_SYSCALL_BIT);
}
/**
@@ -57,7 +57,7 @@ int x32_syscall_resolve_name_munge(const char *name)
*/
const char *x32_syscall_resolve_num_munge(int num)
{
- return x32_syscall_resolve_num(num - X32_SYSCALL_BIT);
+ return x32_syscall_resolve_num(num & (~X32_SYSCALL_BIT));
}
const struct arch_def arch_def_x32 = {
diff --git a/src/gen_bpf.c b/src/gen_bpf.c
index 55a7958..ae9c3f4 100644
--- a/src/gen_bpf.c
+++ b/src/gen_bpf.c
@@ -1555,6 +1555,10 @@ static int _gen_bpf_syscalls(struct bpf_state *state,
for (s_iter = s_tail; s_iter != NULL; s_iter = s_iter->pri_prv) {
if (!s_iter->valid)
continue;
+ /* skip pseudo-syscalls */
+ if ((s_iter->num & 0x80000000) &&
+ (state->attr->api_tskip == 0 || s_iter->num != -1))
+ continue;
if (*bintree_levels > 0 &&
((syscall_cnt + empty_cnt) % SYSCALLS_PER_NODE) == 0)
Я понимаю вашу озабоченность @ vt-alt, и, возможно, в будущем выпуске мы сделаем это с помощью PFC, но я считаю, что удаление псевдосистемных вызовов из вывода PFC является ошибкой.
@drakenclimber, у вас есть твердое мнение по этому
Не совсем, но я думаю, что корень проблемы в том, что выход PFC используется разными способами:
Возможно, мы могли бы добавить флаг --no-pseudo-syscalls
в логику PFC? Тогда он может остаться прежним для начинающих пользователей, но продвинутые пользователи могут получить лучшее приближение BPF.
_UPDATED: исправлена проблема с TSKIP_
Еще не полностью протестирован, но это может быть исправление - можете ли вы убедиться, что это разумно для алгоритма оптимизации сбалансированного дерева @drakenclimber?
Сделаю. Я хочу посмотреть, смогу ли я сделать автоматический тест, который воспроизведет этот сценарий.
_UPDATED: исправлена проблема с TSKIP_
Еще не полностью протестирован, но это может быть исправление - можете ли вы убедиться, что это разумно для алгоритма оптимизации сбалансированного дерева @drakenclimber?Сделаю. Я хочу посмотреть, смогу ли я сделать автоматический тест, который воспроизведет этот сценарий.
И, конечно же, я начну с теста репродуктора, который у вас был выше. Спасибо!
_UPDATED: исправлена проблема с TSKIP_
Еще не полностью протестирован, но это может быть исправление - можете ли вы убедиться, что это разумно для алгоритма оптимизации сбалансированного дерева @drakenclimber?
Двоичное дерево предварительно вычисляет, когда необходимо изменить аккумулятор, и именно так оно узнает, что нужно вставить логику jge
. Удаление системных вызовов (как в предложенном выше) при построении фильтра нарушает эту логику.
Я тоже еще не полностью протестировал свои изменения :), но я почти уверен, что нам понадобится что-то подобное, чтобы двоичное дерево работало с удалением псевдо-системных вызовов. Я сгенерировал двоичное дерево BPF, используя это, и это выглядит разумно. По мере того, как мы приближаемся к готовому к производству решению, я полностью проверю его.
@@ -1532,11 +1532,31 @@ static int _gen_bpf_syscalls(struct bpf_state *state,
_sys_sort(db_secondary->syscalls, &s_head, &s_tail, optimize);
if (optimize == 2) {
+ /* since pseudo-syscalls are removed from the filter, we need
+ * to calculate the syscall count by hand
+ */
+ for (s_iter = s_tail; s_iter != NULL; s_iter = s_iter->pri_prv) {
+ if (!s_iter->valid)
+ continue;
+
+ /* skip pseudo-syscalls */
+ if ((s_iter->num & 0x80000000) &&
+ (state->attr->api_tskip == 0 || s_iter->num != -1))
+ continue;
+
+ syscall_cnt++;
+ }
+
rc = _gen_bpf_init_bintree(&bintree_hashes, &bintree_syscalls,
- bintree_levels, db->syscall_cnt,
+ bintree_levels, syscall_cnt,
&empty_cnt);
if (rc < 0)
goto out;
+
+ /* reset the syscall_cnt variable because later in this
+ * function it's used as a counter
+ */
+ syscall_cnt = 0;
}
Это можно было бы сделать умнее / быстрее, если бы у нас была переменная в структуре db
отслеживающая "действительный" счетчик системных вызовов.
Возможно, мы могли бы добавить в логику PFC флаг --no-pseudo-syscalls?
Куда денется этот флаг? Я не думаю, что мы хотим использовать это как вариант во время сборки. Я полагаю, мы могли бы добавить опцию фильтра, но меня это не особо радует. Я бы проголосовал за то, чтобы придерживаться псевдосистемных вызовов в PFC, но убрать их из BPF (очевидно) на данный момент, и если нам понадобится увеличить это в какой-то момент в будущем, мы сможем.
Я тоже еще не полностью протестировал свои изменения :), но я почти уверен, что нам понадобится что-то подобное, чтобы двоичное дерево работало с удалением псевдо-системных вызовов. Я сгенерировал двоичное дерево BPF, используя это, и это выглядит разумно. По мере того, как мы приближаемся к готовому к производству решению, я полностью проверю его.
Я подозревал, что это нарушит оптимизацию дерева.
@drakenclimber, учитывая, что это влияет на сортировку дерева гораздо больше, чем стандартная оптимизация, вы хотите решить эту проблему? Не стесняйтесь украсть столько или меньше кода, который я скопировал и вставил выше, насколько это имеет смысл.
Одна вещь, которую я думаю, мы должны сделать, несмотря на это, - это изменения в "arch-arm.c" и "arch-x32.c", поскольку это имеет больше смысла.
Возможно, мы могли бы добавить в логику PFC флаг --no-pseudo-syscalls?
Куда денется этот флаг? Я не думаю, что мы хотим использовать это как вариант во время сборки. Я полагаю, мы могли бы добавить опцию фильтра, но меня это не особо радует. Я бы проголосовал за то, чтобы придерживаться псевдосистемных вызовов в PFC, но убрать их из BPF (очевидно) на данный момент, и если нам понадобится увеличить это в какой-то момент в будущем, мы сможем.
Признаюсь, я напечатал раньше, чем подумал. ;)
Да, это должна быть опция фильтра, и это неправильно. Я согласен; давайте сделаем так, как вы изложили выше. Если мы продолжим получать вопросы, мы можем вернуться к ним.
Я тоже еще не полностью протестировал свои изменения :), но я почти уверен, что нам понадобится что-то подобное, чтобы двоичное дерево работало с удалением псевдо-системных вызовов. Я сгенерировал двоичное дерево BPF, используя это, и это выглядит разумно. По мере того, как мы приближаемся к готовому к производству решению, я полностью проверю его.
Я подозревал, что это нарушит оптимизацию дерева.
@drakenclimber, учитывая, что это влияет на сортировку дерева гораздо больше, чем стандартная оптимизация, вы хотите решить эту проблему? Не стесняйтесь украсть столько или меньше кода, который я скопировал и вставил выше, насколько это имеет смысл.
Одна вещь, которую я думаю, мы должны сделать, несмотря на это, - это изменения в "arch-arm.c" и "arch-x32.c", поскольку это имеет больше смысла.
Конечно. Я могу владеть этим.
@drakenclimber "> Как упоминалось выше, для новых (бывших) пользователей это простой способ примерно проверить свой фильтр"
«Псевдо-системный вызов» не существует в ядре, и это тоже не очень известная концепция. Это чисто изобретение libseccomp и здесь не объясняется. Заявлено только, что это отрицательные числа, и они появляются, когда данный системный вызов не существует для данной архитектуры. Чем это отличается от несуществующего системного вызова? С какой целью они отрицательные? Концепция псевдосистемного вызова действительно сбивает с толку новых пользователей.
Я не могу поверить, что новые (бывшие) пользователи хотят видеть несуществующие системные вызовы, отмеченные в их фильтрах.
Позвольте мне добавить еще один момент. Все это в сфере безопасности, где работает только тщательное и детальное понимание. Вы создаете новые непонятные концепции (псевдосистемные вызовы) и разницу между представлениями (bpf и pfc). Неужели это действительно предназначено для новых пользователей, чтобы еще больше запутать их?
@ vt-alt благодарим вас за проявленное беспокойство, но в выпуске v2.5.0 мы собираемся подавить псевдосистемные вызовы из фильтра BPF и продолжать отображать их в фильтре PFC. Я понимаю, что вы можете не согласиться с этим решением, но прошу вас уважать это решение. В будущих выпусках мы будем лучше объяснять цель псевдосистемных вызовов (это для поддержки нескольких ABI) и документировать ее на страницах руководства; Я создал проблему для этого (ссылка ниже), приглашаем вас принять участие в этом обсуждении и любых связанных с этим PR. Также возможно, что мы пересмотрим наш подход к фильтру PFC в будущем, но я не хочу здесь ничего обещать.
Еще раз благодарю вас за то, что вы обратили наше внимание на проблему BPF; вы помогли улучшить следующий выпуск libseccomp!
Закрытие через # 264.