Реализация 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, поэтому у меня нет обходного пути.
Привет @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.
Но новые функции
используют _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,
Самый полезный комментарий
Ах... извините за это. На самом деле, это глубже, чем уровень API, посмотрите в «system.c», и вы увидите, что вызовы системного уровня libseccomp не распространяются на функции уровня API. Глядя на справочные страницы, кажется, что мы не делаем никаких заявлений о
SCMP_FLTATR_API_SYSRAWRC
для API уведомлений (обратный пример см.seccomp_load(3)
).Я продолжу и снова открою это как RFE, поскольку в настоящее время мы не делаем никаких заявлений об этой работе.
@drakenclimber Я думаю, что это материал версии 2.6.x (возможно, версии 2.5.2), так как я не хочу замедлять выпуск версии 2.5.1. Если вы думаете иначе, дайте мне знать.