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.
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
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,
Commentaire le plus utile
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 (voirseccomp_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.