Libseccomp: RFE : étendre la prise en charge de SCMP_FLTATR_API_SYSRAWRC à l'API de notification

Créé le 13 nov. 2020  ·  5Commentaires  ·  Source: seccomp/libseccomp

L'implémentation de seccomp_notify_receive() utilise simplement :

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

Indépendamment de l'erreur dans errno , il renvoie -ECANCELED .

Lors du débogage avec strace, j'ai découvert que l'ioctl retournait EINTR à cause du signal 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)

Le signal SIGURL est généré par le runtime Golang, voir les détails dans https://go-review.googlesource.com/c/go/+/232862/
Selon ce rapport, l'appel système devrait simplement être réémis lors de l'obtention de EINTR.
Idéalement, libseccomp devrait s'en occuper, afin qu'il soit transparent pour les utilisateurs.

Pour contourner le problème, j'ai essayé de réémettre l'appel système en appelant seccomp_notify_receive() dans mon programme, et de faire la même chose dans seccomp_notify_respond() car il a le même modèle :

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

Mais parfois j'obtiens la valeur de retour errno = ENOENT :

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

libseccomp ne me permet pas de faire la distinction entre ENOENT (le processus cible a été interrompu juste avant d'appeler SECCOMP_IOCTL_NOTIF_SEND ) et EINTR (l'agent seccomp a été interrompu par le signal SIGURG).

De plus, je ne peux pas lire errno depuis Golang, donc je ne peux pas avoir de solution de contournement.

enhancement prioritmedium

Commentaire le plus utile

Mais les nouvelles fonctions ... utilisent _rc_filter() et non _rc_filter_sys() ...

Ah... désolé. En fait, cela va plus loin que le niveau de l'API, regardez dans "system.c" et vous verrez que les appels au niveau du système libseccomp ne les propagent pas jusqu'aux fonctions au niveau de l'API. En regardant les pages de manuel, il semble que nous ne fassions aucune réclamation à propos SCMP_FLTATR_API_SYSRAWRC pour l'API de notification (voir seccomp_load(3) pour un contre-exemple).

Je vais continuer et rouvrir cela en tant que RFE puisque nous ne faisons actuellement aucune déclaration à propos de ce fonctionnement.

@drakenclimber Je pense qu'il s'agit de matériel v2.6.x (éventuellement v2.5.2) car je ne veux pas ralentir la version v2.5.1. Si vous pensez autrement faites le moi savoir.

Tous les 5 commentaires

Salut @alban.

Regardez SCMP_FLTATR_API_SYSRAWRC dans la page de manuel seccomp_attr_set(3) :

Un indicateur pour spécifier si libseccomp doit renvoyer les codes d'erreur système à l'appelant au lieu de la valeur par défaut -ECANCELED. Désactivé par défaut (valeur == 0).

Nous forçons -ECANCELED dans ce cas pour garantir une promesse de code de retour stable dans l'API libseccomp sur différentes versions du noyau/libc. Nous proposons le SCMP_FLTATR_API_SYSRAWRC pour les appelants qui souhaitent toujours voir le code de retour réel du noyau/libc, sachez simplement que nous ne garantissons pas un code de retour stable si vous activez cet attribut.

Je vais fermer ce problème en tant que NOTABUG, mais n'hésitez pas à continuer à en discuter ici si vous avez des questions supplémentaires. Nous pouvons rouvrir s'il semble qu'il y a un vrai problème qui doit être résolu.

Salut @pcmoore , merci pour la réponse rapide.

Nous proposons le SCMP_FLTATR_API_SYSRAWRC pour les appelants qui souhaitent toujours voir le code de retour réel du noyau/libc

Mais les nouvelles fonctions

  • seccomp_notify_receive
  • seccomp_notify_respond
  • seccomp_notify_id_valid

utilisent _rc_filter() et non _rc_filter_sys() , donc SCMP_FLTATR_API_SYSRAWRC ne devrait pas avoir d'effet, si je ne me trompe pas.

Mais les nouvelles fonctions ... utilisent _rc_filter() et non _rc_filter_sys() ...

Ah... désolé. En fait, cela va plus loin que le niveau de l'API, regardez dans "system.c" et vous verrez que les appels au niveau du système libseccomp ne les propagent pas jusqu'aux fonctions au niveau de l'API. En regardant les pages de manuel, il semble que nous ne fassions aucune réclamation à propos SCMP_FLTATR_API_SYSRAWRC pour l'API de notification (voir seccomp_load(3) pour un contre-exemple).

Je vais continuer et rouvrir cela en tant que RFE puisque nous ne faisons actuellement aucune déclaration à propos de ce fonctionnement.

@drakenclimber Je pense qu'il s'agit de matériel v2.6.x (éventuellement v2.5.2) car je ne veux pas ralentir la version v2.5.1. Si vous pensez autrement faites le moi savoir.

Merci!

Pour mémoire, j'ai trouvé la solution de contournement du côté Golang pour pouvoir distinguer ENOENT et EINTR, avec ce modèle de code :

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

Avec cela, cela semble bien fonctionner avec libseccomp-2.5.0,

Cette page vous a été utile?
0 / 5 - 0 notes