Libseccomp: RFE: расширить поддержку SCMP_FLTATR_API_SYSRAWRC для API уведомлений.

Созданный на 13 нояб. 2020  ·  5Комментарии  ·  Источник: seccomp/libseccomp

Реализация seccomp_notify_receive() просто использует:

        if (ioctl(fd, SECCOMP_IOCTL_NOTIF_RECV, req) < 0)
                return -ECANCELED;

Независимо от ошибки в errno возвращается -ECANCELED .

При отладке с помощью strace я обнаружил, что ioctl возвращает EINTR из-за сигнала SIGURG:

1448850 ioctl(7, SECCOMP_IOCTL_NOTIF_RECV <unfinished ...>
1448230 getpid()                        = 1448217
1448230 tgkill(1448217, 1448850, SIGURG) = 0
1448850 <... ioctl resumed>, 0x7fc65d49ecd0) = -1 EINTR (Interrupted system call)

Сигнал SIGURL генерируется средой выполнения Golang, подробности см. в https://go-review.googlesource.com/c/go/+/232862/ .
Согласно этому отчету, системный вызов следует просто повторить при получении EINTR.
В идеале libseccomp должен позаботиться об этом, чтобы он был прозрачным для пользователей.

В качестве обходного пути я попытался повторить системный вызов, вызвав seccomp_notify_receive() в своей программе, и сделать то же самое в seccomp_notify_respond() , потому что он имеет тот же шаблон:

        if (ioctl(fd, SECCOMP_IOCTL_NOTIF_SEND, resp) < 0)
                return -ECANCELED;

Но иногда я получаю возвращаемое значение errno = ENOENT:

1497880 ioctl(12, SECCOMP_IOCTL_NOTIF_SEND, 0x7f718fd28e10) = -1 ENOENT (No such file or directory)

libseccomp не позволяет мне различать ENOENT (целевой процесс был прерван непосредственно перед вызовом SECCOMP_IOCTL_NOTIF_SEND ) и EINTR (агент seccomp был прерван сигналом SIGURG).

Кроме того, я не могу прочитать errno с Golang, поэтому у меня нет обходного пути.

enhancement prioritmedium

Самый полезный комментарий

Но новые функции... используют _rc_filter(), а не _rc_filter_sys()...

Ах... извините за это. На самом деле, это глубже, чем уровень API, посмотрите в «system.c», и вы увидите, что вызовы системного уровня libseccomp не распространяются на функции уровня API. Глядя на справочные страницы, кажется, что мы не делаем никаких заявлений о SCMP_FLTATR_API_SYSRAWRC для API уведомлений (обратный пример см. seccomp_load(3) ).

Я продолжу и снова открою это как RFE, поскольку в настоящее время мы не делаем никаких заявлений об этой работе.

@drakenclimber Я думаю, что это материал версии 2.6.x (возможно, версии 2.5.2), так как я не хочу замедлять выпуск версии 2.5.1. Если вы думаете иначе, дайте мне знать.

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

Привет @alban.

Посмотрите SCMP_FLTATR_API_SYSRAWRC на справочной странице seccomp_attr_set(3) :

Флаг, указывающий, должен ли libseccomp передавать коды системных ошибок вызывающей стороне вместо значения по умолчанию -ECANCELED. По умолчанию отключено (значение == 0).

В этом случае мы принудительно используем -ECANCELED , чтобы гарантировать стабильное обещание кода возврата в API libseccomp для разных версий ядра/libc. Мы предлагаем SCMP_FLTATR_API_SYSRAWRC для вызывающих абонентов, которые все еще хотят видеть фактический код возврата ядра/libc, но имейте в виду, что мы не гарантируем стабильный код возврата, если вы включите этот атрибут.

Я собираюсь закрыть этот вопрос как NOTABUG, но вы можете продолжить обсуждение здесь, если у вас есть дополнительные вопросы. Мы можем возобновить работу, если возникнет реальная проблема, которую необходимо решить.

Привет @pcmoore , спасибо за быстрый ответ.

Мы предлагаем SCMP_FLTATR_API_SYSRAWRC для вызывающих абонентов, которые все еще хотят видеть фактический код возврата ядра/libc.

Но новые функции

  • seccomp_notify_receive
  • seccomp_notify_respond
  • seccomp_notify_id_valid

используют _rc_filter() , а не _rc_filter_sys() , поэтому SCMP_FLTATR_API_SYSRAWRC не должны иметь эффекта, если я не ошибаюсь.

Но новые функции... используют _rc_filter(), а не _rc_filter_sys()...

Ах... извините за это. На самом деле, это глубже, чем уровень API, посмотрите в «system.c», и вы увидите, что вызовы системного уровня libseccomp не распространяются на функции уровня API. Глядя на справочные страницы, кажется, что мы не делаем никаких заявлений о SCMP_FLTATR_API_SYSRAWRC для API уведомлений (обратный пример см. seccomp_load(3) ).

Я продолжу и снова открою это как RFE, поскольку в настоящее время мы не делаем никаких заявлений об этой работе.

@drakenclimber Я думаю, что это материал версии 2.6.x (возможно, версии 2.5.2), так как я не хочу замедлять выпуск версии 2.5.1. Если вы думаете иначе, дайте мне знать.

Спасибо!

Для записи я нашел обходной путь на стороне Golang, чтобы различать ENOENT и EINTR с помощью этого шаблона кода:

-   if retCode := C.seccomp_notify_respond(C.int(fd), resp); retCode != 0 {
-       return errRc(retCode)
+   for {
+       retCode, errno := C.seccomp_notify_respond(C.int(fd), resp)
+       if errno == syscall.EINTR {
+           continue
+       }
+       if errno == syscall.ENOENT {
+           return errno
+       }
+       if retCode != 0 {
+           return errRc(retCode)
+       }
+       break
    }

При этом вроде нормально работает с libseccomp-2.5.0,

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