Libseccomp: RFE: estender o suporte SCMP_FLTATR_API_SYSRAWRC para a API de notificação

Criado em 13 nov. 2020  ·  5Comentários  ·  Fonte: seccomp/libseccomp

A implementação de seccomp_notify_receive() apenas usa:

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

Independentemente do erro em errno , ele retorna -ECANCELED .

Ao depurar com strace, descobri que o ioctl retornou EINTR por causa do sinal 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)

O sinal SIGURL é gerado pelo runtime Golang, veja detalhes em https://go-review.googlesource.com/c/go/+/232862/
De acordo com esse relatório, o syscall deve ser reeditado apenas ao obter o EINTR.
Idealmente, o libseccomp deve cuidar disso, para que seja transparente para os usuários.

Como solução alternativa, tentei reemitir o syscall chamando seccomp_notify_receive() no meu programa e fazer o mesmo em seccomp_notify_respond() porque tem o mesmo padrão:

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

Mas às vezes recebo o valor de retorno errno = ENOENT:

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

libseccomp não me permite distinguir entre ENOENT (o processo de destino foi interrompido logo antes de chamar SECCOMP_IOCTL_NOTIF_SEND ) e EINTR (o agente seccomp foi interrompido pelo sinal SIGURG).

Além disso, não consigo ler errno de Golang, então não posso ter uma solução alternativa.

enhancement prioritmedium

Comentários muito úteis

Mas as novas funções... estão usando _rc_filter() e não _rc_filter_sys()...

Ah... desculpe por isso. Na verdade, é mais profundo do que o nível da API, procure em "system.c" e você verá que as chamadas de nível de sistema libseccomp não as propagam até as funções de nível de API. Olhando para as páginas de manual, parece que não fazemos nenhuma reclamação sobre SCMP_FLTATR_API_SYSRAWRC para a API de notificação (veja seccomp_load(3) para um contra-exemplo).

Vou em frente e reabrir isso como um RFE, já que atualmente não fazemos nenhuma reclamação sobre isso funcionar.

@drakenclimber Acho que este é o material v2.6.x (possivelmente v2.5.2), pois não quero retardar o lançamento da v2.5.1. Se você pensar de outra forma, deixe-me saber.

Todos 5 comentários

Olá @alban.

Veja SCMP_FLTATR_API_SYSRAWRC na página de manual seccomp_attr_set(3) :

Um sinalizador para especificar se libseccomp deve passar códigos de erro do sistema de volta para o chamador em vez do padrão -ECANCELED. O padrão é desligado (valor == 0).

Forçamos -ECANCELED neste caso para garantir uma promessa de código de retorno estável na API libseccomp em diferentes versões do kernel/libc. Oferecemos o SCMP_FLTATR_API_SYSRAWRC para chamadores que ainda desejam ver o código de retorno real do kernel/libc, apenas esteja avisado que não garantimos um código de retorno estável se você habilitar esse atributo.

Vou encerrar esta edição como NOTABUG, mas sinta-se à vontade para continuar discutindo isso aqui se tiver dúvidas adicionais. Podemos reabrir se parecer que há um problema real que precisa ser resolvido.

Oi @pcmoore , obrigado pela resposta rápida.

Oferecemos o SCMP_FLTATR_API_SYSRAWRC para chamadores que ainda desejam ver o código de retorno real do kernel/libc

Mas as novas funções

  • seccomp_notify_receive
  • seccomp_notify_respond
  • seccomp_notify_id_valid

estão usando _rc_filter() e não _rc_filter_sys() , então SCMP_FLTATR_API_SYSRAWRC não deve ter efeito, se não me engano.

Mas as novas funções... estão usando _rc_filter() e não _rc_filter_sys()...

Ah... desculpe por isso. Na verdade, é mais profundo do que o nível da API, procure em "system.c" e você verá que as chamadas de nível de sistema libseccomp não as propagam até as funções de nível de API. Olhando para as páginas de manual, parece que não fazemos nenhuma reclamação sobre SCMP_FLTATR_API_SYSRAWRC para a API de notificação (veja seccomp_load(3) para um contra-exemplo).

Vou em frente e reabrir isso como um RFE, já que atualmente não fazemos nenhuma reclamação sobre isso funcionar.

@drakenclimber Acho que este é o material v2.6.x (possivelmente v2.5.2), pois não quero retardar o lançamento da v2.5.1. Se você pensar de outra forma, deixe-me saber.

Obrigado!

Para constar, encontrei a solução alternativa no lado de Golang para poder distinguir ENOENT e EINTR, com este padrão de código:

-   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
    }

Com isso, parece funcionar bem com libseccomp-2.5.0,

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

kloetzl picture kloetzl  ·  19Comentários

pcmoore picture pcmoore  ·  20Comentários

drakenclimber picture drakenclimber  ·  10Comentários

oxr463 picture oxr463  ·  4Comentários

pcmoore picture pcmoore  ·  10Comentários